1 parent
cc7466823b
commit
e8c5b414d9
44 files changed
+7649
-344
No files matched your search
@@ -210,7 +210,16 @@ func (s *Server) Stop(ctx context.Context) error {
|
||||
}
|
||||
var errs []error
|
||||
for _, l := range ls {
|
||||
if err := l.close(); err != nil {
|
||||
if err := l.close(); err != nil && !errors.Is(err, net.ErrClosed) {
|
||||
// The DoH listener is closed TWICE, by two different owners: once
|
||||
// from this list, and once by http.Server.Shutdown, which tracks
|
||||
// the very same net.Listener because serveDoH hands it to
|
||||
// srv.Serve. Whichever of the two lost that race made an
|
||||
// otherwise clean Stop return "use of closed network
|
||||
// connection" at random, so a clean shutdown looked like a
|
||||
// failed one. Closing an already-closed listener is not a
|
||||
// failure; only a real close error is. Pinned by
|
||||
// TestStopIsIdempotent.
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
@@ -583,9 +592,6 @@ func (s *Server) serveDoH(ctx context.Context, cfg *config.Config) error {
|
||||
|
||||
const contentTypeDNS = "application/dns-message"
|
||||
|
||||
// maxGETResponse bounds a DoH GET response so no intermediary truncates it.
|
||||
const maxGETResponse = 65535
|
||||
|
||||
// doHHandler builds the RFC 8484 handler.
|
||||
func (s *Server) doHHandler(base string, allowPost bool) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -616,7 +622,18 @@ func (s *Server) doHHandler(base string, allowPost bool) http.Handler {
|
||||
}
|
||||
}
|
||||
}
|
||||
payload, err = decodeBase64URL(q.Get("dns"))
|
||||
// A DNS message is at most 65535 bytes on the wire (every section
|
||||
// carries a 16-bit length), so its base64url form cannot be
|
||||
// longer than this. POST gets the same bound from readCapped;
|
||||
// without it here an unauthenticated client could make the
|
||||
// server allocate, base64-decode and Unpack a megabyte per
|
||||
// request, where the adjacent POST path refuses at 64 KiB.
|
||||
enc := q.Get("dns")
|
||||
if len(enc) > base64.RawURLEncoding.EncodedLen(dns.MaxMsgSize) {
|
||||
writeDoHError(w, http.StatusRequestEntityTooLarge, "dns parameter too large")
|
||||
return
|
||||
}
|
||||
payload, err = decodeBase64URL(enc)
|
||||
if err != nil {
|
||||
writeDoHError(w, http.StatusBadRequest, "malformed dns parameter")
|
||||
return
|
||||
@@ -656,7 +673,11 @@ func (s *Server) doHHandler(base string, allowPost bool) http.Handler {
|
||||
if res.Drop || res.Msg == nil {
|
||||
// A dropped query still needs a body: unlike UDP, this is a
|
||||
// well-formed HTTP exchange, so hanging up would read as a
|
||||
// transport error rather than a policy decision.
|
||||
// transport error rather than a policy decision. It is still a
|
||||
// drop, so it counts as one here too — the UDP and TCP paths bump
|
||||
// "dropped" in the same position, and the DoH path used to be
|
||||
// the only one that did not.
|
||||
s.bump("doh", "dropped")
|
||||
res.Msg = new(dns.Msg)
|
||||
res.Msg.SetRcode(m, dns.RcodeSuccess)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user