]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
auth dnsproxy: make local port range configurable 14591/head
authorChris Hofstaedtler <chris.hofstaedtler@deduktiva.com>
Tue, 27 Aug 2024 09:17:34 +0000 (11:17 +0200)
committerChris Hofstaedtler <chris.hofstaedtler@deduktiva.com>
Tue, 27 Aug 2024 09:23:08 +0000 (11:23 +0200)
docs/settings.rst
pdns/auth-main.cc
pdns/dnsproxy.cc
pdns/dnsproxy.hh

index 5acfc0c4b964c6112018f3aa2b81b11fff4f4dbc..a2ac0037df0e1619594a7efb9098d366d64f03a1 100644 (file)
@@ -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``
index 691242143f2ea41804c49dd17cac2f892b8571c8..72e05c9e6e7fd0b92b10172d6f8fad79468c4512 100644 (file)
@@ -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<DNSProxy>(::arg()["resolver"]);
+    DP = std::make_unique<DNSProxy>(::arg()["resolver"], ::arg()["dnsproxy-udp-port-range"]);
     DP->go();
   }
 
index 19adff21cb16a1d441fee362517d97f4f3eba21e..8c14559c92ecaf46c3377c9655180b1c880309d2 100644 (file)
 #include "ednsoptions.hh"
 #include "ednssubnet.hh"
 
+#include <boost/uuid/uuid_io.hpp>
+
 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<string> 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<DNSPacket>& reply, const DNSName& target, const DNSName& aname, const uint8_t scopeMask)
 {
   string ECSOptionStr;
index 0ce1eefd1d61b1ad011f5624b24027f4599a53d4..b5ec5de136420cb6bf6347c024dea1c52b814d24 100644 (file)
@@ -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(); //<! dtor for DNSProxy
   void go(); //!< launches the actual thread
   bool completePacket(std::unique_ptr<DNSPacket>& reply, const DNSName& target, const DNSName& aname, uint8_t scopeMask);