From c80dd5d738077a53989ddd7e155f685d0e23f1cb Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Tue, 19 Mar 2024 14:44:36 +0800 Subject: [PATCH] chore: retry DNS over TCP when receive a truncated UDP response https://github.com/MetaCubeX/mihomo/issues/1117 --- dns/client.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/dns/client.go b/dns/client.go index 95f0f29b..fc76c124 100644 --- a/dns/client.go +++ b/dns/client.go @@ -12,6 +12,7 @@ import ( "github.com/metacubex/mihomo/component/dialer" "github.com/metacubex/mihomo/component/resolver" C "github.com/metacubex/mihomo/constant" + "github.com/metacubex/mihomo/log" D "github.com/miekg/dns" "github.com/zhangyunhao116/fastrand" @@ -97,12 +98,22 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error) conn = tls.Client(conn, ca.GetGlobalTLSConfig(c.Client.TLSConfig)) } - msg, _, err := c.Client.ExchangeWithConn(m, &D.Conn{ + dConn := &D.Conn{ Conn: conn, UDPSize: c.Client.UDPSize, TsigSecret: c.Client.TsigSecret, TsigProvider: c.Client.TsigProvider, - }) + } + + msg, _, err := c.Client.ExchangeWithConn(m, dConn) + + // Resolvers MUST resend queries over TCP if they receive a truncated UDP response (with TC=1 set)! + if msg != nil && msg.Truncated && c.Client.Net == "" { + tcpClient := *c.Client // copy a client + tcpClient.Net = "tcp" + log.Debugln("[DNS] Truncated reply from %s:%s for %s over UDP, retrying over TCP", c.host, c.port, m.Question[0].String()) + msg, _, err = tcpClient.ExchangeWithConn(m, dConn) + } ch <- result{msg, err} }()