Skip to content

Commit 2e5277d

Browse files
committed
internal/dns: retry over TCP upon truncated response
This fixes resolving login.tailscale.com as of the time of writing, the first DNS name for which I noticed an error in 7 years of router7.
1 parent 52826d6 commit 2e5277d

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

internal/dns/dns.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ type Server struct {
4646
Mux *dns.ServeMux
4747

4848
client *dns.Client
49+
tcpClient *dns.Client
4950
domain string
5051
sometimes *rate.Limiter
5152
prom struct {
@@ -69,9 +70,10 @@ func NewServer(addr, domain string) *Server {
6970
hostname, _ := os.Hostname()
7071
ip, _, _ := net.SplitHostPort(addr)
7172
server := &Server{
72-
Mux: dns.NewServeMux(),
73-
client: &dns.Client{},
74-
domain: domain,
73+
Mux: dns.NewServeMux(),
74+
client: &dns.Client{},
75+
tcpClient: &dns.Client{Net: "tcp"},
76+
domain: domain,
7577
upstream: []string{
7678
// https://developers.google.com/speed/public-dns/docs/using#google_public_dns_ip_addresses
7779
"8.8.8.8:53",
@@ -424,6 +426,17 @@ func (s *Server) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
424426
}
425427
continue // fall back to next-slower upstream
426428
}
429+
if in.Truncated {
430+
// Truncated response (exceeds UDP packet size), retry over TCP:
431+
// https://www.rfc-editor.org/rfc/rfc2181#section-9
432+
in, _, err = s.tcpClient.Exchange(r, u)
433+
if err != nil {
434+
if s.sometimes.Allow() {
435+
log.Printf("resolving %v failed: %v", r.Question, err)
436+
}
437+
continue // fall back to next-slower upstream
438+
}
439+
}
427440
w.WriteMsg(in)
428441
if idx > 0 {
429442
// re-order this upstream to the front of s.upstream.

0 commit comments

Comments
 (0)