diff --git a/dnscrypt-proxy/dnsutils.go b/dnscrypt-proxy/dnsutils.go index 60da3082..548d19ce 100644 --- a/dnscrypt-proxy/dnsutils.go +++ b/dnscrypt-proxy/dnsutils.go @@ -209,6 +209,21 @@ func updateTTL(msg *dns.Msg, expiration time.Time) { } } +func hasEDNS0Padding(packet []byte) (bool, error) { + msg := dns.Msg{} + if err := msg.Unpack(packet); err != nil { + return false, err + } + if edns0 := msg.IsEdns0(); edns0 != nil { + for _, option := range edns0.Option { + if option.Option() == dns.EDNS0PADDING { + return true, nil + } + } + } + return false, nil +} + func addEDNS0PaddingIfNoneFound(msg *dns.Msg, unpaddedPacket []byte, paddingLen int) ([]byte, error) { edns0 := msg.IsEdns0() if edns0 == nil { diff --git a/dnscrypt-proxy/local-doh.go b/dnscrypt-proxy/local-doh.go index 344d4e02..31a660c6 100644 --- a/dnscrypt-proxy/local-doh.go +++ b/dnscrypt-proxy/local-doh.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "net" "net/http" + "strings" "time" "github.com/jedisct1/dlog" @@ -47,6 +48,11 @@ func (handler localDoHHandler) ServeHTTP(writer http.ResponseWriter, request *ht dlog.Warnf("No body in a local DoH query") return } + hasEDNS0Padding, err := hasEDNS0Padding(packet) + if err != nil { + writer.WriteHeader(400) + return + } response := proxy.processIncomingQuery(proxy.serversInfo.getOne(), "local_doh", proxy.mainProto, packet, &xClientAddr, nil, start) if len(response) == 0 { writer.WriteHeader(500) @@ -60,13 +66,19 @@ func (handler localDoHHandler) ServeHTTP(writer http.ResponseWriter, request *ht responseLen := len(response) paddedLen := dohPaddedLen(responseLen) padLen := paddedLen - responseLen - paddedResponse, err := addEDNS0PaddingIfNoneFound(&msg, response, padLen) - if err != nil { - return + if hasEDNS0Padding { + response, err = addEDNS0PaddingIfNoneFound(&msg, response, padLen) + if err != nil { + dlog.Critical(err) + return + } + } else { + pad := strings.Repeat("X", padLen) + writer.Header().Set("X-Pad", pad) } writer.Header().Set("Content-Type", dataType) writer.WriteHeader(200) - writer.Write(paddedResponse) + writer.Write(response) } func (proxy *Proxy) localDoHListener(acceptPc *net.TCPListener) {