add new option: 'respond_with_ip'

This commit is contained in:
James Newell 2019-06-09 14:15:38 -05:00 committed by Frank Denis
parent e43b85d9f9
commit 87bbfbfc10
6 changed files with 48 additions and 9 deletions

1
.gitignore vendored
View file

@ -9,3 +9,4 @@
*~ *~
dnscrypt-proxy/dnscrypt-proxy2 dnscrypt-proxy/dnscrypt-proxy2
dnscrypt-proxy/dnscrypt-proxy dnscrypt-proxy/dnscrypt-proxy
.idea

View file

@ -81,6 +81,7 @@ type Config struct {
OfflineMode bool `toml:"offline_mode"` OfflineMode bool `toml:"offline_mode"`
HTTPProxyURL string `toml:"http_proxy"` HTTPProxyURL string `toml:"http_proxy"`
RefusedCodeInResponses bool `toml:"refused_code_in_responses"` RefusedCodeInResponses bool `toml:"refused_code_in_responses"`
RespondWithIP string `toml:"respond_with_ip"`
} }
func newConfig() Config { func newConfig() Config {
@ -291,6 +292,7 @@ func ConfigLoad(proxy *Proxy, svcFlag *string) error {
proxy.xTransport.rebuildTransport() proxy.xTransport.rebuildTransport()
proxy.refusedCodeInResponses = config.RefusedCodeInResponses proxy.refusedCodeInResponses = config.RefusedCodeInResponses
proxy.respondWithIP = config.RespondWithIP
proxy.timeout = time.Duration(config.Timeout) * time.Millisecond proxy.timeout = time.Duration(config.Timeout) * time.Millisecond
proxy.maxClients = config.MaxClients proxy.maxClients = config.MaxClients
proxy.mainProto = "udp" proxy.mainProto = "udp"

View file

@ -2,6 +2,7 @@ package main
import ( import (
"encoding/binary" "encoding/binary"
"net"
"strings" "strings"
"time" "time"
@ -31,7 +32,7 @@ func EmptyResponseFromMessage(srcMsg *dns.Msg) (*dns.Msg, error) {
return dstMsg, nil return dstMsg, nil
} }
func RefusedResponseFromMessage(srcMsg *dns.Msg, refusedCode bool) (*dns.Msg, error) { func RefusedResponseFromMessage(srcMsg *dns.Msg, refusedCode bool, ip 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
@ -42,12 +43,38 @@ func RefusedResponseFromMessage(srcMsg *dns.Msg, refusedCode bool) (*dns.Msg, er
dstMsg.Rcode = dns.RcodeSuccess dstMsg.Rcode = dns.RcodeSuccess
questions := srcMsg.Question questions := srcMsg.Question
if len(questions) > 0 { if len(questions) > 0 {
hinfo := new(dns.HINFO) question := questions[0]
hinfo.Hdr = dns.RR_Header{Name: questions[0].Name, Rrtype: dns.TypeHINFO, sendHInfoResponse := true
Class: dns.ClassINET, Ttl: 1}
hinfo.Cpu = "This query has been locally blocked" if ip != nil {
hinfo.Os = "by dnscrypt-proxy" if question.Qtype == dns.TypeA {
dstMsg.Answer = []dns.RR{hinfo} 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 sendHInfoResponse {
hinfo := new(dns.HINFO)
hinfo.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypeHINFO,
Class: dns.ClassINET, Ttl: 1}
hinfo.Cpu = "This query has been locally blocked"
hinfo.Os = "by dnscrypt-proxy"
dstMsg.Answer = []dns.RR{hinfo}
}
} }
} }
return dstMsg, nil return dstMsg, nil

View file

@ -117,6 +117,12 @@ keepalive = 30
refused_code_in_responses = false refused_code_in_responses = false
## If refused_code_in_responses is `false`, use this optional setting
## to redirect blocked respones to an IP address (e.g. pixelserv-tls)
## instead of returning an HINFO record
# respond_with_ip = '192.168.1.4'
## Load-balancing strategy: 'p2' (default), 'ph', 'first' or 'random' ## Load-balancing strategy: 'p2' (default), 'ph', 'first' or 'random'

View file

@ -26,6 +26,7 @@ type PluginsGlobals struct {
responsePlugins *[]Plugin responsePlugins *[]Plugin
loggingPlugins *[]Plugin loggingPlugins *[]Plugin
refusedCodeInResponses bool refusedCodeInResponses bool
respondWithIP net.IP
} }
type PluginsReturnCode int type PluginsReturnCode int
@ -136,6 +137,7 @@ func InitPluginsGlobals(pluginsGlobals *PluginsGlobals, proxy *Proxy) error {
(*pluginsGlobals).responsePlugins = responsePlugins (*pluginsGlobals).responsePlugins = responsePlugins
(*pluginsGlobals).loggingPlugins = loggingPlugins (*pluginsGlobals).loggingPlugins = loggingPlugins
(*pluginsGlobals).refusedCodeInResponses = proxy.refusedCodeInResponses (*pluginsGlobals).refusedCodeInResponses = proxy.refusedCodeInResponses
(*pluginsGlobals).respondWithIP = net.ParseIP(proxy.respondWithIP)
return nil return nil
} }
@ -186,7 +188,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) synth, err := RefusedResponseFromMessage(&msg, pluginsGlobals.refusedCodeInResponses, pluginsGlobals.respondWithIP, pluginsState.cacheMinTTL)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -234,7 +236,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) synth, err := RefusedResponseFromMessage(&msg, pluginsGlobals.refusedCodeInResponses, pluginsGlobals.respondWithIP, pluginsState.cacheMinTTL)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -64,6 +64,7 @@ type Proxy struct {
logMaxAge int logMaxAge int
logMaxBackups int logMaxBackups int
refusedCodeInResponses bool refusedCodeInResponses bool
respondWithIP string
showCerts bool showCerts bool
} }