blocked_query_response takes the format 'a:<IPv4>,aaaa:<IPv6>' for IP responses

This commit is contained in:
James Newell 2019-07-14 13:46:11 -04:00 committed by Frank Denis
parent 5812cb2fe4
commit d3ab899f7b
3 changed files with 66 additions and 32 deletions

View File

@ -32,7 +32,7 @@ func EmptyResponseFromMessage(srcMsg *dns.Msg) (*dns.Msg, error) {
return dstMsg, nil
}
func RefusedResponseFromMessage(srcMsg *dns.Msg, refusedCode bool, ip net.IP, ttl uint32) (*dns.Msg, error) {
func RefusedResponseFromMessage(srcMsg *dns.Msg, refusedCode bool, ipv4 net.IP, ipv6 net.IP, ttl uint32) (*dns.Msg, error) {
dstMsg, err := EmptyResponseFromMessage(srcMsg)
if err != nil {
return dstMsg, err
@ -46,24 +46,21 @@ func RefusedResponseFromMessage(srcMsg *dns.Msg, refusedCode bool, ip net.IP, tt
question := questions[0]
sendHInfoResponse := true
if ip != nil {
if question.Qtype == dns.TypeA {
rr := new(dns.A)
rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: ttl}
rr.A = ip.To4()
if rr.A != nil {
dstMsg.Answer = []dns.RR{rr}
sendHInfoResponse = false
}
} else if question.Qtype == dns.TypeAAAA {
rr := new(dns.AAAA)
rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: ttl}
rr.AAAA = ip.To16()
if rr.AAAA != nil {
dstMsg.Answer = []dns.RR{rr}
sendHInfoResponse = false
}
if ipv4 != nil && question.Qtype == dns.TypeA {
rr := new(dns.A)
rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: ttl}
rr.A = ipv4.To4()
if rr.A != nil {
dstMsg.Answer = []dns.RR{rr}
sendHInfoResponse = false
}
} else if ipv6 != nil && question.Qtype == dns.TypeAAAA {
rr := new(dns.AAAA)
rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: ttl}
rr.AAAA = ipv6.To16()
if rr.AAAA != nil {
dstMsg.Answer = []dns.RR{rr}
sendHInfoResponse = false
}
}

View File

@ -112,9 +112,9 @@ keepalive = 30
## Response for blocked queries. Options are `refused`, `hinfo` (default) or
## an IP address (e.g. local pixelserv-tls server). Using the `hinfo` option
## means that some responses will be lies. Unfortunately, the `hinfo` option
## appears to be required for Android 8+
## an IP response. To give an IP response, use the format `a:<IPv4>,aaaa:<IPv6>`.
## Using the `hinfo` option means that some responses will be lies.
## Unfortunately, the `hinfo` option appears to be required for Android 8+
# blocked_query_response = 'refused'

View File

@ -3,6 +3,7 @@ package main
import (
"errors"
"net"
"strings"
"sync"
"time"
@ -26,7 +27,8 @@ type PluginsGlobals struct {
responsePlugins *[]Plugin
loggingPlugins *[]Plugin
refusedCodeInResponses bool
respondWithIP net.IP
respondWithIPv4 net.IP
respondWithIPv6 net.IP
}
type PluginsReturnCode int
@ -137,21 +139,56 @@ func InitPluginsGlobals(pluginsGlobals *PluginsGlobals, proxy *Proxy) error {
(*pluginsGlobals).responsePlugins = responsePlugins
(*pluginsGlobals).loggingPlugins = loggingPlugins
// blockedQueryResponse can be 'refused', 'hinfo' or an IP address
(*pluginsGlobals).respondWithIP = net.ParseIP(proxy.blockedQueryResponse)
if (*pluginsGlobals).respondWithIP == nil {
switch proxy.blockedQueryResponse {
parseBlockedQueryResponse(proxy.blockedQueryResponse, pluginsGlobals)
return nil
}
// blockedQueryResponse can be 'refused', 'hinfo' or IP responses 'a:IPv4,aaaa:IPv6
func parseBlockedQueryResponse(bockedResponse string, pluginsGlobals *PluginsGlobals) {
bockedResponse = strings.ReplaceAll(strings.ToLower(bockedResponse), " ", "")
if strings.HasPrefix(bockedResponse, "a:") {
blockedIPStrings := strings.Split(bockedResponse, ",")
(*pluginsGlobals).respondWithIPv4 = net.ParseIP(strings.TrimPrefix(blockedIPStrings[0], "a:"))
if (*pluginsGlobals).respondWithIPv4 == nil {
dlog.Notice("Error parsing IPv4 response given in blocked_query_response option, defaulting to `hinfo`")
(*pluginsGlobals).refusedCodeInResponses = false
return
}
if len(blockedIPStrings) > 1 {
if strings.HasPrefix(blockedIPStrings[1], "aaaa:") {
ipv6Response := strings.TrimPrefix(blockedIPStrings[1], "aaaa:")
if strings.HasPrefix(ipv6Response, "[") {
ipv6Response = strings.Trim(ipv6Response, "[]")
}
(*pluginsGlobals).respondWithIPv6 = net.ParseIP(ipv6Response)
if (*pluginsGlobals).respondWithIPv6 == nil {
dlog.Notice("Error parsing IPv6 response given in blocked_query_response option, defaulting to IPv4")
}
} else {
dlog.Noticef("Invalid IPv6 response given in blocked_query_response option [%s], the option should take the form 'a:<IPv4>,aaaa:<IPv6>'", blockedIPStrings[1])
}
}
if (*pluginsGlobals).respondWithIPv6 == nil {
(*pluginsGlobals).respondWithIPv6 = (*pluginsGlobals).respondWithIPv4
}
} else {
switch bockedResponse {
case "refused":
(*pluginsGlobals).refusedCodeInResponses = true
case "hinfo":
(*pluginsGlobals).refusedCodeInResponses = false
default:
dlog.Noticef("Invalid blocked_query_response option [%s], defaulting to `hinfo`", proxy.blockedQueryResponse)
dlog.Noticef("Invalid blocked_query_response option [%s], defaulting to `hinfo`", bockedResponse)
(*pluginsGlobals).refusedCodeInResponses = false
}
}
return nil
}
type Plugin interface {
@ -201,7 +238,7 @@ func (pluginsState *PluginsState) ApplyQueryPlugins(pluginsGlobals *PluginsGloba
return packet, ret
}
if pluginsState.action == PluginsActionReject {
synth, err := RefusedResponseFromMessage(&msg, pluginsGlobals.refusedCodeInResponses, pluginsGlobals.respondWithIP, pluginsState.cacheMinTTL)
synth, err := RefusedResponseFromMessage(&msg, pluginsGlobals.refusedCodeInResponses, pluginsGlobals.respondWithIPv4, pluginsGlobals.respondWithIPv6, pluginsState.cacheMinTTL)
if err != nil {
return nil, err
}
@ -249,7 +286,7 @@ func (pluginsState *PluginsState) ApplyResponsePlugins(pluginsGlobals *PluginsGl
return packet, ret
}
if pluginsState.action == PluginsActionReject {
synth, err := RefusedResponseFromMessage(&msg, pluginsGlobals.refusedCodeInResponses, pluginsGlobals.respondWithIP, pluginsState.cacheMinTTL)
synth, err := RefusedResponseFromMessage(&msg, pluginsGlobals.refusedCodeInResponses, pluginsGlobals.respondWithIPv4, pluginsGlobals.respondWithIPv6, pluginsState.cacheMinTTL)
if err != nil {
return nil, err
}