From d3e22a2631de0f8e2e594e6cbb105d425236585c Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Sun, 5 Apr 2026 03:19:53 +0800 Subject: [PATCH] update --- dns/server.go | 108 ++++++++++++++++++++++++-------------------------- 1 file changed, 52 insertions(+), 56 deletions(-) diff --git a/dns/server.go b/dns/server.go index 7f2e826..ed3f7fa 100644 --- a/dns/server.go +++ b/dns/server.go @@ -1188,38 +1188,34 @@ func (s *Server) updateDNSSECServerMap() { } } -// forwardDNSRequestWithCache 转发DNS请求到上游服务器并返回响应 +// forwardDNSRequestWithCache 转发 DNS 请求到上游服务器并返回响应 func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg, time.Duration, string, string) { - // 始终支持EDNS + // 始终支持 EDNS var udpSize uint16 = 4096 var doFlag bool = s.config.EnableDNSSEC - // 检查域名是否匹配不验证DNSSEC的模式 + // 检查域名是否匹配不验证 DNSSEC 的模式 noDNSSEC := false for _, pattern := range s.config.NoDNSSECDomains { if strings.Contains(domain, pattern) { noDNSSEC = true doFlag = false - logger.Debug("域名匹配到不验证DNSSEC的模式", "domain", domain, "pattern", pattern) + logger.Debug("域名匹配到不验证 DNSSEC 的模式", "domain", domain, "pattern", pattern) break } } - // 检查客户端请求是否包含EDNS记录 + // 检查客户端请求是否包含 EDNS 记录 if opt := r.IsEdns0(); opt != nil { - // 保留客户端的UDP缓冲区大小 + // 保留客户端的 UDP 缓冲区大小 udpSize = opt.UDPSize() - // 移除现有的EDNS记录,以便重新添加 - for i := range r.Extra { - if r.Extra[i] == opt { - r.Extra = append(r.Extra[:i], r.Extra[i+1:]...) - break - } - } } - // 添加EDNS记录,设置适当的UDPSize和DO标志 - r.SetEdns0(udpSize, doFlag) + // 创建请求的副本,避免修改原始请求 + query := r.Copy() + + // 在副本上添加 EDNS 记录,设置适当的 UDPSize 和 DO 标志 + query.SetEdns0(udpSize, doFlag) // DNSSEC专用服务器列表,从配置中获取 dnssecServers := s.config.DNSSECUpstreamDNS @@ -1284,7 +1280,7 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg // 使用配置中的超时时间 defaultTimeout := time.Duration(s.config.QueryTimeout) * time.Millisecond -logger.Debug("并行查询超时设置", "domain", r.Question[0].Name, "defaultTimeout", defaultTimeout, "queryTimeout 配置", s.config.QueryTimeout) + logger.Debug("并行查询超时设置", "domain", r.Question[0].Name, "defaultTimeout", defaultTimeout, "queryTimeout 配置", s.config.QueryTimeout) // 根据查询模式处理请求 switch s.config.QueryMode { @@ -1307,7 +1303,7 @@ logger.Debug("并行查询超时设置", "domain", r.Question[0].Name, "defaultT client.Timeout = defaultTimeout // 使用配置的超时时间 // 发送请求并获取响应,确保服务器地址包含端口号 - response, rtt, err := client.Exchange(r, normalizeDNSServerAddress(server)) + response, rtt, err := client.Exchange(query, normalizeDNSServerAddress(server)) responses <- serverResponse{response, rtt, server, err} // 将客户端实例放回池中(不重置 Timeout,因为下次使用时会重新设置) @@ -1411,7 +1407,7 @@ logger.Debug("并行查询超时设置", "domain", r.Question[0].Name, "defaultT client.Timeout = defaultTimeout // 只向一个服务器发送请求 - response, rtt, err := client.Exchange(r, normalizeDNSServerAddress(fastestServer)) + response, rtt, err := client.Exchange(query, normalizeDNSServerAddress(fastestServer)) // 将客户端实例放回池中 s.clientPool.Put(client) @@ -1504,7 +1500,7 @@ logger.Debug("并行查询超时设置", "domain", r.Question[0].Name, "defaultT go func(server string) { defer wg.Done() - // 创建带有超时的resolver + // 创建带有超时的 resolver client := &dns.Client{ Net: s.resolver.Net, UDPSize: s.resolver.UDPSize, @@ -1512,7 +1508,7 @@ logger.Debug("并行查询超时设置", "domain", r.Question[0].Name, "defaultT } // 发送请求并获取响应,确保服务器地址包含端口号 - response, rtt, err := client.Exchange(r, normalizeDNSServerAddress(server)) + response, rtt, err := client.Exchange(query, normalizeDNSServerAddress(server)) responses <- serverResponse{response, rtt, server, err} }(upstream) } @@ -1568,44 +1564,44 @@ logger.Debug("并行查询超时设置", "domain", r.Question[0].Name, "defaultT } // 简化的快速返回逻辑:找到第一个成功响应或更快的响应 - // 对于不验证 DNSSEC 的域名,直接返回第一个成功响应(只发送一次) - if noDNSSEC && !bestResponseSent { - // 不验证 DNSSEC 的域名:返回第一个包含有效记录的成功响应 - if fastestResponse == nil || resp.rtt < fastestRtt { - // 检查响应是否包含有效记录 - hasValidRecords := false - if len(resp.response.Answer) > 0 { - hasValidRecords = true - } else if len(resp.response.Ns) > 0 { - hasValidRecords = true - } else if len(resp.response.Extra) > 0 { - for _, rr := range resp.response.Extra { - if rr.Header().Rrtype != dns.TypeOPT { - hasValidRecords = true - break + // 对于不验证 DNSSEC 的域名,直接返回第一个成功响应(只发送一次) + if noDNSSEC && !bestResponseSent { + // 不验证 DNSSEC 的域名:返回第一个包含有效记录的成功响应 + if fastestResponse == nil || resp.rtt < fastestRtt { + // 检查响应是否包含有效记录 + hasValidRecords := false + if len(resp.response.Answer) > 0 { + hasValidRecords = true + } else if len(resp.response.Ns) > 0 { + hasValidRecords = true + } else if len(resp.response.Extra) > 0 { + for _, rr := range resp.response.Extra { + if rr.Header().Rrtype != dns.TypeOPT { + hasValidRecords = true + break + } } } - } - // 只有包含有效记录才返回 - if hasValidRecords { - fastestResponse = resp.response - fastestRtt = resp.rtt - fastestServer = resp.server - fastestDnssecServer = dnssecServerForResponse - fastestHasDnssec = false + // 只有包含有效记录才返回 + if hasValidRecords { + fastestResponse = resp.response + fastestRtt = resp.rtt + fastestServer = resp.server + fastestDnssecServer = dnssecServerForResponse + fastestHasDnssec = false - // 立即发送结果,快速返回(只发送一次) - resultChan <- struct { - response *dns.Msg - rtt time.Duration - usedServer string - usedDnssecServer string - }{fastestResponse, fastestRtt, fastestServer, fastestDnssecServer} - bestResponseSent = true + // 立即发送结果,快速返回(只发送一次) + resultChan <- struct { + response *dns.Msg + rtt time.Duration + usedServer string + usedDnssecServer string + }{fastestResponse, fastestRtt, fastestServer, fastestDnssecServer} + bestResponseSent = true + } } - } - } else if resp.response.Rcode == dns.RcodeSuccess && !bestResponseSent { + } else if resp.response.Rcode == dns.RcodeSuccess && !bestResponseSent { // 优先选择带有DNSSEC的响应 if containsDNSSEC { // 如果这是第一个DNSSEC响应,或者比当前最快的DNSSEC响应更快 @@ -1815,13 +1811,13 @@ logger.Debug("并行查询超时设置", "domain", r.Question[0].Name, "defaultT }, 1) go func() { - // 创建带有超时的resolver + // 创建带有超时的 resolver client := &dns.Client{ Net: s.resolver.Net, UDPSize: s.resolver.UDPSize, Timeout: defaultTimeout, } - response, rtt, err := client.Exchange(r, normalizeDNSServerAddress(selectedDnssecServer)) + response, rtt, err := client.Exchange(query, normalizeDNSServerAddress(selectedDnssecServer)) resultChan <- struct { response *dns.Msg rtt time.Duration @@ -1924,7 +1920,7 @@ logger.Debug("并行查询超时设置", "domain", r.Question[0].Name, "defaultT UDPSize: s.resolver.UDPSize, Timeout: defaultTimeout, // 使用配置的超时时间 } - resp, rtt, e := tempResolver.Exchange(r, normalizeDNSServerAddress(localServer)) + resp, rtt, e := tempResolver.Exchange(query, normalizeDNSServerAddress(localServer)) resultChan <- struct { response *dns.Msg rtt time.Duration