From c27d41faa0edf3950fb228c4b6800aabf01c0448 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Mon, 23 Dec 2019 11:37:45 +0100 Subject: [PATCH] Avoid unneeded DNS packet unpacking --- dnscrypt-proxy/dnsutils.go | 16 ++++------------ dnscrypt-proxy/plugins.go | 8 +++++++- dnscrypt-proxy/proxy.go | 4 +++- dnscrypt-proxy/xtransport.go | 11 ++--------- 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/dnscrypt-proxy/dnsutils.go b/dnscrypt-proxy/dnsutils.go index c96579d5..e8f82b36 100644 --- a/dnscrypt-proxy/dnsutils.go +++ b/dnscrypt-proxy/dnsutils.go @@ -209,33 +209,25 @@ func updateTTL(msg *dns.Msg, expiration time.Time) { } } -func addEDNS0PaddingIfNoneFound(packet *[]byte, paddingLen int) *[]byte { - msg := dns.Msg{Compress: true} - if msg.Unpack(*packet) != nil { - return packet - } +func addEDNS0PaddingIfNoneFound(msg *dns.Msg, unpaddedPacket []byte, paddingLen int) ([]byte, error) { edns0 := msg.IsEdns0() if edns0 == nil { msg.SetEdns0(uint16(MaxDNSPacketSize), false) edns0 = msg.IsEdns0() if edns0 == nil { - return packet + return unpaddedPacket, nil } } for _, option := range edns0.Option { if option.Option() == dns.EDNS0PADDING { - return packet + return unpaddedPacket, nil } } ext := new(dns.EDNS0_PADDING) padding := []byte("dnscrypt-proxy.padding:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmno") ext.Padding = padding[:paddingLen] edns0.Option = append(edns0.Option, ext) - paddedPacket, err := msg.Pack() - if err != nil { - return packet - } - return &paddedPacket + return msg.Pack() } func removeEDNS0Options(msg *dns.Msg) bool { diff --git a/dnscrypt-proxy/plugins.go b/dnscrypt-proxy/plugins.go index 74074643..f8e2df65 100644 --- a/dnscrypt-proxy/plugins.go +++ b/dnscrypt-proxy/plugins.go @@ -243,7 +243,7 @@ func NewPluginsState(proxy *Proxy, clientProto string, clientAddr *net.Addr, sta } } -func (pluginsState *PluginsState) ApplyQueryPlugins(pluginsGlobals *PluginsGlobals, packet []byte, serverName string) ([]byte, error) { +func (pluginsState *PluginsState) ApplyQueryPlugins(pluginsGlobals *PluginsGlobals, packet []byte, serverName string, needsEDNS0Padding bool) ([]byte, error) { pluginsState.serverName = serverName msg := dns.Msg{} if err := msg.Unpack(packet); err != nil { @@ -280,6 +280,12 @@ func (pluginsState *PluginsState) ApplyQueryPlugins(pluginsGlobals *PluginsGloba if err != nil { return packet, err } + if needsEDNS0Padding && pluginsState.action == PluginsActionContinue { + padLen := 63 - (len(packet2)+63)&63 + if paddedPacket2, _ := addEDNS0PaddingIfNoneFound(&msg, packet2, padLen); paddedPacket2 != nil { + return paddedPacket2, nil + } + } return packet2, nil } diff --git a/dnscrypt-proxy/proxy.go b/dnscrypt-proxy/proxy.go index eb5382e9..4c3b4484 100644 --- a/dnscrypt-proxy/proxy.go +++ b/dnscrypt-proxy/proxy.go @@ -435,10 +435,12 @@ func (proxy *Proxy) processIncomingQuery(serverInfo *ServerInfo, clientProto str } pluginsState := NewPluginsState(proxy, clientProto, clientAddr, start) serverName := "-" + needsEDNS0Padding := false if serverInfo != nil { serverName = serverInfo.Name + needsEDNS0Padding = (serverInfo.Proto == stamps.StampProtoTypeDoH || serverInfo.Proto == stamps.StampProtoTypeTLS) } - query, _ = pluginsState.ApplyQueryPlugins(&proxy.pluginsGlobals, query, serverName) + query, _ = pluginsState.ApplyQueryPlugins(&proxy.pluginsGlobals, query, serverName, needsEDNS0Padding) if len(query) < MinDNSPacketSize || len(query) > MaxDNSPacketSize { return } diff --git a/dnscrypt-proxy/xtransport.go b/dnscrypt-proxy/xtransport.go index 56df23ca..0d290a7c 100644 --- a/dnscrypt-proxy/xtransport.go +++ b/dnscrypt-proxy/xtransport.go @@ -371,22 +371,15 @@ func (xTransport *XTransport) Post(url *url.URL, accept string, contentType stri } func (xTransport *XTransport) DoHQuery(useGet bool, url *url.URL, body []byte, timeout time.Duration) (*http.Response, time.Duration, error) { - padLen := 63 - (len(body)+63)&63 dataType := "application/dns-message" - paddedBody := addEDNS0PaddingIfNoneFound(&body, padLen) if useGet { qs := url.Query() qs.Add("ct", "") - encBody := base64.RawURLEncoding.EncodeToString(*paddedBody) + encBody := base64.RawURLEncoding.EncodeToString(body) qs.Add("dns", encBody) url2 := *url url2.RawQuery = qs.Encode() return xTransport.Get(&url2, dataType, timeout) } - return xTransport.Post(url, dataType, dataType, paddedBody, timeout) -} - -func (xTransport *XTransport) makePad(padLen int) *string { - padding := strings.Repeat("X", padLen) - return &padding + return xTransport.Post(url, dataType, dataType, &body, timeout) }