From 455e5de74de2ad67b18f77e956c2988b950704a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sun, 29 Jun 2025 19:23:26 +0800 Subject: [PATCH] Fixed DoH server recover from conn freezes --- dns/transport/https.go | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/dns/transport/https.go b/dns/transport/https.go index a13d9116..f02fd330 100644 --- a/dns/transport/https.go +++ b/dns/transport/https.go @@ -3,11 +3,15 @@ package transport import ( "bytes" "context" + "errors" "io" "net" "net/http" "net/url" + "os" "strconv" + "sync" + "time" "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/common/dialer" @@ -39,11 +43,13 @@ func RegisterHTTPS(registry *dns.TransportRegistry) { type HTTPSTransport struct { dns.TransportAdapter - logger logger.ContextLogger - dialer N.Dialer - destination *url.URL - headers http.Header - transport *http.Transport + logger logger.ContextLogger + dialer N.Dialer + destination *url.URL + headers http.Header + transportAccess sync.Mutex + transport *http.Transport + transportResetAt time.Time } func NewHTTPS(ctx context.Context, logger log.ContextLogger, tag string, options option.RemoteHTTPSDNSServerOptions) (adapter.DNSTransport, error) { @@ -161,12 +167,33 @@ func (t *HTTPSTransport) Start(stage adapter.StartStage) error { } func (t *HTTPSTransport) Close() error { + t.transportAccess.Lock() + defer t.transportAccess.Unlock() t.transport.CloseIdleConnections() t.transport = t.transport.Clone() return nil } func (t *HTTPSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) { + startAt := time.Now() + response, err := t.exchange(ctx, message) + if err != nil { + if errors.Is(err, os.ErrDeadlineExceeded) { + t.transportAccess.Lock() + defer t.transportAccess.Unlock() + if t.transportResetAt.After(startAt) { + return nil, err + } + t.transport.CloseIdleConnections() + t.transport = t.transport.Clone() + t.transportResetAt = time.Now() + } + return nil, err + } + return response, nil +} + +func (t *HTTPSTransport) exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) { exMessage := *message exMessage.Id = 0 exMessage.Compress = true