]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Handle Proxy Protocol payloads with cross-protocol queries
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 13 Apr 2021 12:47:26 +0000 (14:47 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 26 Aug 2021 14:30:26 +0000 (16:30 +0200)
pdns/dnsdist-tcp.cc
pdns/dnsdistdist/dnsdist-proxy-protocol.cc
pdns/dnsdistdist/dnsdist-proxy-protocol.hh
pdns/dnsdistdist/dnsdist-tcp.hh
pdns/dnsdistdist/doh.cc
pdns/doh.hh

index cea13fc631cdac35049d730e20bbd710d846e5bd..022ae687838c754faba609107834f9cd0e67f2f8 100644 (file)
@@ -379,14 +379,18 @@ static void handleResponseSent(std::shared_ptr<IncomingTCPConnectionState>& stat
   }
 }
 
-static void prependSizeToTCPQuery(PacketBuffer& buffer)
+static void prependSizeToTCPQuery(PacketBuffer& buffer, size_t proxyProtocolPayloadSize)
 {
-  uint16_t queryLen = buffer.size();
+  if (buffer.size() <= proxyProtocolPayloadSize) {
+    throw std::runtime_error("The payload size is smaller or equal to the buffer size");
+  }
+
+  uint16_t queryLen = proxyProtocolPayloadSize > 0 ? (buffer.size() - proxyProtocolPayloadSize) : buffer.size();
   const uint8_t sizeBytes[] = { static_cast<uint8_t>(queryLen / 256), static_cast<uint8_t>(queryLen % 256) };
   /* prepend the size. Yes, this is not the most efficient way but it prevents mistakes
      that could occur if we had to deal with the size during the processing,
      especially alignment issues */
-  buffer.insert(buffer.begin(), sizeBytes, sizeBytes + 2);
+  buffer.insert(buffer.begin() + proxyProtocolPayloadSize, sizeBytes, sizeBytes + 2);
 }
 
 bool IncomingTCPConnectionState::canAcceptNewQueries(const struct timeval& now)
@@ -714,7 +718,7 @@ static void handleQuery(std::shared_ptr<IncomingTCPConnectionState>& state, cons
   setIDStateFromDNSQuestion(ids, dq, std::move(qname));
   ids.origID = ntohs(dh->id);
 
-  prependSizeToTCPQuery(state->d_buffer);
+  prependSizeToTCPQuery(state->d_buffer, 0);
 
   auto downstreamConnection = state->getDownstreamConnection(ds, dq.proxyProtocolValues, now);
 
@@ -1137,14 +1141,14 @@ static void handleCrossProtocolQuery(int pipefd, FDMultiplexer::funcparam_t& par
 
     auto query = std::move(tmp->query);
     auto downstreamServer = std::move(tmp->downstream);
+    auto proxyProtocolPayloadSize = tmp->proxyProtocolPayloadSize;
     std::shared_ptr<TCPQuerySender> tqs = tmp->getTCPQuerySender();
     delete tmp;
     tmp = nullptr;
 
     auto downstream = DownstreamConnectionsManager::getConnectionToDownstream(threadData->mplexer, downstreamServer, now);
 
-#warning FIXME: what if a proxy protocol payload was inserted?
-    prependSizeToTCPQuery(query.d_buffer);
+    prependSizeToTCPQuery(query.d_buffer, proxyProtocolPayloadSize);
     downstream->queueQuery(tqs, std::move(query));
   }
   catch (...) {
index 06a300d6a51da1d71c709eac227af348faafc7d8..6a3e97897704f1fb2a077b644c9e880341c52861 100644 (file)
@@ -41,9 +41,13 @@ bool addProxyProtocol(DNSQuestion& dq, const std::string& payload)
   return addProxyProtocol(dq.getMutableData(), payload);
 }
 
-bool addProxyProtocol(DNSQuestion& dq)
+bool addProxyProtocol(DNSQuestion& dq, size_t* payloadSize)
 {
   auto payload = getProxyProtocolPayload(dq);
+  if (payloadSize != nullptr) {
+    *payloadSize = payload.size();
+  }
+
   return addProxyProtocol(dq, payload);
 }
 
index fac7dea6181def9716efb5320a0060a101aa4a6f..de7674a2dbaa27069bf0f79b32db85f62d6f3fd4 100644 (file)
@@ -29,7 +29,7 @@ extern bool g_applyACLToProxiedClients;
 
 std::string getProxyProtocolPayload(const DNSQuestion& dq);
 
-bool addProxyProtocol(DNSQuestion& dq);
+bool addProxyProtocol(DNSQuestion& dq, size_t* proxyProtocolPayloadSize = nullptr);
 bool addProxyProtocol(DNSQuestion& dq, const std::string& payload);
 bool addProxyProtocol(PacketBuffer& buffer, const std::string& payload);
 bool addProxyProtocol(PacketBuffer& buffer, bool tcp, const ComboAddress& source, const ComboAddress& destination, const std::vector<ProxyProtocolValue>& values);
index b932e5d5a4fc980b0e1c39dbd134c02670730083..6a0058ca53acd2481ff6b31ba0e8c1606faad1da 100644 (file)
@@ -157,6 +157,8 @@ struct CrossProtocolQuery
 
   InternalQuery query;
   std::shared_ptr<DownstreamState> downstream{nullptr};
+  size_t proxyProtocolPayloadSize{0};
+  bool isXFR{false};
 };
 
 class TCPClientCollection {
index 296c09e6db2774727cd3a633d04f0767e36d3e1e..fe237dceceea0a1568c3144157ec52113964f7bf 100644 (file)
@@ -199,14 +199,6 @@ struct DOHServerConfig
 
     setNonBlocking(dohresponsepair[1]);
 
-    if (pipe(fd) < 0) {
-      close(dohquerypair[0]);
-      close(dohquerypair[1]);
-      close(dohresponsepair[0]);
-      close(dohresponsepair[1]);
-      unixDie("Creating a pipe for DNS over HTTPS");
-    }
-
     h2o_config_init(&h2o_config);
     h2o_config.http2.idle_timeout = idleTimeout * 1000;
   }
@@ -563,7 +555,10 @@ static int processDOHQuery(DOHUnit* du)
     }
 
     if (du->downstream->useProxyProtocol) {
-      addProxyProtocol(dq);
+      size_t payloadSize = 0;
+      if (addProxyProtocol(dq)) {
+        du->proxyProtocolPayloadSize = payloadSize;
+      }
     }
 
     int fd = pickBackendSocketForSending(du->downstream);
@@ -1196,6 +1191,7 @@ public:
   {
     query = InternalQuery(std::move(du->query), std::move(du->ids));
     downstream = du->downstream;
+    proxyProtocolPayloadSize = du->proxyProtocolPayloadSize;
   }
 
   ~DoHCrossProtocolQuery()
index 9a2d12bb4d81aa76b22aab4777a5c0e79edec055..de8f67f42d9d4960f98c880c4b0165f296ce2752 100644 (file)
@@ -221,6 +221,7 @@ struct DOHUnit
   std::string contentType;
   std::atomic<uint64_t> d_refcnt{1};
   size_t query_at{0};
+  size_t proxyProtocolPayloadSize{0};
   int rsock{-1};
   /* the status_code is set from
      processDOHQuery() (which is executed in