* Fix EDNS0 compliance Do SizeAndDo in the server (ScrubWriter) and remove all uses of this from the plugins. Also *always* do it. This is to get into compliance for https://dnsflagday.net/. The pkg/edns0 now exports the EDNS0 options we understand; this is exported to allow plugins add things there. The *rewrite* plugin used this to add custom EDNS0 option codes that the server needs to understand. This also needs a new release of miekg/dns because it triggered a race-condition that was basicly there forever. See: * https://github.com/miekg/dns/issues/857 * https://github.com/miekg/dns/pull/859 Running a test instance and pointing the https://ednscomp.isc.org/ednscomp to it shows the tests are now fixed: ~~~ EDNS Compliance Tester Checking: 'miek.nl' as at 2018-12-01T17:53:15Z miek.nl. @147.75.204.203 (drone.coredns.io.): dns=ok edns=ok edns1=ok edns@512=ok ednsopt=ok edns1opt=ok do=ok ednsflags=ok docookie=ok edns512tcp=ok optlist=ok miek.nl. @2604:1380:2002:a000::1 (drone.coredns.io.): dns=ok edns=ok edns1=ok edns@512=ok ednsopt=ok edns1opt=ok do=ok ednsflags=ok docookie=ok edns512tcp=ok optlist=ok All Ok Codes ok - test passed. ~~~ Signed-off-by: Miek Gieben <miek@miek.nl> Signed-off-by: Miek Gieben <miek@miek.nl> * typos in comments Signed-off-by: Miek Gieben <miek@miek.nl>
73 lines
1.8 KiB
Go
73 lines
1.8 KiB
Go
// Package edns provides function useful for adding/inspecting OPT records to/in messages.
|
|
package edns
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
var sup = &supported{m: make(map[uint16]struct{})}
|
|
|
|
type supported struct {
|
|
m map[uint16]struct{}
|
|
sync.RWMutex
|
|
}
|
|
|
|
// SetSupportedOption adds a new supported option the set of EDNS0 options that we support. Plugins typically call
|
|
// this in their setup code to signal support for a new option.
|
|
// By default we support:
|
|
// dns.EDNS0NSID, dns.EDNS0EXPIRE, dns.EDNS0COOKIE, dns.EDNS0TCPKEEPALIVE, dns.EDNS0PADDING. These
|
|
// values are not in this map and checked directly in the server.
|
|
func SetSupportedOption(option uint16) {
|
|
sup.Lock()
|
|
sup.m[option] = struct{}{}
|
|
sup.Unlock()
|
|
}
|
|
|
|
// SupportedOption returns true if the option code is supported as an extra EDNS0 option.
|
|
func SupportedOption(option uint16) bool {
|
|
sup.RLock()
|
|
_, ok := sup.m[option]
|
|
sup.RUnlock()
|
|
return ok
|
|
}
|
|
|
|
// Version checks the EDNS version in the request. If error
|
|
// is nil everything is OK and we can invoke the plugin. If non-nil, the
|
|
// returned Msg is valid to be returned to the client (and should). For some
|
|
// reason this response should not contain a question RR in the question section.
|
|
func Version(req *dns.Msg) (*dns.Msg, error) {
|
|
opt := req.IsEdns0()
|
|
if opt == nil {
|
|
return nil, nil
|
|
}
|
|
if opt.Version() == 0 {
|
|
return nil, nil
|
|
}
|
|
m := new(dns.Msg)
|
|
m.SetReply(req)
|
|
// zero out question section, wtf.
|
|
m.Question = nil
|
|
|
|
o := new(dns.OPT)
|
|
o.Hdr.Name = "."
|
|
o.Hdr.Rrtype = dns.TypeOPT
|
|
o.SetVersion(0)
|
|
o.SetExtendedRcode(dns.RcodeBadVers)
|
|
m.Extra = []dns.RR{o}
|
|
|
|
return m, errors.New("EDNS0 BADVERS")
|
|
}
|
|
|
|
// Size returns a normalized size based on proto.
|
|
func Size(proto string, size int) int {
|
|
if proto == "tcp" {
|
|
return dns.MaxMsgSize
|
|
}
|
|
if size < dns.MinMsgSize {
|
|
return dns.MinMsgSize
|
|
}
|
|
return size
|
|
}
|