From 33c8027e0a572a1ebd66d71e41a47380c1973d8a Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Thu, 2 Feb 2023 19:24:40 +0100 Subject: [PATCH] Use a custom dialer for HTTP/3 --- dnscrypt-proxy/xtransport.go | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/dnscrypt-proxy/xtransport.go b/dnscrypt-proxy/xtransport.go index 402ea8ab..e365fa27 100644 --- a/dnscrypt-proxy/xtransport.go +++ b/dnscrypt-proxy/xtransport.go @@ -22,8 +22,9 @@ import ( "github.com/jedisct1/dlog" stamps "github.com/jedisct1/go-dnsstamps" - "github.com/quic-go/quic-go/http3" "github.com/miekg/dns" + "github.com/quic-go/quic-go" + "github.com/quic-go/quic-go/http3" "golang.org/x/net/http2" netproxy "golang.org/x/net/proxy" ) @@ -155,7 +156,7 @@ func (xTransport *XTransport) rebuildTransport() { ipOnly = "[" + cachedIP.String() + "]" } } else { - dlog.Debugf("[%s] IP address was not cached", host) + dlog.Debugf("[%s] IP address was not cached in DialContext", host) } addrStr = ipOnly + ":" + strconv.Itoa(port) if xTransport.proxyDialer == nil { @@ -223,7 +224,31 @@ func (xTransport *XTransport) rebuildTransport() { } xTransport.transport = transport if xTransport.http3 { - h3Transport := &http3.RoundTripper{DisableCompression: true, TLSClientConfig: &tlsClientConfig} + h3Transport := &http3.RoundTripper{DisableCompression: true, TLSClientConfig: &tlsClientConfig, Dial: func(ctx context.Context, addrStr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) { + dlog.Debugf("Dialing for H3: [%v]", addrStr) + host, port := ExtractHostAndPort(addrStr, stamps.DefaultPort) + ipOnly := host + cachedIP, _ := xTransport.loadCachedIP(host) + if cachedIP != nil { + if ipv4 := cachedIP.To4(); ipv4 != nil { + ipOnly = ipv4.String() + } else { + ipOnly = "[" + cachedIP.String() + "]" + } + } else { + dlog.Debugf("[%s] IP address was not cached in H3 DialContext", host) + } + addrStr = ipOnly + ":" + strconv.Itoa(port) + udpAddr, err := net.ResolveUDPAddr("udp", addrStr) + if err != nil { + return nil, err + } + udpConn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0}) + if err != nil { + return nil, err + } + return quic.DialEarlyContext(ctx, udpConn, udpAddr, host, tlsCfg, cfg) + }} xTransport.h3Transport = h3Transport } } @@ -401,7 +426,8 @@ func (xTransport *XTransport) Fetch( hasAltSupport := false if xTransport.h3Transport != nil { xTransport.altSupport.RLock() - altPort, hasAltSupport := xTransport.altSupport.cache[url.Host] + var altPort uint16 + altPort, hasAltSupport = xTransport.altSupport.cache[url.Host] xTransport.altSupport.RUnlock() if hasAltSupport { if int(altPort) == port { @@ -456,6 +482,7 @@ func (xTransport *XTransport) Fetch( err = errors.New(resp.Status) } } else { + dlog.Debugf("HTTP client error: [%v] - closing idle H3 connections", err) (*xTransport.transport).CloseIdleConnections() } statusCode := 503 @@ -496,6 +523,7 @@ func (xTransport *XTransport) Fetch( } xTransport.altSupport.Lock() xTransport.altSupport.cache[url.Host] = altPort + dlog.Debugf("Caching altPort for [%v]", url.Host) xTransport.altSupport.Unlock() } }