From f4346691bc4d8297ee2e5f276a8c2503309625ca Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Wed, 10 Jan 2018 09:04:03 +0100 Subject: [PATCH] Transform queries via an initial edns mangling plugin Yet another thing that was utterly broken in dnscrypt-proxy v1.x --- dnscrypt-proxy/main.go | 2 ++ dnscrypt-proxy/plugins.go | 63 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 dnscrypt-proxy/plugins.go diff --git a/dnscrypt-proxy/main.go b/dnscrypt-proxy/main.go index ebc8ebc2..a81f8f13 100644 --- a/dnscrypt-proxy/main.go +++ b/dnscrypt-proxy/main.go @@ -138,6 +138,8 @@ func (proxy *Proxy) processIncomingQuery(serverInfo *ServerInfo, serverProto str if len(query) < MinDNSPacketSize { return } + pluginsState := NewPluginsState() + query, _ = pluginsState.ApplyQueryPlugins(query) encryptedQuery, clientNonce, err := proxy.Encrypt(serverInfo, query, serverProto) if err != nil { return diff --git a/dnscrypt-proxy/plugins.go b/dnscrypt-proxy/plugins.go new file mode 100644 index 00000000..c5853355 --- /dev/null +++ b/dnscrypt-proxy/plugins.go @@ -0,0 +1,63 @@ +package main + +import ( + "github.com/miekg/dns" +) + +type PluginsAction int + +const ( + PluginsActionNone = 0 + PluginsActionForward = 1 +) + +type PluginsState struct { + sessionData map[string]interface{} + action PluginsAction + originalMaxPayloadSize int + maxPayloadSize int + proto string +} + +func NewPluginsState() PluginsState { + return PluginsState{action: PluginsActionForward, maxPayloadSize: MaxDNSUDPPacketSize - ResponseOverhead} +} + +func (pluginsState *PluginsState) ApplyQueryPlugins(packet []byte) ([]byte, error) { + msg := dns.Msg{} + if err := msg.Unpack(packet); err != nil { + return packet, err + } + + if ret := pluginsState.BuiltinPluginsGetSetPayloadSize(&msg); ret != nil { + return packet, ret + } + + packet2, err := msg.PackBuffer(packet) + if err != nil { + return packet, err + } + return packet2, nil +} + +func (pluginsState *PluginsState) BuiltinPluginsGetSetPayloadSize(msg *dns.Msg) error { + pluginsState.originalMaxPayloadSize = 512 - ResponseOverhead + opt := msg.IsEdns0() + dnssec := false + if opt != nil { + pluginsState.originalMaxPayloadSize = Min(int(opt.UDPSize())-ResponseOverhead, pluginsState.originalMaxPayloadSize) + dnssec = opt.Do() + } + pluginsState.maxPayloadSize = Min(MaxDNSUDPPacketSize-ResponseOverhead, Max(pluginsState.originalMaxPayloadSize, pluginsState.maxPayloadSize)) + if pluginsState.maxPayloadSize > 512 { + extra2 := []dns.RR{} + for _, extra := range msg.Extra { + if extra.Header().Rrtype != dns.TypeOPT { + extra2 = append(extra2, extra) + } + } + msg.Extra = extra2 + msg.SetEdns0(uint16(pluginsState.maxPayloadSize), dnssec) + } + return nil +}