This commit is contained in:
Alex Yang
2026-04-05 03:19:53 +08:00
parent 2c0c1733d9
commit d3e22a2631
+52 -56
View File
@@ -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