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.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} +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} 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
|
section
|
||||||
t || dig -p${DNS_PORT} telemetry.example @127.0.0.1 | grep -Fq 'locally blocked' || fail
|
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
|
cloaked.* one.one.one.one
|
||||||
*.cloaked2.* one.one.one.one # inline comment
|
*.cloaked2.* one.one.one.one # inline comment
|
||||||
=www.dnscrypt-test 192.168.100.100
|
=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
|
block_undelegated = true
|
||||||
forwarding_rules = 'forwarding-rules.txt'
|
forwarding_rules = 'forwarding-rules.txt'
|
||||||
cloaking_rules = 'cloaking-rules.txt'
|
cloaking_rules = 'cloaking-rules.txt'
|
||||||
|
cloak_ptr = true
|
||||||
cache = true
|
cache = true
|
||||||
|
|
||||||
[local_doh]
|
[local_doh]
|
||||||
|
|
|
@ -47,6 +47,11 @@ const (
|
||||||
InheritedDescriptorsBase = uintptr(50)
|
InheritedDescriptorsBase = uintptr(50)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
IPv4Arpa = "in-addr.arpa"
|
||||||
|
IPv6Arpa = "ip6.arpa"
|
||||||
|
)
|
||||||
|
|
||||||
func PrefixWithSize(packet []byte) ([]byte, error) {
|
func PrefixWithSize(packet []byte) ([]byte, error) {
|
||||||
packetLen := len(packet)
|
packetLen := len(packet)
|
||||||
if packetLen > 0xffff {
|
if packetLen > 0xffff {
|
||||||
|
|
|
@ -98,6 +98,7 @@ type Config struct {
|
||||||
RefusedCodeInResponses bool `toml:"refused_code_in_responses"`
|
RefusedCodeInResponses bool `toml:"refused_code_in_responses"`
|
||||||
BlockedQueryResponse string `toml:"blocked_query_response"`
|
BlockedQueryResponse string `toml:"blocked_query_response"`
|
||||||
QueryMeta []string `toml:"query_meta"`
|
QueryMeta []string `toml:"query_meta"`
|
||||||
|
CloakedPTR bool `toml:"cloak_ptr"`
|
||||||
AnonymizedDNS AnonymizedDNSConfig `toml:"anonymized_dns"`
|
AnonymizedDNS AnonymizedDNSConfig `toml:"anonymized_dns"`
|
||||||
DoHClientX509Auth DoHClientX509AuthConfig `toml:"doh_client_x509_auth"`
|
DoHClientX509Auth DoHClientX509AuthConfig `toml:"doh_client_x509_auth"`
|
||||||
DoHClientX509AuthLegacy DoHClientX509AuthConfig `toml:"tls_client_auth"`
|
DoHClientX509AuthLegacy DoHClientX509AuthConfig `toml:"tls_client_auth"`
|
||||||
|
@ -154,6 +155,7 @@ func newConfig() Config {
|
||||||
AnonymizedDNS: AnonymizedDNSConfig{
|
AnonymizedDNS: AnonymizedDNSConfig{
|
||||||
DirectCertFallback: true,
|
DirectCertFallback: true,
|
||||||
},
|
},
|
||||||
|
CloakedPTR: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,6 +486,7 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
|
||||||
proxy.cacheMaxTTL = config.CacheMaxTTL
|
proxy.cacheMaxTTL = config.CacheMaxTTL
|
||||||
proxy.rejectTTL = config.RejectTTL
|
proxy.rejectTTL = config.RejectTTL
|
||||||
proxy.cloakTTL = config.CloakTTL
|
proxy.cloakTTL = config.CloakTTL
|
||||||
|
proxy.cloakedPTR = config.CloakedPTR
|
||||||
|
|
||||||
proxy.queryMeta = config.QueryMeta
|
proxy.queryMeta = config.QueryMeta
|
||||||
|
|
||||||
|
|
|
@ -35,3 +35,10 @@ localhost ::1
|
||||||
# ads.* 192.168.100.1
|
# ads.* 192.168.100.1
|
||||||
# ads.* 192.168.100.2
|
# ads.* 192.168.100.2
|
||||||
# ads.* ::1
|
# 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.
|
## Cloaking returns a predefined address for a specific name.
|
||||||
## In addition to acting as a HOSTS file, it can also return the IP address
|
## 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.
|
## 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
|
## 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
|
## TTL used when serving entries in cloaking-rules.txt
|
||||||
|
|
||||||
# cloak_ttl = 600
|
# cloak_ttl = 600
|
||||||
|
# cloak_ptr = false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,12 +19,14 @@ type CloakedName struct {
|
||||||
lastUpdate *time.Time
|
lastUpdate *time.Time
|
||||||
lineNo int
|
lineNo int
|
||||||
isIP bool
|
isIP bool
|
||||||
|
PTR []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type PluginCloak struct {
|
type PluginCloak struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
patternMatcher *PatternMatcher
|
patternMatcher *PatternMatcher
|
||||||
ttl uint32
|
ttl uint32
|
||||||
|
createPTR bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *PluginCloak) Name() string {
|
func (plugin *PluginCloak) Name() string {
|
||||||
|
@ -42,6 +44,7 @@ func (plugin *PluginCloak) Init(proxy *Proxy) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
plugin.ttl = proxy.cloakTTL
|
plugin.ttl = proxy.cloakTTL
|
||||||
|
plugin.createPTR = proxy.cloakedPTR
|
||||||
plugin.patternMatcher = NewPatternMatcher()
|
plugin.patternMatcher = NewPatternMatcher()
|
||||||
cloakedNames := make(map[string]*CloakedName)
|
cloakedNames := make(map[string]*CloakedName)
|
||||||
for lineNo, line := range strings.Split(string(bin), "\n") {
|
for lineNo, line := range strings.Split(string(bin), "\n") {
|
||||||
|
@ -67,7 +70,8 @@ func (plugin *PluginCloak) Init(proxy *Proxy) error {
|
||||||
if !found {
|
if !found {
|
||||||
cloakedName = &CloakedName{}
|
cloakedName = &CloakedName{}
|
||||||
}
|
}
|
||||||
if ip := net.ParseIP(target); ip != nil {
|
ip := net.ParseIP(target)
|
||||||
|
if ip != nil {
|
||||||
if ipv4 := ip.To4(); ipv4 != nil {
|
if ipv4 := ip.To4(); ipv4 != nil {
|
||||||
cloakedName.ipv4 = append((*cloakedName).ipv4, ipv4)
|
cloakedName.ipv4 = append((*cloakedName).ipv4, ipv4)
|
||||||
} else if ipv6 := ip.To16(); ipv6 != nil {
|
} else if ipv6 := ip.To16(); ipv6 != nil {
|
||||||
|
@ -82,6 +86,28 @@ func (plugin *PluginCloak) Init(proxy *Proxy) error {
|
||||||
}
|
}
|
||||||
cloakedName.lineNo = lineNo + 1
|
cloakedName.lineNo = lineNo + 1
|
||||||
cloakedNames[line] = cloakedName
|
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 {
|
for line, cloakedName := range cloakedNames {
|
||||||
if err := plugin.patternMatcher.Add(line, cloakedName, cloakedName.lineNo); err != nil {
|
if err := plugin.patternMatcher.Add(line, cloakedName, cloakedName.lineNo); err != nil {
|
||||||
|
@ -91,6 +117,15 @@ func (plugin *PluginCloak) Init(proxy *Proxy) error {
|
||||||
return nil
|
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 {
|
func (plugin *PluginCloak) Drop() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -101,7 +136,7 @@ func (plugin *PluginCloak) Reload() error {
|
||||||
|
|
||||||
func (plugin *PluginCloak) Eval(pluginsState *PluginsState, msg *dns.Msg) error {
|
func (plugin *PluginCloak) Eval(pluginsState *PluginsState, msg *dns.Msg) error {
|
||||||
question := msg.Question[0]
|
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
|
return nil
|
||||||
}
|
}
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
@ -157,13 +192,20 @@ func (plugin *PluginCloak) Eval(pluginsState *PluginsState, msg *dns.Msg) error
|
||||||
rr.A = ip
|
rr.A = ip
|
||||||
synth.Answer = append(synth.Answer, rr)
|
synth.Answer = append(synth.Answer, rr)
|
||||||
}
|
}
|
||||||
} else {
|
} else if question.Qtype == dns.TypeAAAA {
|
||||||
for _, ip := range cloakedName.ipv6 {
|
for _, ip := range cloakedName.ipv6 {
|
||||||
rr := new(dns.AAAA)
|
rr := new(dns.AAAA)
|
||||||
rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: ttl}
|
rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: ttl}
|
||||||
rr.AAAA = ip
|
rr.AAAA = ip
|
||||||
synth.Answer = append(synth.Answer, rr)
|
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] })
|
rand.Shuffle(len(synth.Answer), func(i, j int) { synth.Answer[i], synth.Answer[j] = synth.Answer[j], synth.Answer[i] })
|
||||||
pluginsState.synthResponse = synth
|
pluginsState.synthResponse = synth
|
||||||
|
|
|
@ -83,6 +83,7 @@ type Proxy struct {
|
||||||
cacheMinTTL uint32
|
cacheMinTTL uint32
|
||||||
cacheNegMaxTTL uint32
|
cacheNegMaxTTL uint32
|
||||||
cloakTTL uint32
|
cloakTTL uint32
|
||||||
|
cloakedPTR bool
|
||||||
cache bool
|
cache bool
|
||||||
pluginBlockIPv6 bool
|
pluginBlockIPv6 bool
|
||||||
ephemeralKeys bool
|
ephemeralKeys bool
|
||||||
|
|
Loading…
Reference in New Issue