Skip to content

Commit

Permalink
auth dnsproxy: make local port range configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
zeha committed Aug 27, 2024
1 parent abe0199 commit 60157e5
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 5 deletions.
14 changes: 14 additions & 0 deletions docs/settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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``
Expand Down
3 changes: 2 additions & 1 deletion pdns/auth-main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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") = "";
Expand Down Expand Up @@ -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();
}

Expand Down
22 changes: 19 additions & 3 deletions pdns/dnsproxy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@
#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");
Expand All @@ -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());
}
Expand All @@ -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;
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion pdns/dnsproxy.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 60157e5

Please sign in to comment.