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 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) dstMsg, err := EmptyResponseFromMessage(srcMsg)
if err != nil { if err != nil {
return dstMsg, err return dstMsg, err
@ -46,24 +46,21 @@ func RefusedResponseFromMessage(srcMsg *dns.Msg, refusedCode bool, ip net.IP, tt
question := questions[0] question := questions[0]
sendHInfoResponse := true sendHInfoResponse := true
if ip != nil { if ipv4 != nil && question.Qtype == dns.TypeA {
if question.Qtype == dns.TypeA { rr := new(dns.A)
rr := new(dns.A) rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: ttl}
rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: ttl} rr.A = ipv4.To4()
rr.A = ip.To4() if rr.A != nil {
if rr.A != nil { dstMsg.Answer = []dns.RR{rr}
dstMsg.Answer = []dns.RR{rr} sendHInfoResponse = false
sendHInfoResponse = false }
} } else if ipv6 != nil && question.Qtype == dns.TypeAAAA {
rr := new(dns.AAAA)
} else if question.Qtype == dns.TypeAAAA { rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: ttl}
rr := new(dns.AAAA) rr.AAAA = ipv6.To16()
rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: ttl} if rr.AAAA != nil {
rr.AAAA = ip.To16() dstMsg.Answer = []dns.RR{rr}
if rr.AAAA != nil { sendHInfoResponse = false
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 ## Response for blocked queries. Options are `refused`, `hinfo` (default) or
## an IP address (e.g. local pixelserv-tls server). Using the `hinfo` option ## an IP response. To give an IP response, use the format `a:<IPv4>,aaaa:<IPv6>`.
## means that some responses will be lies. Unfortunately, the `hinfo` option ## Using the `hinfo` option means that some responses will be lies.
## appears to be required for Android 8+ ## Unfortunately, the `hinfo` option appears to be required for Android 8+
# blocked_query_response = 'refused' # blocked_query_response = 'refused'

View File

@ -3,6 +3,7 @@ package main
import ( import (
"errors" "errors"
"net" "net"
"strings"
"sync" "sync"
"time" "time"
@ -26,7 +27,8 @@ type PluginsGlobals struct {
responsePlugins *[]Plugin responsePlugins *[]Plugin
loggingPlugins *[]Plugin loggingPlugins *[]Plugin
refusedCodeInResponses bool refusedCodeInResponses bool
respondWithIP net.IP respondWithIPv4 net.IP
respondWithIPv6 net.IP
} }
type PluginsReturnCode int type PluginsReturnCode int
@ -137,21 +139,56 @@ func InitPluginsGlobals(pluginsGlobals *PluginsGlobals, proxy *Proxy) error {
(*pluginsGlobals).responsePlugins = responsePlugins (*pluginsGlobals).responsePlugins = responsePlugins
(*pluginsGlobals).loggingPlugins = loggingPlugins (*pluginsGlobals).loggingPlugins = loggingPlugins
// blockedQueryResponse can be 'refused', 'hinfo' or an IP address parseBlockedQueryResponse(proxy.blockedQueryResponse, pluginsGlobals)
(*pluginsGlobals).respondWithIP = net.ParseIP(proxy.blockedQueryResponse)
if (*pluginsGlobals).respondWithIP == nil { return nil
switch proxy.blockedQueryResponse { }
// 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": case "refused":
(*pluginsGlobals).refusedCodeInResponses = true (*pluginsGlobals).refusedCodeInResponses = true
case "hinfo": case "hinfo":
(*pluginsGlobals).refusedCodeInResponses = false (*pluginsGlobals).refusedCodeInResponses = false
default: 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 (*pluginsGlobals).refusedCodeInResponses = false
} }
} }
return nil
} }
type Plugin interface { type Plugin interface {
@ -201,7 +238,7 @@ func (pluginsState *PluginsState) ApplyQueryPlugins(pluginsGlobals *PluginsGloba
return packet, ret return packet, ret
} }
if pluginsState.action == PluginsActionReject { 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 { if err != nil {
return nil, err return nil, err
} }
@ -249,7 +286,7 @@ func (pluginsState *PluginsState) ApplyResponsePlugins(pluginsGlobals *PluginsGl
return packet, ret return packet, ret
} }
if pluginsState.action == PluginsActionReject { 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 { if err != nil {
return nil, err return nil, err
} }