mirror of https://github.com/0xERR0R/blocky.git
155 lines
3.5 KiB
Go
155 lines
3.5 KiB
Go
package resolver
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
|
|
"github.com/0xERR0R/blocky/model"
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
const (
|
|
sudnTest = "test."
|
|
sudnInvalid = "invalid."
|
|
sudnLocalhost = "localhost."
|
|
mdnsLocal = "local."
|
|
)
|
|
|
|
func sudnArpaSlice() []string {
|
|
return []string{
|
|
"10.in-addr.arpa.",
|
|
"21.172.in-addr.arpa.",
|
|
"26.172.in-addr.arpa.",
|
|
"16.172.in-addr.arpa.",
|
|
"22.172.in-addr.arpa.",
|
|
"27.172.in-addr.arpa.",
|
|
"17.172.in-addr.arpa.",
|
|
"30.172.in-addr.arpa.",
|
|
"28.172.in-addr.arpa.",
|
|
"18.172.in-addr.arpa.",
|
|
"23.172.in-addr.arpa.",
|
|
"29.172.in-addr.arpa.",
|
|
"19.172.in-addr.arpa.",
|
|
"24.172.in-addr.arpa.",
|
|
"31.172.in-addr.arpa.",
|
|
"20.172.in-addr.arpa.",
|
|
"25.172.in-addr.arpa.",
|
|
"168.192.in-addr.arpa.",
|
|
}
|
|
}
|
|
|
|
type defaultIPs struct {
|
|
loopbackV4 net.IP
|
|
loopbackV6 net.IP
|
|
}
|
|
|
|
type SpecialUseDomainNamesResolver struct {
|
|
NextResolver
|
|
defaults *defaultIPs
|
|
}
|
|
|
|
func NewSpecialUseDomainNamesResolver() ChainedResolver {
|
|
return &SpecialUseDomainNamesResolver{
|
|
defaults: &defaultIPs{
|
|
loopbackV4: net.ParseIP("127.0.0.1"),
|
|
loopbackV6: net.IPv6loopback,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (r *SpecialUseDomainNamesResolver) Resolve(request *model.Request) (*model.Response, error) {
|
|
// RFC 6761 - negative
|
|
if r.isSpecial(request, sudnArpaSlice()...) ||
|
|
r.isSpecial(request, sudnInvalid) ||
|
|
r.isSpecial(request, sudnTest) {
|
|
return r.negativeResponse(request)
|
|
}
|
|
// RFC 6761 - switched
|
|
if r.isSpecial(request, sudnLocalhost) {
|
|
return r.responseSwitch(request, sudnLocalhost, r.defaults.loopbackV4, r.defaults.loopbackV6)
|
|
}
|
|
|
|
// RFC 6762 - negative
|
|
if r.isSpecial(request, mdnsLocal) {
|
|
return r.negativeResponse(request)
|
|
}
|
|
|
|
return r.next.Resolve(request)
|
|
}
|
|
|
|
// RFC 6761 & 6762 are always active
|
|
func (r *SpecialUseDomainNamesResolver) Configuration() []string {
|
|
return []string{}
|
|
}
|
|
|
|
func (r *SpecialUseDomainNamesResolver) isSpecial(request *model.Request, names ...string) bool {
|
|
domainFromQuestion := request.Req.Question[0].Name
|
|
for _, n := range names {
|
|
if domainFromQuestion == n ||
|
|
strings.HasSuffix(domainFromQuestion, fmt.Sprintf(".%s", n)) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (r *SpecialUseDomainNamesResolver) responseSwitch(request *model.Request,
|
|
name string, ipV4, ipV6 net.IP) (*model.Response, error) {
|
|
qtype := request.Req.Question[0].Qtype
|
|
switch qtype {
|
|
case dns.TypeA:
|
|
return r.positiveResponse(request, name, dns.TypeA, ipV4)
|
|
case dns.TypeAAAA:
|
|
return r.positiveResponse(request, name, dns.TypeAAAA, ipV6)
|
|
default:
|
|
return r.negativeResponse(request)
|
|
}
|
|
}
|
|
|
|
func (r *SpecialUseDomainNamesResolver) positiveResponse(request *model.Request,
|
|
name string, rtype uint16, ip net.IP) (*model.Response, error) {
|
|
response := newResponseMsg(request)
|
|
response.Rcode = dns.RcodeSuccess
|
|
|
|
hdr := dns.RR_Header{
|
|
Name: name,
|
|
Rrtype: rtype,
|
|
Class: dns.ClassINET,
|
|
Ttl: 0,
|
|
}
|
|
|
|
if rtype != dns.TypeA && rtype != dns.TypeAAAA {
|
|
return nil, fmt.Errorf("invalid response type")
|
|
}
|
|
|
|
var rr dns.RR
|
|
if rtype == dns.TypeA {
|
|
rr = &dns.A{
|
|
A: ip,
|
|
Hdr: hdr,
|
|
}
|
|
} else {
|
|
rr = &dns.AAAA{
|
|
AAAA: ip,
|
|
Hdr: hdr,
|
|
}
|
|
}
|
|
|
|
response.Answer = []dns.RR{rr}
|
|
|
|
return r.returnResponseModel(response)
|
|
}
|
|
|
|
func (r *SpecialUseDomainNamesResolver) negativeResponse(request *model.Request) (*model.Response, error) {
|
|
response := newResponseMsg(request)
|
|
response.Rcode = dns.RcodeNameError
|
|
|
|
return r.returnResponseModel(response)
|
|
}
|
|
|
|
func (r *SpecialUseDomainNamesResolver) returnResponseModel(response *dns.Msg) (*model.Response, error) {
|
|
return returnResponseModel(response, model.ResponseTypeSPECIAL, "Special-Use Domain Name")
|
|
}
|