The ISC compliance checker tests a few very important behaviors expected of anything operating in EDNS0 mode.
It can be found at:
https://ednscomp.isc.org/
Its source code (with the dig commands it uses) can be found at:
https://gitlab.isc.org/isc-projects/DNS-Compliance-Testing
It would be really good if DNS servers implemented using miekg/dns would pass these tests by default, or at least if all examples and documentation would include the required handling for it.
To pass the ISC EDNS compliance tests on a DNS authoritative server written using miekg/dns, I had to add specific handing to:
- enable EDNS response only for EDNS requests, keep it disabled for non-EDNS requests on every handler that generates an response of some sort (including error responses)
- do the EDNS version check, and return the BADVER RCODE if it is not EDNS0, on every handler.
It basically boiled down to:
// right at the start of every DNS message handler (or a common one that always runs first)
err := r.Unpack() // error handling omitted for brevity. Required to populate MsgHeader with EDNS OPT RR data.
if r.Version != 0 {
IssueBADVERerror(w, r) // omitted for brevity. composes an EDNS*0* reply with RcodeBadVers and sends it
return
}
m := &dns.Msg{ Data: r.Data }
dnsutil.SetReply(m, r)
if r.UDPSize > 0 { m.UDPSize = 1232 } // r.UDPSize is only changed from 0 if an EDNS OPT RR is processed by r.Unpack()
// rest of DNS message handler, io.Copy(w, m)
Obviously, the 1232 bytes size limit in the example above is just my own preference to stick to DNS Flag Day 2020 parameters.
The need for explicitly doing the r.Version check is IMHO worrisome, because it is important to do so for the DNS ecosystem as a whole (it avoids contributing to DNS ossification), but it is a very non-obvious thing that is only going to be done on most dns servers written using miekg/dns if it happens by default. Heck, I am not sure I implemented it correctly either :-(
Any suggestions on an acceptable way to add the r.Version error handling to miekg/dns ? I am up to trying to write a patch and submit a PR... but I am unsure if doing it on ServeDNS, perhaps gated by an option in the server struct would be acceptable, since it does require a full unpack.
If it cannot be done by default in miekg/dns, my suggestion is that the documentation should explain how to do it and the examples should include it. Maybe a dnsutil function could be provided that helps implementing it correctly, too.
Also, atomdns likely should implement that EDNS version check too [at a first look it doesn't appear to, but I didn't try running atomdns and pointing dig +edns=1 at it, so I apologize if it already does that EDNS version checking].