author | Alberto Bertogli
<albertito@blitiri.com.ar> 2021-06-12 14:18:17 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2021-06-12 14:23:02 UTC |
parent | 900fbffe9a08268130519d24666518d1d859fa5c |
internal/httpserver/server.go | +25 | -1 |
tests/minidns.go | +8 | -2 |
diff --git a/internal/httpserver/server.go b/internal/httpserver/server.go index b9205dd..380445f 100644 --- a/internal/httpserver/server.go +++ b/internal/httpserver/server.go @@ -115,7 +115,7 @@ func (s *Server) resolveDoH(tr *trace.Trace, w http.ResponseWriter, dnsQuery []b tr.Question(r.Question) // Do the DNS request, get the reply. - fromUp, err := dns.Exchange(r, s.Upstream) + fromUp, err := exchange(tr, r, s.Upstream) if err != nil { err = tr.Errorf("dns exchange error: %v", err) http.Error(w, err.Error(), http.StatusFailedDependency) @@ -143,3 +143,27 @@ func (s *Server) resolveDoH(tr *trace.Trace, w http.ResponseWriter, dnsQuery []b w.WriteHeader(http.StatusOK) w.Write(packed) } + +func exchange(tr *trace.Trace, r *dns.Msg, addr string) (*dns.Msg, error) { + reply, err := dns.Exchange(r, addr) + if err == nil && !reply.Truncated { + tr.Printf("UDP exchange successful") + return reply, err + } + + // If we had issues over UDP, or the message was truncated, retry over + // TCP. We don't try beyond that. + if err != nil { + tr.Printf("error on UDP exchange: %v", err) + } else if reply.Truncated { + tr.Printf("UDP exchange returned truncated reply: %v", reply.MsgHdr) + } + tr.Printf("retrying on TCP") + + c := &dns.Client{ + Net: "tcp", + } + + reply, _, err = c.Exchange(r, addr) + return reply, err +} diff --git a/tests/minidns.go b/tests/minidns.go index 2a6b80a..14b1eaf 100644 --- a/tests/minidns.go +++ b/tests/minidns.go @@ -109,7 +109,7 @@ func (m *miniDNS) listenAndServeUDP(addr string) { continue } q := msg.Questions[0] - log.Infof("%v/%-5d Q: %s %s %s", + log.Infof("[UDP] %v/%-5d Q: %s %s %s", addr, msg.ID, q.Name, q.Type, q.Class) reply := m.handle(msg) @@ -117,6 +117,12 @@ func (m *miniDNS) listenAndServeUDP(addr string) { if err != nil { log.Fatalf("error packing reply: %v", err) } + if len(rbuf) > 512 { + log.Infof("truncating UDP response of %v bytes", len(rbuf)) + reply.Truncated = true + reply.Answers = nil + rbuf, err = reply.Pack() + } conn.WriteTo(rbuf, addr) } @@ -151,7 +157,7 @@ func (m *miniDNS) listenAndServeTCP(addr string) { continue } q := msg.Questions[0] - log.Infof("%v/%-5d Q: %s %s %s", + log.Infof("[TCP] %v/%-5d Q: %s %s %s", addr, msg.ID, q.Name, q.Type, q.Class) reply := m.handle(msg)