```
feat(core): 改进 DNS 响应构造逻辑以支持扩展错误码和诊断信息 在 writeReply 函数中,增强对上游 EDNS 选项的处理: - 继承上游的扩展 RCODE 与 EDNS 版本号 - 可选透传 EDE(Extended DNS Errors)记录,保留更多诊断信息 - 明确设置 UDPSize、DO 位及 EDNS 版本转换逻辑 这有助于提升调试能力与协议兼容性,同时保持客户端请求的一致性。 ```
This commit is contained in:
31
main.go
31
main.go
@@ -392,20 +392,22 @@ func getDOFlag(m *dns.Msg) bool {
|
|||||||
* 响应构造:使用客户端请求头构造 reply,复制上游内容
|
* 响应构造:使用客户端请求头构造 reply,复制上游内容
|
||||||
******************************************************************/
|
******************************************************************/
|
||||||
|
|
||||||
// writeReply 根据客户端请求构造响应骨架:复制上游的 Answer/Ns/(非伪)Extra,
|
// writeReply 根据客户端请求构造响应:复制上游 Answer/Ns/非伪 Extra,
|
||||||
// 并按照**客户端请求**重建 OPT(UDPSize/DO),避免直接采纳上游的 OPT/TSIG。
|
// 并按客户端请求重建 OPT(UDPSize/DO),同时继承上游的扩展 RCODE 与 EDNS 版本;
|
||||||
|
// 可选透传上游的 EDE(Extended DNS Errors)以保留诊断信息。
|
||||||
func writeReply(w dns.ResponseWriter, req, upstream *dns.Msg) {
|
func writeReply(w dns.ResponseWriter, req, upstream *dns.Msg) {
|
||||||
if upstream == nil {
|
if upstream == nil {
|
||||||
dns.HandleFailed(w, req)
|
dns.HandleFailed(w, req)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
out := new(dns.Msg)
|
out := new(dns.Msg)
|
||||||
out.SetReply(req)
|
out.SetReply(req)
|
||||||
out.Authoritative = false
|
out.Authoritative = false
|
||||||
out.RecursionAvailable = upstream.RecursionAvailable
|
out.RecursionAvailable = upstream.RecursionAvailable
|
||||||
out.AuthenticatedData = upstream.AuthenticatedData
|
out.AuthenticatedData = upstream.AuthenticatedData
|
||||||
out.CheckingDisabled = req.CheckingDisabled // 反映客户端 CD 位
|
out.CheckingDisabled = req.CheckingDisabled // 反映客户端 CD 位
|
||||||
out.Rcode = upstream.Rcode
|
out.Rcode = upstream.Rcode // 主 RCODE(低 4 位)
|
||||||
out.Answer = upstream.Answer
|
out.Answer = upstream.Answer
|
||||||
out.Ns = upstream.Ns
|
out.Ns = upstream.Ns
|
||||||
|
|
||||||
@@ -417,20 +419,39 @@ func writeReply(w dns.ResponseWriter, req, upstream *dns.Msg) {
|
|||||||
}
|
}
|
||||||
extras = append(extras, rr)
|
extras = append(extras, rr)
|
||||||
}
|
}
|
||||||
// 基于客户端请求镜像 EDNS(UDPSize + DO),保持传输一致性
|
|
||||||
|
// 基于客户端请求镜像 EDNS(UDPSize + DO)
|
||||||
if ro := req.IsEdns0(); ro != nil {
|
if ro := req.IsEdns0(); ro != nil {
|
||||||
o := new(dns.OPT)
|
o := new(dns.OPT)
|
||||||
o.Hdr.Name = "."
|
o.Hdr.Name = "."
|
||||||
o.Hdr.Rrtype = dns.TypeOPT
|
o.Hdr.Rrtype = dns.TypeOPT
|
||||||
|
|
||||||
|
// 与客户端保持一致的 UDPSize / DO 位
|
||||||
o.SetUDPSize(ro.UDPSize())
|
o.SetUDPSize(ro.UDPSize())
|
||||||
if ro.Do() {
|
if ro.Do() {
|
||||||
o.SetDo()
|
o.SetDo()
|
||||||
}
|
}
|
||||||
// 如需转发 NSID/COOKIE 等可在此附加;为减少复杂性与缓存污染,建议保守最小集合
|
|
||||||
|
// 继承上游的扩展 RCODE 与 EDNS 版本(注意不同版本签名差异,这里显式转换)
|
||||||
|
if uo := upstream.IsEdns0(); uo != nil {
|
||||||
|
// 你当前库期望 uint16,这里强转;若你的库期望 uint8,也可改成 uint8(...)
|
||||||
|
o.SetExtendedRcode(uint16(uo.ExtendedRcode()))
|
||||||
|
o.SetVersion(uint8(uo.Version()))
|
||||||
|
|
||||||
|
// 可选:透传只读的 EDE 诊断信息
|
||||||
|
for _, opt := range uo.Option {
|
||||||
|
if ede, ok := opt.(*dns.EDNS0_EDE); ok {
|
||||||
|
o.Option = append(o.Option, ede)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extras = append(extras, o)
|
extras = append(extras, o)
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Extra = extras
|
out.Extra = extras
|
||||||
out.Compress = true
|
out.Compress = true
|
||||||
|
|
||||||
if err := w.WriteMsg(out); err != nil {
|
if err := w.WriteMsg(out); err != nil {
|
||||||
log.Printf("[write] WriteMsg error: %v", err)
|
log.Printf("[write] WriteMsg error: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user