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``
::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") = "";
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();
}
#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");
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());
}
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;
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;
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);