chore: impl rfc9250 DoQ client

pull/44/head
lyekumchew 2022-06-13 23:54:34 +08:00 committed by Karan Sharma
parent ea7cb3c6cd
commit 2008cd9ed9
2 changed files with 22 additions and 7 deletions

View File

@ -10,7 +10,7 @@ const (
// DefaultTCPPort specifies the default port for a DNS server connecting over TCP. // DefaultTCPPort specifies the default port for a DNS server connecting over TCP.
DefaultTCPPort = "53" DefaultTCPPort = "53"
// DefaultDOQPort specifies the default port for a DNS server connecting over DNS over QUIC. // DefaultDOQPort specifies the default port for a DNS server connecting over DNS over QUIC.
DefaultDOQPort = "784" DefaultDOQPort = "853"
UDPResolver = "udp" UDPResolver = "udp"
DOHResolver = "doh" DOHResolver = "doh"
TCPResolver = "tcp" TCPResolver = "tcp"

View File

@ -2,6 +2,7 @@ package resolvers
import ( import (
"crypto/tls" "crypto/tls"
"encoding/binary"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@ -24,7 +25,7 @@ type DOQResolver struct {
func NewDOQResolver(server string, resolverOpts Options) (Resolver, error) { func NewDOQResolver(server string, resolverOpts Options) (Resolver, error) {
return &DOQResolver{ return &DOQResolver{
tls: &tls.Config{ tls: &tls.Config{
NextProtos: []string{"doq-i02", "doq-i00", "dq", "doq"}, NextProtos: []string{"doq"},
}, },
server: server, server: server,
resolverOptions: resolverOpts, resolverOptions: resolverOpts,
@ -52,6 +53,9 @@ func (r *DOQResolver) Lookup(question dns.Question) (Response, error) {
"nameserver": r.server, "nameserver": r.server,
}).Debug("Attempting to resolve") }).Debug("Attempting to resolve")
// ref: https://www.rfc-editor.org/rfc/rfc9250.html#name-dns-message-ids
msg.Id = 0
// get the DNS Message in wire format. // get the DNS Message in wire format.
var b []byte var b []byte
b, err = msg.Pack() b, err = msg.Pack()
@ -66,12 +70,17 @@ func (r *DOQResolver) Lookup(question dns.Question) (Response, error) {
return rsp, err return rsp, err
} }
// Make a QUIC request to the DNS server with the DNS message as wire format bytes in the body. var msgLen = uint16(len(b))
_, err = stream.Write(b) var msgLenBytes = []byte{byte(msgLen >> 8), byte(msgLen & 0xFF)}
_ = stream.Close() _, err = stream.Write(msgLenBytes)
if err != nil { if err != nil {
return rsp, fmt.Errorf("send query error: %w", err) return rsp, err
} }
_, err = stream.Write(b)
if err != nil {
return rsp, err
}
err = stream.SetDeadline(time.Now().Add(r.resolverOptions.Timeout)) err = stream.SetDeadline(time.Now().Add(r.resolverOptions.Timeout))
if err != nil { if err != nil {
return rsp, err return rsp, err
@ -87,7 +96,11 @@ func (r *DOQResolver) Lookup(question dns.Question) (Response, error) {
} }
rtt := time.Since(now) rtt := time.Since(now)
err = msg.Unpack(buf) packetLen := binary.BigEndian.Uint16(buf[:2])
if packetLen != uint16(len(buf[2:])) {
return rsp, fmt.Errorf("packet length mismatch")
}
err = msg.Unpack(buf[2:])
if err != nil { if err != nil {
return rsp, err return rsp, err
} }
@ -109,6 +122,8 @@ func (r *DOQResolver) Lookup(question dns.Question) (Response, error) {
// stop iterating the searchlist. // stop iterating the searchlist.
break break
} }
_ = stream.Close()
} }
return rsp, nil return rsp, nil
} }