优化DNSSEC

This commit is contained in:
Alex Yang
2025-12-16 16:25:55 +08:00
parent 50d2b5fbdb
commit 106b869111
7 changed files with 108 additions and 195 deletions

View File

@@ -41,7 +41,7 @@ func cacheKey(qName string, qType uint16) string {
// hasDNSSECRecords 检查响应是否包含DNSSEC记录
func hasDNSSECRecords(response *dns.Msg) bool {
// 检查响应中是否包含DNSKEYRRSIG记录
// 检查响应中是否包含DNSSEC相关记录DNSKEYRRSIG、DS、NSEC、NSEC3等
for _, rr := range response.Answer {
if _, ok := rr.(*dns.DNSKEY); ok {
return true
@@ -49,6 +49,15 @@ func hasDNSSECRecords(response *dns.Msg) bool {
if _, ok := rr.(*dns.RRSIG); ok {
return true
}
if _, ok := rr.(*dns.DS); ok {
return true
}
if _, ok := rr.(*dns.NSEC); ok {
return true
}
if _, ok := rr.(*dns.NSEC3); ok {
return true
}
}
for _, rr := range response.Ns {
if _, ok := rr.(*dns.DNSKEY); ok {
@@ -57,6 +66,15 @@ func hasDNSSECRecords(response *dns.Msg) bool {
if _, ok := rr.(*dns.RRSIG); ok {
return true
}
if _, ok := rr.(*dns.DS); ok {
return true
}
if _, ok := rr.(*dns.NSEC); ok {
return true
}
if _, ok := rr.(*dns.NSEC3); ok {
return true
}
}
for _, rr := range response.Extra {
if _, ok := rr.(*dns.DNSKEY); ok {
@@ -65,6 +83,15 @@ func hasDNSSECRecords(response *dns.Msg) bool {
if _, ok := rr.(*dns.RRSIG); ok {
return true
}
if _, ok := rr.(*dns.DS); ok {
return true
}
if _, ok := rr.(*dns.NSEC); ok {
return true
}
if _, ok := rr.(*dns.NSEC3); ok {
return true
}
}
return false
}

View File

@@ -610,6 +610,21 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
var backupRtt time.Duration
var hasBackup bool
// 如果启用了DNSSEC设置DO标志请求DNSSEC记录
if s.config.EnableDNSSEC {
// 如果请求已经包含EDNS记录移除它
if opt := r.IsEdns0(); opt != nil {
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(4096, true)
}
// DNSSEC专用服务器列表从配置中获取
dnssecServers := s.config.DNSSECUpstreamDNS
@@ -623,6 +638,29 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
// 检查是否包含DNSSEC记录
containsDNSSEC := s.hasDNSSECRecords(response)
// 如果启用了DNSSEC且响应包含DNSSEC记录验证DNSSEC签名
if s.config.EnableDNSSEC && containsDNSSEC {
// 验证DNSSEC记录
signatureValid := s.verifyDNSSEC(response)
// 设置AD标志Authenticated Data
response.AuthenticatedData = signatureValid
if signatureValid {
// 更新DNSSEC验证成功计数
s.updateStats(func(stats *Stats) {
stats.DNSSECQueries++
stats.DNSSECSuccess++
})
} else {
// 更新DNSSEC验证失败计数
s.updateStats(func(stats *Stats) {
stats.DNSSECQueries++
stats.DNSSECFailed++
})
}
}
// 如果响应成功根据DNSSEC状态选择最佳响应
if response.Rcode == dns.RcodeSuccess {
// 优先选择带有DNSSEC记录的响应
@@ -694,13 +732,10 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
hasBestResponse = true
hasDNSSECResponse = true
logger.Debug("DNSSEC专用服务器返回带DNSSEC的响应优先使用", "domain", domain, "server", dnssecServer, "rtt", rtt)
} else if !hasBestResponse || hasBestResponse && !s.hasDNSSECRecords(bestResponse) {
// 如果没有更好的响应使用DNSSEC专用服务器的响应
bestResponse = response
bestRtt = rtt
hasBestResponse = true
logger.Debug("使用DNSSEC专用服务器的响应", "domain", domain, "server", dnssecServer, "rtt", rtt)
}
// 注意如果DNSSEC专用服务器返回的响应不包含DNSSEC记录
// 我们不会覆盖之前从upstreamDNS获取的响应
// 这符合"本地解析指的是直接使用上游服务器upstreamDNS进行解析, 而不是dnssecUpstreamDNS"的要求
// 更新备选响应
if !hasBackup {
@@ -715,12 +750,17 @@ func (s *Server) forwardDNSRequestWithCache(r *dns.Msg, domain string) (*dns.Msg
// 3. 返回最佳响应
if hasBestResponse {
// 记录解析域名统计
s.updateResolvedDomainStats(domain)
// 检查最佳响应是否包含DNSSEC记录
bestHasDNSSEC := s.hasDNSSECRecords(bestResponse)
// 如果启用了DNSSEC且最佳响应不包含DNSSEC记录使用upstreamDNS的解析结果
if s.config.EnableDNSSEC && !bestHasDNSSEC {
logger.Debug("最佳响应不包含DNSSEC记录使用upstreamDNS的解析结果", "domain", domain)
}
// 记录解析域名统计
s.updateResolvedDomainStats(domain)
// 更新域名的DNSSEC状态
if bestHasDNSSEC {
s.updateDomainDNSSECStatus(domain, true)
@@ -821,7 +861,7 @@ func (s *Server) updateClientStats(ip string) {
// hasDNSSECRecords 检查响应是否包含DNSSEC记录
func (s *Server) hasDNSSECRecords(response *dns.Msg) bool {
// 检查响应中是否包含DNSKEYRRSIG记录
// 检查响应中是否包含DNSSEC相关记录DNSKEYRRSIG、DS、NSEC、NSEC3等
for _, rr := range response.Answer {
if _, ok := rr.(*dns.DNSKEY); ok {
return true
@@ -829,6 +869,15 @@ func (s *Server) hasDNSSECRecords(response *dns.Msg) bool {
if _, ok := rr.(*dns.RRSIG); ok {
return true
}
if _, ok := rr.(*dns.DS); ok {
return true
}
if _, ok := rr.(*dns.NSEC); ok {
return true
}
if _, ok := rr.(*dns.NSEC3); ok {
return true
}
}
for _, rr := range response.Ns {
if _, ok := rr.(*dns.DNSKEY); ok {
@@ -837,6 +886,15 @@ func (s *Server) hasDNSSECRecords(response *dns.Msg) bool {
if _, ok := rr.(*dns.RRSIG); ok {
return true
}
if _, ok := rr.(*dns.DS); ok {
return true
}
if _, ok := rr.(*dns.NSEC); ok {
return true
}
if _, ok := rr.(*dns.NSEC3); ok {
return true
}
}
for _, rr := range response.Extra {
if _, ok := rr.(*dns.DNSKEY); ok {
@@ -845,6 +903,15 @@ func (s *Server) hasDNSSECRecords(response *dns.Msg) bool {
if _, ok := rr.(*dns.RRSIG); ok {
return true
}
if _, ok := rr.(*dns.DS); ok {
return true
}
if _, ok := rr.(*dns.NSEC); ok {
return true
}
if _, ok := rr.(*dns.NSEC3); ok {
return true
}
}
return false
}