优化DNSSEC
This commit is contained in:
29
dns/cache.go
29
dns/cache.go
@@ -41,7 +41,7 @@ func cacheKey(qName string, qType uint16) string {
|
||||
|
||||
// hasDNSSECRecords 检查响应是否包含DNSSEC记录
|
||||
func hasDNSSECRecords(response *dns.Msg) bool {
|
||||
// 检查响应中是否包含DNSKEY或RRSIG记录
|
||||
// 检查响应中是否包含DNSSEC相关记录(DNSKEY、RRSIG、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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
// 检查响应中是否包含DNSKEY或RRSIG记录
|
||||
// 检查响应中是否包含DNSSEC相关记录(DNSKEY、RRSIG、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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user