diff --git a/docs/settings.rst b/docs/settings.rst index 5acfc0c4b964..a2ac0037df0e 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -633,6 +633,20 @@ approximately doubles query load. If this is turned off, DNAME records are treated as any other and served only when queried explicitly. +.. _setting-dnsproxy-udp-port-range: + +``dnsproxy-udp-port-range`` +--------------------------- + +- String +- Default: `10000 60000` + +If :ref:`setting-resolver` enables the DNS Proxy, this setting limits the +port range the DNS Proxy's UDP port is chosen from. + +Default should be fine on most installs, but if you have conflicting local +services, you may choose to limit the range. + .. _setting-dnssec-key-cache-ttl: ``dnssec-key-cache-ttl`` diff --git a/pdns/auth-main.cc b/pdns/auth-main.cc index 691242143f2e..72e05c9e6e7f 100644 --- a/pdns/auth-main.cc +++ b/pdns/auth-main.cc @@ -205,6 +205,7 @@ static void declareArguments() ::arg().set("receiver-threads", "Default number of receiver threads to start") = "1"; ::arg().set("queue-limit", "Maximum number of milliseconds to queue a query") = "1500"; ::arg().set("resolver", "Use this resolver for ALIAS and the internal stub resolver") = "no"; + ::arg().set("dnsproxy-udp-port-range", "Select DNS Proxy outgoing UDP port from given range (lower upper)") = "10000 60000"; ::arg().set("udp-truncation-threshold", "Maximum UDP response size before we truncate") = "1232"; ::arg().set("config-name", "Name of this virtual configuration - will rename the binary image") = ""; @@ -786,7 +787,7 @@ static void mainthread() Utility::dropUserPrivs(newuid); if (::arg().mustDo("resolver")) { - DP = std::make_unique(::arg()["resolver"]); + DP = std::make_unique(::arg()["resolver"], ::arg()["dnsproxy-udp-port-range"]); DP->go(); } diff --git a/pdns/dnsproxy.cc b/pdns/dnsproxy.cc index 19adff21cb16..8c14559c92ec 100644 --- a/pdns/dnsproxy.cc +++ b/pdns/dnsproxy.cc @@ -40,9 +40,11 @@ #include "ednsoptions.hh" #include "ednssubnet.hh" +#include + extern StatBag S; -DNSProxy::DNSProxy(const string& remote) : +DNSProxy::DNSProxy(const string& remote, const string& udpPortRange) : d_xor(dns_random_uint16()) { d_resanswers = S.getPointer("recursing-answers"); @@ -53,6 +55,20 @@ DNSProxy::DNSProxy(const string& remote) : stringtok(addresses, remote, " ,\t"); d_remote = ComboAddress(addresses[0], 53); + vector parts; + stringtok(parts, udpPortRange, " "); + if (parts.size() != 2) { + throw PDNSException("DNS Proxy UDP port range must contain exactly one lower and one upper bound"); + } + unsigned long portRangeLow = std::stoul(parts.at(0)); + unsigned long portRangeHigh = std::stoul(parts.at(1)); + if (portRangeLow < 1 || portRangeHigh > 65535) { + throw PDNSException("DNS Proxy UDP port range values out of valid port bounds (1 to 65535)"); + } + if (portRangeLow >= portRangeHigh) { + throw PDNSException("DNS Proxy UDP port range upper bound " + std::to_string(portRangeHigh) + " must be higher than lower bound (" + std::to_string(portRangeLow) + ")"); + } + if ((d_sock = socket(d_remote.sin4.sin_family, SOCK_DGRAM, 0)) < 0) { throw PDNSException(string("socket: ") + stringerror()); } @@ -67,7 +83,7 @@ DNSProxy::DNSProxy(const string& remote) : unsigned int attempts = 0; for (; attempts < 10; attempts++) { - local.sin4.sin_port = htons(10000 + dns_random(50000)); + local.sin4.sin_port = htons(portRangeLow + dns_random(portRangeHigh - portRangeLow)); if (::bind(d_sock, (struct sockaddr*)&local, local.getSocklen()) >= 0) { // NOLINT(cppcoreguidelines-pro-type-cstyle-cast) break; @@ -92,7 +108,7 @@ void DNSProxy::go() proxythread.detach(); } -//! look up qname target with r->qtype, plonk it in the answer section of 'r' with name aname +//! look up qname 'target' with reply->qtype, plonk it in the answer section of 'reply' with name 'aname' bool DNSProxy::completePacket(std::unique_ptr& reply, const DNSName& target, const DNSName& aname, const uint8_t scopeMask) { string ECSOptionStr; diff --git a/pdns/dnsproxy.hh b/pdns/dnsproxy.hh index 0ce1eefd1d61..b5ec5de13642 100644 --- a/pdns/dnsproxy.hh +++ b/pdns/dnsproxy.hh @@ -49,7 +49,7 @@ To fix: how to remove the stale entries that will surely accumulate class DNSProxy { public: - DNSProxy(const string& remote); //!< creates socket + DNSProxy(const string& remote, const string& udpPortRange); //!< creates socket ~DNSProxy(); //& reply, const DNSName& target, const DNSName& aname, uint8_t scopeMask);