diff --git a/dnscrypt-proxy/serversInfo.go b/dnscrypt-proxy/serversInfo.go index 64f39cbb..f0637be8 100644 --- a/dnscrypt-proxy/serversInfo.go +++ b/dnscrypt-proxy/serversInfo.go @@ -390,6 +390,29 @@ func dohTestPacket(msgID uint16) []byte { return body } +func dohNXTestPacket(msgID uint16) []byte { + msg := dns.Msg{} + qName := make([]byte, 16) + charset := "abcdefghijklmnopqrstuvwxyz" + for i := range qName { + qName[i] = charset[rand.Intn(len(charset))] + } + msg.SetQuestion(string(qName)+".dnscrypt.test.", dns.TypeNS) + msg.Id = msgID + msg.MsgHdr.RecursionDesired = true + msg.SetEdns0(uint16(MaxDNSPacketSize), false) + ext := new(dns.EDNS0_PADDING) + ext.Padding = make([]byte, 16) + crypto_rand.Read(ext.Padding) + edns0 := msg.IsEdns0() + edns0.Option = append(edns0.Option, ext) + body, err := msg.Pack() + if err != nil { + dlog.Fatal(err) + } + return body +} + func fetchDoHServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, isNew bool) (ServerInfo, error) { // If an IP has been provided, use it forever. // Or else, if the fallback server and the DoH server are operated @@ -424,6 +447,7 @@ func fetchDoHServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, isN } dlog.Debugf("Server [%s] doesn't appear to support POST; falling back to GET requests", name) } + body = dohNXTestPacket(0xcafe) serverResponse, tls, rtt, err := proxy.xTransport.DoHQuery(useGet, url, body, proxy.timeout) if err != nil { return ServerInfo{}, err @@ -431,6 +455,13 @@ func fetchDoHServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, isN if tls == nil || !tls.HandshakeComplete { return ServerInfo{}, errors.New("TLS handshake failed") } + msg := dns.Msg{} + if err := msg.Unpack(serverResponse); err != nil { + return ServerInfo{}, err + } + if msg.Rcode != dns.RcodeNameError { + dlog.Criticalf("[%s] may be a lying resolver", name) + } protocol := tls.NegotiatedProtocol if len(protocol) == 0 { protocol = "h1"