blocky/resolver/sudn_resolver.go

185 lines
4.4 KiB
Go
Raw Permalink Normal View History

2022-08-27 00:00:48 +02:00
package resolver
import (
"context"
2022-09-04 01:27:13 +02:00
"net"
2022-08-27 00:00:48 +02:00
"strings"
"github.com/0xERR0R/blocky/config"
2022-08-27 00:00:48 +02:00
"github.com/0xERR0R/blocky/model"
"github.com/miekg/dns"
)
type sudnHandler = func(request *model.Request, cfg *config.SUDN) *model.Response
//nolint:gochecknoglobals
var (
loopbackV4 = net.ParseIP("127.0.0.1")
loopbackV6 = net.IPv6loopback
// See Wikipedia for an up-to-date reference:
// https://en.wikipedia.org/wiki/Special-use_domain_name
sudnHandlers = map[string]sudnHandler{
// RFC 6761
// https://www.rfc-editor.org/rfc/rfc6761
//
// Section 6.1
"10.in-addr.arpa.": sudnNXDomain,
"21.172.in-addr.arpa.": sudnNXDomain,
"26.172.in-addr.arpa.": sudnNXDomain,
"16.172.in-addr.arpa.": sudnNXDomain,
"22.172.in-addr.arpa.": sudnNXDomain,
"27.172.in-addr.arpa.": sudnNXDomain,
"17.172.in-addr.arpa.": sudnNXDomain,
"30.172.in-addr.arpa.": sudnNXDomain,
"28.172.in-addr.arpa.": sudnNXDomain,
"18.172.in-addr.arpa.": sudnNXDomain,
"23.172.in-addr.arpa.": sudnNXDomain,
"29.172.in-addr.arpa.": sudnNXDomain,
"19.172.in-addr.arpa.": sudnNXDomain,
"24.172.in-addr.arpa.": sudnNXDomain,
"31.172.in-addr.arpa.": sudnNXDomain,
"20.172.in-addr.arpa.": sudnNXDomain,
"25.172.in-addr.arpa.": sudnNXDomain,
"168.192.in-addr.arpa.": sudnNXDomain,
// Section 6.2
"test.": sudnNXDomain,
// Section 6.3
"localhost.": sudnLocalhost,
// Section 6.4
"invalid.": sudnNXDomain,
// Section 6.5
"example.": nil,
"example.com.": nil,
"example.net.": nil,
"example.org.": nil,
// RFC 6762
// https://www.rfc-editor.org/rfc/rfc6762
//
// mDNS is not implemented, so just return NXDOMAIN
//
// Section 3
"local.": sudnNXDomain,
// Section 12
"254.169.in-addr.arpa.": sudnNXDomain, // also section 4
"8.e.f.ip6.arpa.": sudnNXDomain,
"9.e.f.ip6.arpa.": sudnNXDomain,
"a.e.f.ip6.arpa.": sudnNXDomain,
"b.e.f.ip6.arpa.": sudnNXDomain,
// Appendix G
"intranet.": sudnRFC6762AppendixG,
"internal.": sudnRFC6762AppendixG,
"private.": sudnRFC6762AppendixG,
"corp.": sudnRFC6762AppendixG,
"home.": sudnRFC6762AppendixG,
"lan.": sudnRFC6762AppendixG,
// RFC 7686
// https://www.rfc-editor.org/rfc/rfc7686
"onion.": sudnNXDomain,
// RFC 8375
// https://www.rfc-editor.org/rfc/rfc8375
//
// Section 4
"home.arpa.": sudnHomeArpa,
2022-08-27 00:00:48 +02:00
}
)
2022-09-13 19:56:50 +02:00
type SpecialUseDomainNamesResolver struct {
2022-08-27 00:00:48 +02:00
NextResolver
refactor: configuration rework (usage and printing) (#920) * refactor: make `config.Duration` a struct with `time.Duration` embed Allows directly calling `time.Duration` methods. * refactor(HostsFileResolver): don't copy individual config items The idea is to make adding configuration options easier, and searching for references straight forward. * refactor: move config printing to struct and use a logger Using a logger allows using multiple levels so the whole configuration can be printed in trace/verbose mode, but only important parts are shown by default. * squash: rename `Cast` to `ToDuration` * squash: revert `Duration` to a simple wrapper ("new type" pattern) * squash: `Duration.IsZero` tests * squash: refactor resolvers to rely on their config directly if possible * squash: implement `IsEnabled` and `LogValues` for all resolvers * refactor: use go-enum `--values` to simplify getting all log fields * refactor: simplify `QType` unmarshaling * squash: rename `ValueLogger` to `Configurable` * squash: rename `UpstreamConfig` to `ParallelBestConfig` * squash: rename `RewriteConfig` to `RewriterConfig` * squash: config tests * squash: resolver tests * squash: add `ForEach` test and improve `Chain` ones * squash: simplify implementing `config.Configurable` * squash: minor changes for better coverage * squash: more `UnmarshalYAML` -> `UnmarshalText` * refactor: move `config.Upstream` into own file * refactor: add `Resolver.Type` method * squash: add `log` method to `typed` to use `Resolover.Type` as prefix * squash: tweak startup config logging * squash: add `LogResolverConfig` tests * squash: make sure all options of type `Duration` use `%s`
2023-03-12 22:14:10 +01:00
typed
configurable[*config.SUDN]
2022-08-27 00:00:48 +02:00
}
func NewSpecialUseDomainNamesResolver(cfg config.SUDN) *SpecialUseDomainNamesResolver {
2022-09-13 19:56:50 +02:00
return &SpecialUseDomainNamesResolver{
typed: withType("special_use_domains"),
configurable: withConfig(&cfg),
2022-09-13 19:56:50 +02:00
}
2022-08-27 00:00:48 +02:00
}
func (r *SpecialUseDomainNamesResolver) Resolve(ctx context.Context, request *model.Request) (*model.Response, error) {
handler := r.handler(request)
if handler != nil {
resp := handler(request, r.cfg)
if resp != nil {
return resp, nil
}
2022-08-27 00:00:48 +02:00
}
return r.next.Resolve(ctx, request)
2022-08-27 00:00:48 +02:00
}
func (r *SpecialUseDomainNamesResolver) handler(request *model.Request) sudnHandler {
q := request.Req.Question[0]
domain := q.Name
for {
handler, ok := sudnHandlers[domain]
if ok {
return handler
}
_, after, ok := strings.Cut(domain, ".")
if !ok {
return nil
2022-09-13 19:56:50 +02:00
}
domain = after
2022-09-13 19:56:50 +02:00
}
}
2022-08-27 00:00:48 +02:00
func newSUDNResponse(response *model.Request, rcode int) *model.Response {
return newResponse(response, rcode, model.ResponseTypeSPECIAL, "Special-Use Domain Name")
2022-08-27 00:00:48 +02:00
}
func sudnNXDomain(request *model.Request, _ *config.SUDN) *model.Response {
return newSUDNResponse(request, dns.RcodeNameError)
}
func sudnLocalhost(request *model.Request, cfg *config.SUDN) *model.Response {
q := request.Req.Question[0]
var rr dns.RR
switch q.Qtype {
2022-09-13 19:56:50 +02:00
case dns.TypeA:
rr = &dns.A{A: loopbackV4}
2022-09-13 19:56:50 +02:00
case dns.TypeAAAA:
rr = &dns.AAAA{AAAA: loopbackV6}
2022-09-13 19:56:50 +02:00
default:
return sudnNXDomain(request, cfg)
2022-09-04 01:27:13 +02:00
}
*rr.Header() = dns.RR_Header{
Name: q.Name,
Rrtype: q.Qtype,
2022-09-04 01:27:13 +02:00
Class: dns.ClassINET,
Ttl: 0,
}
response := newSUDNResponse(request, dns.RcodeSuccess)
response.Res.Answer = []dns.RR{rr}
2022-09-13 19:56:50 +02:00
return response
2022-09-04 01:27:13 +02:00
}
func sudnRFC6762AppendixG(request *model.Request, cfg *config.SUDN) *model.Response {
if !cfg.RFC6762AppendixG {
return nil
}
2022-08-27 00:00:48 +02:00
return sudnNXDomain(request, cfg)
2022-09-23 23:07:54 +02:00
}
func sudnHomeArpa(request *model.Request, cfg *config.SUDN) *model.Response {
if request.Req.Question[0].Qtype == dns.TypeDS {
// DS queries must be forwarded
return nil
}
return sudnNXDomain(request, cfg)
2022-09-06 21:33:48 +02:00
}