From: Otto Moerbeek Date: Tue, 2 Apr 2024 08:02:07 +0000 (+0200) Subject: rec: allow exception to proxy protocal usage for specific listen addresses X-Git-Tag: rec-5.1.0-alpha1~65^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8a6888f7f2ce9e3a851eea1cddbef1610377b51e;p=thirdparty%2Fpdns.git rec: allow exception to proxy protocal usage for specific listen addresses --- diff --git a/pdns/recursordist/docs/upgrade.rst b/pdns/recursordist/docs/upgrade.rst index 39b42c9f7f..3d3023ceec 100644 --- a/pdns/recursordist/docs/upgrade.rst +++ b/pdns/recursordist/docs/upgrade.rst @@ -14,8 +14,10 @@ Changed settings - Disabling :ref:`setting-structured-logging` is no longer supported. -Changed Settings -^^^^^^^^^^^^^^^^ +New Settings +^^^^^^^^^^^^ + +- The :ref:`setting-proxy-protocol-exceptions` has been added. It allows to exclude specific listen addresses from requiring th e Proxy Protocol. 5.0.2 to 5.0.3, 4.9.3 to 4.9.4 and 4.8.6 to 4.8.7 ------------------------------------------------- diff --git a/pdns/recursordist/pdns_recursor.cc b/pdns/recursordist/pdns_recursor.cc index 109b7b342f..0aec4db5f2 100644 --- a/pdns/recursordist/pdns_recursor.cc +++ b/pdns/recursordist/pdns_recursor.cc @@ -2113,9 +2113,9 @@ void requestWipeCaches(const DNSName& canon) // coverity[leaked_storage] } -bool expectProxyProtocol(const ComboAddress& from) +bool expectProxyProtocol(const ComboAddress& from, const ComboAddress& listenAddress) { - return g_proxyProtocolACL.match(from); + return g_proxyProtocolACL.match(from) && g_proxyProtocolExceptions.count(listenAddress) == 0; } // fromaddr: the address the query is coming from @@ -2449,7 +2449,26 @@ static void handleNewUDPQuestion(int fileDesc, FDMultiplexer::funcparam_t& /* va data.resize(static_cast(len)); - if (expectProxyProtocol(fromaddr)) { + ComboAddress destaddr; // the address the query was sent to to + destaddr.reset(); // this makes sure we ignore this address if not explictly set below + const auto* loc = rplookup(g_listenSocketsAddresses, fileDesc); + if (HarvestDestinationAddress(&msgh, &destaddr)) { + // but.. need to get port too + if (loc != nullptr) { + destaddr.sin4.sin_port = loc->sin4.sin_port; + } + } + else { + if (loc != nullptr) { + destaddr = *loc; + } + else { + destaddr.sin4.sin_family = fromaddr.sin4.sin_family; + socklen_t slen = destaddr.getSocklen(); + getsockname(fileDesc, reinterpret_cast(&destaddr), &slen); // if this fails, we're ok with it // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) + } + } + if (expectProxyProtocol(fromaddr, destaddr)) { bool tcp = false; ssize_t used = parseProxyHeader(data, proxyProto, source, destination, tcp, proxyProtocolValues); if (used <= 0) { @@ -2569,25 +2588,6 @@ static void handleNewUDPQuestion(int fileDesc, FDMultiplexer::funcparam_t& /* va struct timeval tval = {0, 0}; HarvestTimestamp(&msgh, &tval); - ComboAddress destaddr; // the address the query was sent to to - destaddr.reset(); // this makes sure we ignore this address if not returned by recvmsg above - const auto* loc = rplookup(g_listenSocketsAddresses, fileDesc); - if (HarvestDestinationAddress(&msgh, &destaddr)) { - // but.. need to get port too - if (loc != nullptr) { - destaddr.sin4.sin_port = loc->sin4.sin_port; - } - } - else { - if (loc != nullptr) { - destaddr = *loc; - } - else { - destaddr.sin4.sin_family = fromaddr.sin4.sin_family; - socklen_t slen = destaddr.getSocklen(); - getsockname(fileDesc, reinterpret_cast(&destaddr), &slen); // if this fails, we're ok with it // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) - } - } if (!proxyProto) { destination = destaddr; } diff --git a/pdns/recursordist/rec-main.cc b/pdns/recursordist/rec-main.cc index d65ae03ff6..db062182fd 100644 --- a/pdns/recursordist/rec-main.cc +++ b/pdns/recursordist/rec-main.cc @@ -88,6 +88,7 @@ std::atomic statsWanted; uint32_t g_disthashseed; bool g_useIncomingECS; NetmaskGroup g_proxyProtocolACL; +std::set g_proxyProtocolExceptions; boost::optional g_dns64Prefix{boost::none}; DNSName g_dns64PrefixReverse; std::shared_ptr g_initialDomainMap; // new threads needs this to be setup @@ -2119,6 +2120,14 @@ static int serviceMain(Logr::log_t log) } g_proxyProtocolACL.toMasks(::arg()["proxy-protocol-from"]); + { + std::vector vec; + stringtok(vec, ::arg()["proxy-protocol-exceptions"], ", "); + for (const auto& sockAddrStr: vec) { + ComboAddress sockAddr(sockAddrStr, 53); + g_proxyProtocolExceptions.emplace(sockAddr); + } + } g_proxyProtocolMaximumSize = ::arg().asNum("proxy-protocol-maximum-size"); ret = initDNS64(log); diff --git a/pdns/recursordist/rec-main.hh b/pdns/recursordist/rec-main.hh index bf83b1b985..98c6898696 100644 --- a/pdns/recursordist/rec-main.hh +++ b/pdns/recursordist/rec-main.hh @@ -221,6 +221,7 @@ extern boost::optional g_dns64Prefix; extern DNSName g_dns64PrefixReverse; extern uint64_t g_latencyStatSize; extern NetmaskGroup g_proxyProtocolACL; +extern std::set g_proxyProtocolExceptions; extern std::atomic g_statsWanted; extern uint32_t g_disthashseed; extern int g_argc; @@ -610,7 +611,7 @@ void protobufLogResponse(const struct dnsheader* header, LocalStateHolder& policyTags); void requestWipeCaches(const DNSName& canon); void startDoResolve(void*); -bool expectProxyProtocol(const ComboAddress& from); +bool expectProxyProtocol(const ComboAddress& from, const ComboAddress& listenAddress); void finishTCPReply(std::unique_ptr&, bool hadError, bool updateInFlight); void checkFastOpenSysctl(bool active, Logr::log_t); void checkTFOconnect(Logr::log_t); diff --git a/pdns/recursordist/rec-tcp.cc b/pdns/recursordist/rec-tcp.cc index 196db6fe7b..a2287598a0 100644 --- a/pdns/recursordist/rec-tcp.cc +++ b/pdns/recursordist/rec-tcp.cc @@ -697,7 +697,10 @@ void handleNewTCPQuestion(int fileDesc, [[maybe_unused]] FDMultiplexer::funcpara t_remotes->push_back(addr); } - bool fromProxyProtocolSource = expectProxyProtocol(addr); + ComboAddress destaddr; + socklen_t len = sizeof(destaddr); + getsockname(newsock, reinterpret_cast(&destaddr), &len); // if this fails, we're ok with it NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) + bool fromProxyProtocolSource = expectProxyProtocol(addr, destaddr); ComboAddress mappedSource = addr; if (!fromProxyProtocolSource && t_proxyMapping) { if (const auto* iter = t_proxyMapping->lookup(addr)) { @@ -737,10 +740,7 @@ void handleNewTCPQuestion(int fileDesc, [[maybe_unused]] FDMultiplexer::funcpara setTCPNoDelay(newsock); std::shared_ptr tcpConn = std::make_shared(newsock, addr); tcpConn->d_source = addr; - tcpConn->d_destination.reset(); - tcpConn->d_destination.sin4.sin_family = addr.sin4.sin_family; - socklen_t len = tcpConn->d_destination.getSocklen(); - getsockname(tcpConn->getFD(), reinterpret_cast(&tcpConn->d_destination), &len); // if this fails, we're ok with it NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) + tcpConn->d_destination = destaddr; tcpConn->d_mappedSource = mappedSource; if (fromProxyProtocolSource) { diff --git a/pdns/recursordist/settings/table.py b/pdns/recursordist/settings/table.py index 24cb75c37f..485d4496c5 100644 --- a/pdns/recursordist/settings/table.py +++ b/pdns/recursordist/settings/table.py @@ -2064,6 +2064,19 @@ The dnsdist docs have `more information about the PROXY protocol