]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
recursor: add min-udp-source-port, max-udp-source-port and avoid-udp-source-port...
authorCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Thu, 15 Mar 2018 11:09:47 +0000 (12:09 +0100)
committerCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Thu, 15 Mar 2018 11:09:47 +0000 (12:09 +0100)
pdns/pdns_recursor.cc

index 60fc1ccab78fb7bc76aefa28c10e8d2da54ad67b..602d637e6dbcf61a1983695c0b76a6e21b6b6a51 100644 (file)
@@ -60,6 +60,7 @@
 #include <boost/shared_array.hpp>
 #include <boost/function.hpp>
 #include <boost/algorithm/string.hpp>
+#include <boost/container/flat_set.hpp>
 #ifdef MALLOC_TRACE
 #include "malloctrace.hh"
 #endif
@@ -160,6 +161,9 @@ static bool g_gettagNeedsEDNSOptions{false};
 static time_t g_statisticsInterval;
 static bool g_useIncomingECS;
 std::atomic<uint32_t> g_maxCacheEntries, g_maxPacketCacheEntries;
+static boost::container::flat_set<uint16_t> s_avoidUdpSourcePorts;
+static uint16_t s_minUdpSourcePort;
+static uint16_t s_maxUdpSourcePort;
 
 RecursorControlChannel s_rcc; // only active in thread 0
 RecursorStats g_stats;
@@ -516,8 +520,12 @@ public:
 
       if(tries==1)  // fall back to kernel 'random'
         port = 0;
-      else
-        port = 1025 + dns_random(64510);
+      else {
+        do {
+          port = s_minUdpSourcePort + dns_random(s_maxUdpSourcePort - s_minUdpSourcePort + 1);
+        }
+        while (s_avoidUdpSourcePorts.count(port));
+      }
 
       sin=getQueryLocalAddress(family, port); // does htons for us
 
@@ -3199,6 +3207,30 @@ static int serviceMain(int argc, char*argv[])
     g_snmpAgent->run();
   }
 
+  int port = ::arg().asNum("min-udp-source-port");
+  if(port < 1025 || port > 65535){
+    L<<Logger::Error<<"Unable to launch, min-udp-source-port is not a valid port number"<<endl;
+    exit(99); // this isn't going to fix itself either
+  }
+  s_minUdpSourcePort = port;
+  port = ::arg().asNum("max-udp-source-port");
+  if(port < 1025 || port > 65535 || port < s_minUdpSourcePort){
+    L<<Logger::Error<<"Unable to launch, max-udp-source-port is not a valid port number or is smaller than min-udp-source-port"<<endl;
+    exit(99); // this isn't going to fix itself either
+  }
+  s_maxUdpSourcePort = port;
+  std::vector<string> parts {};
+  stringtok(parts, ::arg()["avoid-udp-source-port"], ", ");
+  for (const auto &part : parts)
+  {
+    port = std::stoi(part);
+    if(port < 1025 || port > 65535){
+      L<<Logger::Error<<"Unable to launch, avoid-udp-source-port contains an invalid port number: "<<part<<endl;
+      exit(99); // this isn't going to fix itself either
+    }
+    s_avoidUdpSourcePorts.insert(port);
+  }
+
   const auto cpusMap = parseCPUMap();
   if(g_numThreads == 1) {
     L<<Logger::Warning<<"Operating unthreaded"<<endl;
@@ -3516,6 +3548,10 @@ int main(int argc, char **argv)
     ::arg().set("xpf-allow-from","XPF information is only processed from these subnets")="";
     ::arg().set("xpf-rr-code","XPF option code to use")="0";
 
+    ::arg().set("min-udp-source-port", "Minimum UDP port to bind on")="1025";
+    ::arg().set("max-udp-source-port", "Maximum UDP port to bind on")="65535";
+    ::arg().set("avoid-udp-source-port", "List of comma separated UDP port number to avoid")="11211";
+
     ::arg().setCmd("help","Provide a helpful message");
     ::arg().setCmd("version","Print version string");
     ::arg().setCmd("config","Output blank configuration");