From aa101d9dc2149781f134f30ed4e636a824b1a60a Mon Sep 17 00:00:00 2001 From: yuhan6665 <1588741+yuhan6665@users.noreply.github.com> Date: Wed, 28 Feb 2024 21:35:35 -0500 Subject: [PATCH] Doq (#3073) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: change ALPN of DNS over QUIC * Fix: length of DNS over QUIC (#1888) --------- Co-authored-by: 秋のかえで --- app/dns/nameserver_quic.go | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/app/dns/nameserver_quic.go b/app/dns/nameserver_quic.go index 9e702564..89bb4aaa 100644 --- a/app/dns/nameserver_quic.go +++ b/app/dns/nameserver_quic.go @@ -1,7 +1,9 @@ package dns import ( + "bytes" "context" + "encoding/binary" "net/url" "sync" "sync/atomic" @@ -24,7 +26,7 @@ import ( // NextProtoDQ - During connection establishment, DNS/QUIC support is indicated // by selecting the ALPN token "dq" in the crypto handshake. -const NextProtoDQ = "doq-i00" +const NextProtoDQ = "doq" const handshakeTimeout = time.Second * 8 @@ -194,13 +196,18 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP return } + dnsReqBuf := buf.New() + binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len())) + dnsReqBuf.Write(b.Bytes()) + b.Release() + conn, err := s.openStream(dnsCtx) if err != nil { newError("failed to open quic connection").Base(err).AtError().WriteToLog() return } - _, err = conn.Write(b.Bytes()) + _, err = conn.Write(dnsReqBuf.Bytes()) if err != nil { newError("failed to send query").Base(err).AtError().WriteToLog() return @@ -210,9 +217,21 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP respBuf := buf.New() defer respBuf.Release() - n, err := respBuf.ReadFrom(conn) + n, err := respBuf.ReadFullFrom(conn, 2) if err != nil && n == 0 { - newError("failed to read response").Base(err).AtError().WriteToLog() + newError("failed to read response length").Base(err).AtError().WriteToLog() + return + } + var length int16 + err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length) + if err != nil { + newError("failed to parse response length").Base(err).AtError().WriteToLog() + return + } + respBuf.Clear() + n, err = respBuf.ReadFullFrom(conn, int32(length)) + if err != nil && n == 0 { + newError("failed to read response length").Base(err).AtError().WriteToLog() return }