Implement the IPv6 block plugin

This commit is contained in:
Frank Denis 2018-01-10 17:23:20 +01:00
parent fb16eadb24
commit f283105866
5 changed files with 88 additions and 15 deletions

View File

@ -17,6 +17,7 @@ type Config struct {
ForceTCP bool `toml:"force_tcp"` ForceTCP bool `toml:"force_tcp"`
Timeout int `toml:"timeout_ms"` Timeout int `toml:"timeout_ms"`
CertRefreshDelay int `toml:"cert_refresh_delay"` CertRefreshDelay int `toml:"cert_refresh_delay"`
BlockIPv6 bool `toml:"block_ipv6"`
ServersConfig map[string]ServerConfig `toml:"servers"` ServersConfig map[string]ServerConfig `toml:"servers"`
} }
@ -56,6 +57,7 @@ func ConfigLoad(proxy *Proxy, config_file string) error {
} }
proxy.listenAddresses = config.ListenAddresses proxy.listenAddresses = config.ListenAddresses
proxy.daemonize = config.Daemonize proxy.daemonize = config.Daemonize
proxy.pluginBlockIPv6 = config.BlockIPv6
if len(config.ServerNames) == 0 { if len(config.ServerNames) == 0 {
for serverName := range config.ServersConfig { for serverName := range config.ServersConfig {
config.ServerNames = append(config.ServerNames, serverName) config.ServerNames = append(config.ServerNames, serverName)

View File

@ -40,6 +40,13 @@ timeout = 2500
cert_refresh_delay = 30 cert_refresh_delay = 30
############## Filters ##############
## Immediately respond to IPv6-related queries with an empty response
## This makes things faster when there is no IPv6 connectivity
block_ipv6 = false
############## Servers ############## ############## Servers ##############

View File

@ -18,6 +18,15 @@ func TruncatedResponse(packet []byte) ([]byte, error) {
return dstMsg.Pack() return dstMsg.Pack()
} }
func EmptyResponseFromMessage(srcMsg *dns.Msg) (*dns.Msg, error) {
dstMsg := srcMsg
dstMsg.Response = true
dstMsg.Answer = make([]dns.RR, 0)
dstMsg.Ns = make([]dns.RR, 0)
dstMsg.Extra = make([]dns.RR, 0)
return dstMsg, nil
}
func HasTCFlag(packet []byte) bool { func HasTCFlag(packet []byte) bool {
return packet[2]&2 == 2 return packet[2]&2 == 2
} }

View File

@ -23,6 +23,7 @@ type Proxy struct {
listenAddresses []string listenAddresses []string
daemonize bool daemonize bool
registeredServers []RegisteredServer registeredServers []RegisteredServer
pluginBlockIPv6 bool
} }
func main() { func main() {
@ -163,22 +164,33 @@ func (proxy *Proxy) processIncomingQuery(serverInfo *ServerInfo, serverProto str
if clientAddr == nil { if clientAddr == nil {
clientProto = "tcp" clientProto = "tcp"
} }
pluginsState := NewPluginsState(clientProto) pluginsState := NewPluginsState(proxy, clientProto)
query, _ = pluginsState.ApplyQueryPlugins(query) query, _ = pluginsState.ApplyQueryPlugins(query)
encryptedQuery, clientNonce, err := proxy.Encrypt(serverInfo, query, serverProto)
if err != nil {
return
}
serverInfo.noticeBegin(proxy)
var response []byte var response []byte
if serverProto == "udp" { var err error
response, err = proxy.exchangeWithUDPServer(serverInfo, encryptedQuery, clientNonce) if pluginsState.action != PluginsActionForward {
} else { if pluginsState.synthResponse != nil {
response, err = proxy.exchangeWithTCPServer(serverInfo, encryptedQuery, clientNonce) response, err = pluginsState.synthResponse.PackBuffer(response)
if err != nil {
return
}
}
} }
if err != nil { if len(response) == 0 {
serverInfo.noticeFailure(proxy) encryptedQuery, clientNonce, err := proxy.Encrypt(serverInfo, query, serverProto)
return if err != nil {
return
}
serverInfo.noticeBegin(proxy)
if serverProto == "udp" {
response, err = proxy.exchangeWithUDPServer(serverInfo, encryptedQuery, clientNonce)
} else {
response, err = proxy.exchangeWithTCPServer(serverInfo, encryptedQuery, clientNonce)
}
if err != nil {
serverInfo.noticeFailure(proxy)
return
}
} }
if clientAddr != nil { if clientAddr != nil {
if len(response) > MaxDNSUDPPacketSize { if len(response) > MaxDNSUDPPacketSize {

View File

@ -11,6 +11,7 @@ const (
PluginsActionForward = 1 PluginsActionForward = 1
PluginsActionDrop = 2 PluginsActionDrop = 2
PluginsActionReject = 3 PluginsActionReject = 3
PluginsActionSynth = 4
) )
type PluginsState struct { type PluginsState struct {
@ -21,6 +22,7 @@ type PluginsState struct {
proto string proto string
queryPlugins *[]Plugin queryPlugins *[]Plugin
responsePlugins *[]Plugin responsePlugins *[]Plugin
synthResponse *dns.Msg
} }
type Plugin interface { type Plugin interface {
@ -29,9 +31,15 @@ type Plugin interface {
Eval(pluginsState *PluginsState, msg *dns.Msg) error Eval(pluginsState *PluginsState, msg *dns.Msg) error
} }
func NewPluginsState(proto string) PluginsState { func NewPluginsState(proxy *Proxy, proto string) PluginsState {
queryPlugins := &[]Plugin{Plugin(new(PluginGetSetPayloadSize))} queryPlugins := &[]Plugin{}
if proxy.pluginBlockIPv6 {
*queryPlugins = append(*queryPlugins, Plugin(new(PluginBlockIPv6)))
}
*queryPlugins = append(*queryPlugins, Plugin(new(PluginGetSetPayloadSize)))
responsePlugins := &[]Plugin{} responsePlugins := &[]Plugin{}
return PluginsState{action: PluginsActionForward, maxPayloadSize: MaxDNSUDPPacketSize - ResponseOverhead, return PluginsState{action: PluginsActionForward, maxPayloadSize: MaxDNSUDPPacketSize - ResponseOverhead,
queryPlugins: queryPlugins, responsePlugins: responsePlugins, proto: proto} queryPlugins: queryPlugins, responsePlugins: responsePlugins, proto: proto}
} }
@ -47,6 +55,9 @@ func (pluginsState *PluginsState) ApplyQueryPlugins(packet []byte) ([]byte, erro
pluginsState.action = PluginsActionDrop pluginsState.action = PluginsActionDrop
return packet, ret return packet, ret
} }
if pluginsState.action != PluginsActionForward {
break
}
} }
packet2, err := msg.PackBuffer(packet) packet2, err := msg.PackBuffer(packet)
if err != nil { if err != nil {
@ -55,6 +66,8 @@ func (pluginsState *PluginsState) ApplyQueryPlugins(packet []byte) ([]byte, erro
return packet2, nil return packet2, nil
} }
// -------- get_set_payload_size plugin --------
type PluginGetSetPayloadSize struct{} type PluginGetSetPayloadSize struct{}
func (plugin *PluginGetSetPayloadSize) Name() string { func (plugin *PluginGetSetPayloadSize) Name() string {
@ -86,3 +99,33 @@ func (plugin *PluginGetSetPayloadSize) Eval(pluginsState *PluginsState, msg *dns
} }
return nil return nil
} }
// -------- block_ipv6 plugin --------
type PluginBlockIPv6 struct{}
func (plugin *PluginBlockIPv6) Name() string {
return "block_ipv6"
}
func (plugin *PluginBlockIPv6) Description() string {
return "Immediately return a synthetic response to AAAA queries"
}
func (plugin *PluginBlockIPv6) Eval(pluginsState *PluginsState, msg *dns.Msg) error {
questions := msg.Question
if len(questions) != 1 {
return nil
}
question := questions[0]
if question.Qclass != dns.ClassINET || question.Qtype != dns.TypeAAAA {
return nil
}
synth, err := EmptyResponseFromMessage(msg)
if err != nil {
return err
}
pluginsState.synthResponse = synth
pluginsState.action = PluginsActionSynth
return nil
}