Skip to content

Commit 4f151a5

Browse files
committed
xtransport: improve HTTP connection reuse
Decouple the HTTP idle-pool lifetime from the keepalive config knob so connections stay warm for 90 seconds regardless, Also raise MaxIdleConns from 1 to 16 so multi-resolver setups don't re-handshake on every server rotation. Also drain the HTTP/3 transport's idle connections during rebuild, like we did with HTTP/2.
1 parent ff90a55 commit 4f151a5

1 file changed

Lines changed: 13 additions & 4 deletions

File tree

dnscrypt-proxy/xtransport.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ const (
3939
DefaultBootstrapResolver = "9.9.9.9:53"
4040
DefaultKeepAlive = 5 * time.Second
4141
DefaultTimeout = 30 * time.Second
42+
DefaultIdleConnTimeout = 90 * time.Second
43+
DefaultMaxIdleConns = 16
4244
ResolverReadTimeout = 5 * time.Second
4345
SystemResolverIPTTL = 12 * time.Hour
4446
MinResolverIPTTL = 4 * time.Hour
@@ -222,12 +224,15 @@ func (xTransport *XTransport) rebuildTransport() {
222224
if xTransport.transport != nil {
223225
xTransport.transport.CloseIdleConnections()
224226
}
227+
if xTransport.h3Transport != nil {
228+
xTransport.h3Transport.CloseIdleConnections()
229+
}
225230
timeout := xTransport.timeout
226231
transport := &http.Transport{
227232
DisableKeepAlives: false,
228233
DisableCompression: true,
229-
MaxIdleConns: 1,
230-
IdleConnTimeout: xTransport.keepAlive,
234+
MaxIdleConns: DefaultMaxIdleConns,
235+
IdleConnTimeout: DefaultIdleConnTimeout,
231236
ResponseHeaderTimeout: timeout,
232237
ExpectContinueTimeout: timeout,
233238
MaxResponseHeaderBytes: 4096,
@@ -258,7 +263,7 @@ func (xTransport *XTransport) rebuildTransport() {
258263

259264
dial := func(address string) (net.Conn, error) {
260265
if xTransport.proxyDialer == nil {
261-
dialer := &net.Dialer{Timeout: timeout, KeepAlive: timeout, DualStack: true}
266+
dialer := &net.Dialer{Timeout: timeout, KeepAlive: xTransport.keepAlive, DualStack: true}
262267
return dialer.DialContext(ctx, network, address)
263268
}
264269
return (*xTransport.proxyDialer).Dial(network, address)
@@ -284,6 +289,11 @@ func (xTransport *XTransport) rebuildTransport() {
284289

285290
clientCreds := xTransport.tlsClientCreds
286291

292+
// ServerName must stay empty: crypto/tls and quic-go both derive SNI from the
293+
// request URL host on a per-connection clone. For DoH stamps that connect to an
294+
// IP while presenting a different cert name, the URL host is set to the stamp's
295+
// ProviderName, so the right SNI is used automatically. Setting ServerName here
296+
// would override that for every host sharing this transport.
287297
tlsClientConfig := tls.Config{}
288298
certPool, certPoolErr := x509.SystemCertPool()
289299

@@ -417,7 +427,6 @@ func (xTransport *XTransport) rebuildTransport() {
417427
}
418428
continue
419429
}
420-
tlsCfg.ServerName = host
421430
conn, err := quic.DialEarly(ctx, udpConn, udpAddr, tlsCfg, cfg)
422431
if err != nil {
423432
udpConn.Close()

0 commit comments

Comments
 (0)