强化domainSpecificDNS逻辑,增加DNS后缀功能

This commit is contained in:
Alex Yang
2025-12-17 23:23:38 +08:00
parent 0f0aa76662
commit b576996ede
35 changed files with 100 additions and 691905 deletions

View File

@@ -485,8 +485,47 @@ func (s *Server) handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
return
}
// 缓存未命中,转发到上游DNS服务器
response, rtt := s.forwardDNSRequestWithCache(r, domain)
// 缓存未命中,处理DNS请求
var response *dns.Msg
var rtt time.Duration
var queryAttempts []string
// 1. 首先尝试直接查询原始域名
queryAttempts = append(queryAttempts, domain)
response, rtt = s.forwardDNSRequestWithCache(r, domain)
// 2. 如果直接查询失败且配置了prefixDomain尝试添加前缀
if (response == nil || response.Rcode != dns.RcodeSuccess) && len(s.config.PrefixDomain) > 0 {
logger.Debug("直接查询失败尝试使用prefixDomain", "domain", domain, "prefixDomain", s.config.PrefixDomain)
// 保存原始请求
originalQuestion := r.Question[0]
// 遍历所有prefixDomain尝试添加前缀
for _, prefix := range s.config.PrefixDomain {
// 构建完整域名
fullDomain := domain + "." + prefix
queryAttempts = append(queryAttempts, fullDomain)
logger.Debug("尝试查询完整域名", "fullDomain", fullDomain)
// 创建新的请求消息
newReq := r.Copy()
// 更新查询域名
newReq.Question[0] = dns.Question{
Name: fullDomain + ".", // 域名需要以点结尾
Qtype: originalQuestion.Qtype,
Qclass: originalQuestion.Qclass,
}
// 转发请求
response, rtt = s.forwardDNSRequestWithCache(newReq, fullDomain)
if response != nil && response.Rcode == dns.RcodeSuccess {
logger.Debug("使用prefixDomain查询成功", "fullDomain", fullDomain, "originalDomain", domain)
break // 找到成功的响应,退出循环
}
}
}
if response != nil {
// 如果客户端请求包含EDNS记录确保响应也包含EDNS
if opt := r.IsEdns0(); opt != nil {
@@ -693,6 +732,25 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
// DNSSEC专用服务器列表从配置中获取
dnssecServers := s.config.DNSSECUpstreamDNS
// 选择合适的上游DNS服务器列表
// 1. 首先检查是否有域名特定的DNS服务器配置
var selectedUpstreamDNS []string
var domainMatched bool
for matchStr, dnsServers := range s.config.DomainSpecificDNS {
if strings.Contains(domain, matchStr) {
selectedUpstreamDNS = dnsServers
domainMatched = true
logger.Debug("域名匹配到特定DNS服务器配置", "domain", domain, "matchStr", matchStr, "dnsServers", dnsServers)
break
}
}
// 2. 如果没有匹配的域名特定配置使用默认的上游DNS服务器
if !domainMatched {
selectedUpstreamDNS = s.config.UpstreamDNS
}
// 1. 首先尝试所有配置的上游DNS服务器
var bestResponse *dns.Msg
var bestRtt time.Duration
@@ -706,7 +764,7 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
switch s.config.QueryMode {
case "parallel":
// 并行请求模式 - 优化版:添加超时处理和快速响应返回
responses := make(chan serverResponse, len(s.config.UpstreamDNS))
responses := make(chan serverResponse, len(selectedUpstreamDNS))
var wg sync.WaitGroup
// 超时上下文
@@ -714,7 +772,7 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
defer cancel()
// 向所有上游服务器并行发送请求
for _, upstream := range s.config.UpstreamDNS {
for _, upstream := range selectedUpstreamDNS {
wg.Add(1)
go func(server string) {
defer wg.Done()
@@ -806,7 +864,7 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
case "loadbalance":
// 负载均衡模式 - 使用加权随机选择算法
// 1. 选择一个加权随机服务器
selectedServer := s.selectWeightedRandomServer(s.config.UpstreamDNS)
selectedServer := s.selectWeightedRandomServer(selectedUpstreamDNS)
if selectedServer != "" {
response, rtt, err := s.resolver.Exchange(r, selectedServer)
if err == nil && response != nil {
@@ -874,7 +932,7 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
case "fastest-ip":
// 最快的IP地址模式 - 使用TCP连接速度测量选择最快服务器
// 1. 选择最快的服务器
fastestServer := s.selectFastestServer(s.config.UpstreamDNS)
fastestServer := s.selectFastestServer(selectedUpstreamDNS)
if fastestServer != "" {
response, rtt, err := s.resolver.Exchange(r, fastestServer)
if err == nil && response != nil {
@@ -941,11 +999,11 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
default:
// 默认使用并行请求模式
responses := make(chan serverResponse, len(s.config.UpstreamDNS))
responses := make(chan serverResponse, len(selectedUpstreamDNS))
var wg sync.WaitGroup
// 向所有上游服务器并行发送请求
for _, upstream := range s.config.UpstreamDNS {
for _, upstream := range selectedUpstreamDNS {
wg.Add(1)
go func(server string) {
defer wg.Done()
@@ -1020,7 +1078,8 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
}
// 2. 当启用DNSSEC且没有找到带DNSSEC的响应时向DNSSEC专用服务器发送请求
if s.config.EnableDNSSEC && !hasDNSSECResponse {
// 但如果域名匹配了domainSpecificDNS配置则不使用DNSSEC专用服务器只使用指定的DNS服务器
if s.config.EnableDNSSEC && !hasDNSSECResponse && !domainMatched {
logger.Debug("向DNSSEC专用服务器发送请求", "domain", domain)
// 增加DNSSEC查询计数
@@ -1098,7 +1157,6 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
// 优先使用DNSSEC专用服务器的响应尤其是带有DNSSEC记录的
if containsDNSSEC {
// 即使之前有最佳响应也优先使用DNSSEC专用服务器的DNSSEC响应
bestResponse = resp.response
bestRtt = resp.rtt
hasBestResponse = true
@@ -1159,7 +1217,6 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
// 优先使用DNSSEC专用服务器的响应尤其是带有DNSSEC记录的
if containsDNSSEC {
// 即使之前有最佳响应也优先使用DNSSEC专用服务器的DNSSEC响应
bestResponse = response
bestRtt = rtt
hasBestResponse = true
@@ -1220,7 +1277,6 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
// 优先使用DNSSEC专用服务器的响应尤其是带有DNSSEC记录的
if containsDNSSEC {
// 即使之前有最佳响应也优先使用DNSSEC专用服务器的DNSSEC响应
bestResponse = response
bestRtt = rtt
hasBestResponse = true
@@ -1279,7 +1335,6 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
// 优先使用DNSSEC专用服务器的响应尤其是带有DNSSEC记录的
if containsDNSSEC {
// 即使之前有最佳响应也优先使用DNSSEC专用服务器的DNSSEC响应
bestResponse = response
bestRtt = rtt
hasBestResponse = true