diff --git a/dot b/dot index b1c1148..f19db30 100644 Binary files a/dot and b/dot differ diff --git a/main.go b/main.go index b21fcf5..d2c714a 100644 --- a/main.go +++ b/main.go @@ -392,20 +392,22 @@ func getDOFlag(m *dns.Msg) bool { * 响应构造:使用客户端请求头构造 reply,复制上游内容 ******************************************************************/ -// writeReply 根据客户端请求构造响应骨架:复制上游的 Answer/Ns/(非伪)Extra, -// 并按照**客户端请求**重建 OPT(UDPSize/DO),避免直接采纳上游的 OPT/TSIG。 +// writeReply 根据客户端请求构造响应:复制上游 Answer/Ns/非伪 Extra, +// 并按客户端请求重建 OPT(UDPSize/DO),同时继承上游的扩展 RCODE 与 EDNS 版本; +// 可选透传上游的 EDE(Extended DNS Errors)以保留诊断信息。 func writeReply(w dns.ResponseWriter, req, upstream *dns.Msg) { if upstream == nil { dns.HandleFailed(w, req) return } + out := new(dns.Msg) out.SetReply(req) out.Authoritative = false out.RecursionAvailable = upstream.RecursionAvailable out.AuthenticatedData = upstream.AuthenticatedData out.CheckingDisabled = req.CheckingDisabled // 反映客户端 CD 位 - out.Rcode = upstream.Rcode + out.Rcode = upstream.Rcode // 主 RCODE(低 4 位) out.Answer = upstream.Answer out.Ns = upstream.Ns @@ -417,20 +419,39 @@ func writeReply(w dns.ResponseWriter, req, upstream *dns.Msg) { } extras = append(extras, rr) } - // 基于客户端请求镜像 EDNS(UDPSize + DO),保持传输一致性 + + // 基于客户端请求镜像 EDNS(UDPSize + DO) if ro := req.IsEdns0(); ro != nil { o := new(dns.OPT) o.Hdr.Name = "." o.Hdr.Rrtype = dns.TypeOPT + + // 与客户端保持一致的 UDPSize / DO 位 o.SetUDPSize(ro.UDPSize()) if ro.Do() { 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) } + out.Extra = extras out.Compress = true + if err := w.WriteMsg(out); err != nil { log.Printf("[write] WriteMsg error: %v", err) }