allow ptr queries for cloaked domains (#1958)
* allow ptr queries for cloaked domains * multi ips per PTR returned + cleanup * some string tidy up * enable config file switch * add cloaked ptr test * enable cloak ptrs in test scenario * fix reverse ipv6 ptr lookup * added ipv6 cloaked ptr test
This commit is contained in:
parent
27e93a53cf
commit
1b6caba307
|
@ -70,6 +70,8 @@ t || dig -p${DNS_PORT} +short cloaked.com @127.0.0.1 | grep -Eq '1.1.1.1|1.0.0.1
|
|||
t || dig -p${DNS_PORT} +short www.cloaked2.com @127.0.0.1 | grep -Eq '1.1.1.1|1.0.0.1' || fail
|
||||
t || dig -p${DNS_PORT} +short www.dnscrypt-test @127.0.0.1 | grep -Fq '192.168.100.100' || fail
|
||||
t || dig -p${DNS_PORT} a.www.dnscrypt-test @127.0.0.1 | grep -Fq 'NXDOMAIN' || fail
|
||||
t || dig -p${DNS_PORT} +short ptr 101.100.168.192.in-addr.arpa. @127.0.0.1 | grep -Eq 'www.dnscrypt-test.com' || fail
|
||||
t || dig -p${DNS_PORT} +short ptr 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.d.f.ip6.arpa. @127.0.0.1 | grep -Eq 'ipv6.dnscrypt-test.com' || fail
|
||||
|
||||
section
|
||||
t || dig -p${DNS_PORT} telemetry.example @127.0.0.1 | grep -Fq 'locally blocked' || fail
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
cloaked.* one.one.one.one
|
||||
*.cloaked2.* one.one.one.one # inline comment
|
||||
=www.dnscrypt-test 192.168.100.100
|
||||
=www.dnscrypt-test.com 192.168.100.101
|
||||
=ipv6.dnscrypt-test.com fd02::1
|
|
@ -10,6 +10,7 @@ block_unqualified = true
|
|||
block_undelegated = true
|
||||
forwarding_rules = 'forwarding-rules.txt'
|
||||
cloaking_rules = 'cloaking-rules.txt'
|
||||
cloak_ptr = true
|
||||
cache = true
|
||||
|
||||
[local_doh]
|
||||
|
|
|
@ -47,6 +47,11 @@ const (
|
|||
InheritedDescriptorsBase = uintptr(50)
|
||||
)
|
||||
|
||||
const (
|
||||
IPv4Arpa = "in-addr.arpa"
|
||||
IPv6Arpa = "ip6.arpa"
|
||||
)
|
||||
|
||||
func PrefixWithSize(packet []byte) ([]byte, error) {
|
||||
packetLen := len(packet)
|
||||
if packetLen > 0xffff {
|
||||
|
|
|
@ -98,6 +98,7 @@ type Config struct {
|
|||
RefusedCodeInResponses bool `toml:"refused_code_in_responses"`
|
||||
BlockedQueryResponse string `toml:"blocked_query_response"`
|
||||
QueryMeta []string `toml:"query_meta"`
|
||||
CloakedPTR bool `toml:"cloak_ptr"`
|
||||
AnonymizedDNS AnonymizedDNSConfig `toml:"anonymized_dns"`
|
||||
DoHClientX509Auth DoHClientX509AuthConfig `toml:"doh_client_x509_auth"`
|
||||
DoHClientX509AuthLegacy DoHClientX509AuthConfig `toml:"tls_client_auth"`
|
||||
|
@ -154,6 +155,7 @@ func newConfig() Config {
|
|||
AnonymizedDNS: AnonymizedDNSConfig{
|
||||
DirectCertFallback: true,
|
||||
},
|
||||
CloakedPTR: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -484,6 +486,7 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
|
|||
proxy.cacheMaxTTL = config.CacheMaxTTL
|
||||
proxy.rejectTTL = config.RejectTTL
|
||||
proxy.cloakTTL = config.CloakTTL
|
||||
proxy.cloakedPTR = config.CloakedPTR
|
||||
|
||||
proxy.queryMeta = config.QueryMeta
|
||||
|
||||
|
|
|
@ -35,3 +35,10 @@ localhost ::1
|
|||
# ads.* 192.168.100.1
|
||||
# ads.* 192.168.100.2
|
||||
# ads.* ::1
|
||||
|
||||
# PTR records can be created by setting cloak_ptr in the main configuration file
|
||||
# Entries with wild cards will not have PTR records created, but multiple
|
||||
# names for the same IP are supported
|
||||
|
||||
# example.com 192.168.100.1
|
||||
# my.example.com 192.168.100.1
|
||||
|
|
|
@ -352,6 +352,8 @@ reject_ttl = 10
|
|||
## Cloaking returns a predefined address for a specific name.
|
||||
## In addition to acting as a HOSTS file, it can also return the IP address
|
||||
## of a different name. It will also do CNAME flattening.
|
||||
## If 'cloak_ptr' is set, then PTR (reverse lookups) are enabled
|
||||
## for cloaking rules that do not contain wild cards.
|
||||
##
|
||||
## See the `example-cloaking-rules.txt` file for an example
|
||||
|
||||
|
@ -360,6 +362,7 @@ reject_ttl = 10
|
|||
## TTL used when serving entries in cloaking-rules.txt
|
||||
|
||||
# cloak_ttl = 600
|
||||
# cloak_ptr = false
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -19,12 +19,14 @@ type CloakedName struct {
|
|||
lastUpdate *time.Time
|
||||
lineNo int
|
||||
isIP bool
|
||||
PTR []string
|
||||
}
|
||||
|
||||
type PluginCloak struct {
|
||||
sync.RWMutex
|
||||
patternMatcher *PatternMatcher
|
||||
ttl uint32
|
||||
createPTR bool
|
||||
}
|
||||
|
||||
func (plugin *PluginCloak) Name() string {
|
||||
|
@ -42,6 +44,7 @@ func (plugin *PluginCloak) Init(proxy *Proxy) error {
|
|||
return err
|
||||
}
|
||||
plugin.ttl = proxy.cloakTTL
|
||||
plugin.createPTR = proxy.cloakedPTR
|
||||
plugin.patternMatcher = NewPatternMatcher()
|
||||
cloakedNames := make(map[string]*CloakedName)
|
||||
for lineNo, line := range strings.Split(string(bin), "\n") {
|
||||
|
@ -67,7 +70,8 @@ func (plugin *PluginCloak) Init(proxy *Proxy) error {
|
|||
if !found {
|
||||
cloakedName = &CloakedName{}
|
||||
}
|
||||
if ip := net.ParseIP(target); ip != nil {
|
||||
ip := net.ParseIP(target)
|
||||
if ip != nil {
|
||||
if ipv4 := ip.To4(); ipv4 != nil {
|
||||
cloakedName.ipv4 = append((*cloakedName).ipv4, ipv4)
|
||||
} else if ipv6 := ip.To16(); ipv6 != nil {
|
||||
|
@ -82,6 +86,28 @@ func (plugin *PluginCloak) Init(proxy *Proxy) error {
|
|||
}
|
||||
cloakedName.lineNo = lineNo + 1
|
||||
cloakedNames[line] = cloakedName
|
||||
|
||||
if !plugin.createPTR || strings.Contains(line, "*") || !cloakedName.isIP == true {
|
||||
continue
|
||||
}
|
||||
|
||||
var ptrLine string
|
||||
if ipv4 := ip.To4(); ipv4 != nil {
|
||||
reversed, _ := dns.ReverseAddr(ip.To4().String())
|
||||
ptrLine = strings.TrimSuffix(reversed, ".")
|
||||
} else {
|
||||
reversed, _ := dns.ReverseAddr(cloakedName.ipv6[0].To16().String())
|
||||
ptrLine = strings.TrimSuffix(reversed, ".")
|
||||
}
|
||||
ptrQueryLine := ptrEntryToQuery(ptrLine)
|
||||
ptrCloakedName, found := cloakedNames[ptrQueryLine]
|
||||
if !found {
|
||||
ptrCloakedName = &CloakedName{}
|
||||
}
|
||||
ptrCloakedName.isIP = true
|
||||
ptrCloakedName.PTR = append((*ptrCloakedName).PTR, ptrNameToFQDN(line))
|
||||
ptrCloakedName.lineNo = lineNo + 1
|
||||
cloakedNames[ptrQueryLine] = ptrCloakedName
|
||||
}
|
||||
for line, cloakedName := range cloakedNames {
|
||||
if err := plugin.patternMatcher.Add(line, cloakedName, cloakedName.lineNo); err != nil {
|
||||
|
@ -91,6 +117,15 @@ func (plugin *PluginCloak) Init(proxy *Proxy) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func ptrEntryToQuery(ptrEntry string) string {
|
||||
return "=" + ptrEntry
|
||||
}
|
||||
|
||||
func ptrNameToFQDN(ptrLine string) string {
|
||||
ptrLine = strings.TrimPrefix(ptrLine, "=")
|
||||
return ptrLine + "."
|
||||
}
|
||||
|
||||
func (plugin *PluginCloak) Drop() error {
|
||||
return nil
|
||||
}
|
||||
|
@ -101,7 +136,7 @@ func (plugin *PluginCloak) Reload() error {
|
|||
|
||||
func (plugin *PluginCloak) Eval(pluginsState *PluginsState, msg *dns.Msg) error {
|
||||
question := msg.Question[0]
|
||||
if question.Qclass != dns.ClassINET || (question.Qtype != dns.TypeA && question.Qtype != dns.TypeAAAA) {
|
||||
if question.Qclass != dns.ClassINET || (question.Qtype != dns.TypeA && question.Qtype != dns.TypeAAAA && question.Qtype != dns.TypePTR) {
|
||||
return nil
|
||||
}
|
||||
now := time.Now()
|
||||
|
@ -157,13 +192,20 @@ func (plugin *PluginCloak) Eval(pluginsState *PluginsState, msg *dns.Msg) error
|
|||
rr.A = ip
|
||||
synth.Answer = append(synth.Answer, rr)
|
||||
}
|
||||
} else {
|
||||
} else if question.Qtype == dns.TypeAAAA {
|
||||
for _, ip := range cloakedName.ipv6 {
|
||||
rr := new(dns.AAAA)
|
||||
rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: ttl}
|
||||
rr.AAAA = ip
|
||||
synth.Answer = append(synth.Answer, rr)
|
||||
}
|
||||
} else if question.Qtype == dns.TypePTR {
|
||||
for _, ptr := range cloakedName.PTR {
|
||||
rr := new(dns.PTR)
|
||||
rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: ttl}
|
||||
rr.Ptr = ptr
|
||||
synth.Answer = append(synth.Answer, rr)
|
||||
}
|
||||
}
|
||||
rand.Shuffle(len(synth.Answer), func(i, j int) { synth.Answer[i], synth.Answer[j] = synth.Answer[j], synth.Answer[i] })
|
||||
pluginsState.synthResponse = synth
|
||||
|
|
|
@ -83,6 +83,7 @@ type Proxy struct {
|
|||
cacheMinTTL uint32
|
||||
cacheNegMaxTTL uint32
|
||||
cloakTTL uint32
|
||||
cloakedPTR bool
|
||||
cache bool
|
||||
pluginBlockIPv6 bool
|
||||
ephemeralKeys bool
|
||||
|
|
Loading…
Reference in New Issue