From a1b15efe3203e243bcf88ab1c79e38bfa5c41e2b Mon Sep 17 00:00:00 2001 From: bert hubert Date: Wed, 18 Jan 2017 16:18:46 +0100 Subject: [PATCH] add ecs-ipv4-bits and ecs-ipv6-bits tunables for EDNS Client Subnet & document them. Split out ECS code from pdns_recursor.cc. (cherry picked from commit 35695d184316e0686d1dc2d50ef4a4420bc95157) --- docs/markdown/recursor/settings.md | 14 +++++++++++ pdns/pdns_recursor.cc | 31 ++---------------------- pdns/recursordist/Makefile.am | 1 + pdns/recursordist/ecs.cc | 38 ++++++++++++++++++++++++++++++ pdns/syncres.hh | 4 ++++ 5 files changed, 59 insertions(+), 29 deletions(-) create mode 100644 pdns/recursordist/ecs.cc diff --git a/docs/markdown/recursor/settings.md b/docs/markdown/recursor/settings.md index ed654ffdb..f7c2557cb 100644 --- a/docs/markdown/recursor/settings.md +++ b/docs/markdown/recursor/settings.md @@ -228,6 +228,20 @@ your network, and may even be a security risk. Therefore, since version 3.1.5, the PowerDNS recursor by default does not query private space IP addresses. This setting can be used to expand or reduce the limitations. +## `ecs-ipv4-bits` +* Integer +* Default: 24 +* Available since 4.1 + +Number of bits of client IPv4 address to pass when sending EDNS Client Subnet address information. + +## `ecs-ipv6-bits` +* Integer +* Default: 56 +* Available since 4.1 + +Number of bits of client IPv6 address to pass when sending EDNS Client Subnet address information. + ## `edns-outgoing-bufsize` * Integer * Default: 1680 diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index e659c9692..5f8d09673 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -113,8 +113,6 @@ __thread shared_ptr* t_traceRegex; __thread boost::uuids::random_generator* t_uuidGenerator; #endif -NetmaskGroup g_ednssubnets; -SuffixMatchNode g_ednsdomains; RecursorControlChannel s_rcc; // only active in thread 0 @@ -2562,33 +2560,6 @@ void parseACLs() l_initialized = true; } -boost::optional getEDNSSubnetMask(const ComboAddress& local, const DNSName&dn, const ComboAddress& rem) -{ - if(local.sin4.sin_family != AF_INET || local.sin4.sin_addr.s_addr) { // detect unset 'requestor' - if(g_ednsdomains.check(dn) || g_ednssubnets.match(rem)) { - int bits =local.sin4.sin_family == AF_INET ? 24 : 56; - ComboAddress trunc(local); - trunc.truncate(bits); - return boost::optional(Netmask(trunc, bits)); - } - } - return boost::optional(); -} - -void parseEDNSSubnetWhitelist(const std::string& wlist) -{ - vector parts; - stringtok(parts, wlist, ",; "); - for(const auto& a : parts) { - try { - Netmask nm(a); - g_ednssubnets.addMask(nm); - } - catch(...) { - g_ednsdomains.add(DNSName(a)); - } - } -} std::unordered_set g_delegationOnly; static void setupDelegationOnly() @@ -3081,6 +3052,8 @@ int main(int argc, char **argv) ::arg().set("lua-dns-script", "Filename containing an optional 'lua' script that will be used to modify dns answers")=""; ::arg().set("latency-statistic-size","Number of latency values to calculate the qa-latency average")="10000"; ::arg().setSwitch( "disable-packetcache", "Disable packetcache" )= "no"; + ::arg().set("ecs-ipv4-bits", "Number of bits of IPv4 address to pass for EDNS Client Subnet")="24"; + ::arg().set("ecs-ipv6-bits", "Number of bits of IPv6 address to pass for EDNS Client Subnet")="56"; ::arg().set("edns-subnet-whitelist", "List of netmasks and domains that we should enable EDNS subnet for")=""; ::arg().setSwitch( "pdns-distributes-queries", "If PowerDNS itself should distribute queries over threads")=""; ::arg().setSwitch( "root-nx-trust", "If set, believe that an NXDOMAIN from the root means the TLD does not exist")="yes"; diff --git a/pdns/recursordist/Makefile.am b/pdns/recursordist/Makefile.am index 2899bb37f..8b4b7280f 100644 --- a/pdns/recursordist/Makefile.am +++ b/pdns/recursordist/Makefile.am @@ -89,6 +89,7 @@ pdns_recursor_SOURCES = \ dnssecinfra.hh dnssecinfra.cc \ dnsseckeeper.hh \ dnswriter.cc dnswriter.hh \ + ecs.cc \ ednsoptions.cc ednsoptions.hh \ ednssubnet.cc ednssubnet.hh \ filterpo.cc filterpo.hh \ diff --git a/pdns/recursordist/ecs.cc b/pdns/recursordist/ecs.cc new file mode 100644 index 000000000..431daf450 --- /dev/null +++ b/pdns/recursordist/ecs.cc @@ -0,0 +1,38 @@ +#include "syncres.hh" +#include "arguments.hh" + +NetmaskGroup g_ednssubnets; +SuffixMatchNode g_ednsdomains; + +boost::optional getEDNSSubnetMask(const ComboAddress& local, const DNSName&dn, const ComboAddress& rem) +{ + static int l_ipv4limit, l_ipv6limit; + if(!l_ipv4limit) { + l_ipv4limit = ::arg().asNum("ecs-ipv4-bits"); + l_ipv6limit = ::arg().asNum("ecs-ipv6-bits"); + } + if(local.sin4.sin_family != AF_INET || local.sin4.sin_addr.s_addr) { // detect unset 'requestor' + if(g_ednsdomains.check(dn) || g_ednssubnets.match(rem)) { + int bits = local.sin4.sin_family == AF_INET ? l_ipv4limit : l_ipv6limit; + ComboAddress trunc(local); + trunc.truncate(bits); + return boost::optional(Netmask(trunc, bits)); + } + } + return boost::optional(); +} + +void parseEDNSSubnetWhitelist(const std::string& wlist) +{ + vector parts; + stringtok(parts, wlist, ",; "); + for(const auto& a : parts) { + try { + Netmask nm(a); + g_ednssubnets.addMask(nm); + } + catch(...) { + g_ednsdomains.add(DNSName(a)); + } + } +} diff --git a/pdns/syncres.hh b/pdns/syncres.hh index 698c73b8e..aa043d14c 100644 --- a/pdns/syncres.hh +++ b/pdns/syncres.hh @@ -740,6 +740,10 @@ void parseEDNSSubnetWhitelist(const std::string& wlist); extern __thread struct timeval g_now; +extern NetmaskGroup g_ednssubnets; +extern SuffixMatchNode g_ednsdomains; + + #ifdef HAVE_PROTOBUF extern __thread boost::uuids::random_generator* t_uuidGenerator; #endif -- 2.40.0