Repository navigation
ipn/ipnlocal: don't panic on an over-long name in the peerAPI DNS debug mode - #21308
Merged
Merged
Conversation
…ug mode dnsQueryForName builds the query for GET /dns-query?q=<name>, the peerAPI's interactive debug mode. The name comes from the peer's query string and the only thing done to it is appending a trailing dot, but the query is built with dnsmessage.MustNewName, which panics as soon as the name is longer than 255 bytes. The panic happens before the query reaches the resolver, so the nameAllowed filter never gets a say and only sourceAllowed has to be true: any of the user's own untagged devices, and any peer an extension hook lets through, such as a client using this node as an exit node with DNS proxying allowed. http.Server recovers it, so tailscaled survives, but the peer's connection is dropped instead of answered and the node logs a panic trace per request. Just under the limit the name was mishandled too: a 255-byte name is accepted by NewName but rejected by Question when it packs the name, and that error was dropped, so Finish returned a well-formed query with no question in it which was then handed to the resolver. Have dnsQueryForName use NewName, check the error from Question, and return the error from Finish. handleDNSQuery turns a name it cannot build a query for into the 400 it already uses for the other malformed-request cases. Fixes tailscale#21307 Change-Id: I7c1a4b7e4f9a1d2c3b5e8f0a6d4c2b9e1f3a7d50 Signed-off-by: leoca <[email protected]>
bradfitz
approved these changes
Sep 16, 2026
Dev-next-gen
added a commit
to Dev-next-gen/Dev-next-gen
that referenced
this pull request
Sep 16, 2026
tailscale/tailscale#21308, merged today. Unrelated to the embargoed net/packet work.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
dnsQueryForNamebuilds the query forGET /dns-query?q=<name>, the peerAPI'sinteractive debug mode for humans. I noticed the name goes from the peer's query
string into
dnsmessage.MustNewNamewith nothing done to it but appending a trailingdot, and
dnsmessage.NewNamefails once the name is longer than 255 bytes, so a peerthat types a long enough name panics the handler:
The panic happens before the query reaches the resolver, so the
nameAllowedfilterfrom
isPeerAPIDNSAllowednever gets a say and onlysourceAllowedhas to be true:the user's own untagged devices, and any peer an extension hook lets through, such as
a client using this node as an exit node with DNS proxying allowed.
http.Serverrecovers it, so tailscaled itself survives; the peer's connection is dropped instead
of answered and the node logs a panic trace per request.
Just under the limit the name was mishandled too. A 255-byte name is accepted by
NewNamebut rejected byQuestionwhen it packs the name, and that error wasdropped, so
b.Finish()returned a well-formed query with no question in it, whichwas then handed to the resolver.
dnsQueryForNamenow usesNewName, checks the error fromQuestion, and returnsthe error from
Finish;handleDNSQueryturns a name it cannot build a query forinto the 400 it already uses for the other malformed-request cases. The only caller is
the
?q=debug path, so nothing outside this file changes shape.The test is built on the existing
TestPeerAPIPrettyReplyCNAMEharness so it goesthrough the real handler. On
mainit panics atpeerapi.go:934; with the fix it getsa 400. The whole package passes:
Fixes #21307
Found by a defect-hunting pipeline I build and run (Dev-next-gen), using Claude Code with Anthropic's Claude Opus 5.