Implement the IPv6 block plugin
This commit is contained in:
parent
fb16eadb24
commit
f283105866
|
@ -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)
|
||||||
|
|
|
@ -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 ##############
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue