]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add a WIP session cache
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 4 May 2021 16:44:41 +0000 (18:44 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 26 Aug 2021 14:30:27 +0000 (16:30 +0200)
pdns/dnsdistdist/Makefile.am
pdns/dnsdistdist/dnsdist-healthchecks.cc
pdns/dnsdistdist/dnsdist-session-cache.cc [new file with mode: 0644]
pdns/dnsdistdist/dnsdist-session-cache.hh [new file with mode: 0644]
pdns/dnsdistdist/dnsdist-tcp-downstream.cc
pdns/dnsdistdist/dnsdist-tcp-downstream.hh
pdns/dnsdistdist/test-dnsdisttcp_cc.cc
pdns/tcpiohandler.hh

index 83a579f9832b7dbcb9f839f77cf544ad0a109912..07ddd1267a6fde523c9f6bc9afe10c01ae213eab 100644 (file)
@@ -165,6 +165,7 @@ dnsdist_SOURCES = \
        dnsdist-rings.cc dnsdist-rings.hh \
        dnsdist-rules.cc dnsdist-rules.hh \
        dnsdist-secpoll.cc dnsdist-secpoll.hh \
+       dnsdist-session-cache.cc dnsdist-session-cache.hh \
        dnsdist-snmp.cc dnsdist-snmp.hh \
        dnsdist-systemd.cc dnsdist-systemd.hh \
        dnsdist-tcp-downstream.cc dnsdist-tcp-downstream.hh \
@@ -243,6 +244,7 @@ testrunner_SOURCES = \
        dnsdist-proxy-protocol.cc dnsdist-proxy-protocol.hh \
        dnsdist-rings.cc dnsdist-rings.hh \
        dnsdist-rules.cc dnsdist-rules.hh \
+       dnsdist-session-cache.cc dnsdist-session-cache.hh \
        dnsdist-tcp-downstream.cc \
        dnsdist-tcp.cc dnsdist-tcp.hh \
        dnsdist-xpf.cc dnsdist-xpf.hh \
index f1b1fd59250dacdf82aaed13d932a872f8611323..acae3cd63ef54a65e05665860241807bc3a3a3b4 100644 (file)
@@ -355,7 +355,6 @@ bool queueHealthCheck(std::shared_ptr<FDMultiplexer>& mplexer, const std::shared
     else {
       data->d_tcpHandler = std::make_unique<TCPIOHandler>(ds->d_tlsSubjectName, sock.releaseHandle(), timeval{ds->checkTimeout,0}, ds->d_tlsCtx, time(nullptr));
       data->d_ioState = std::make_unique<IOStateHandler>(*mplexer, data->d_tcpHandler->getDescriptor());
-
       data->d_tcpHandler->tryConnect(ds->tcpFastOpen, ds->remote);
 
       const uint8_t sizeBytes[] = { static_cast<uint8_t>(packetSize / 256), static_cast<uint8_t>(packetSize % 256) };
diff --git a/pdns/dnsdistdist/dnsdist-session-cache.cc b/pdns/dnsdistdist/dnsdist-session-cache.cc
new file mode 100644 (file)
index 0000000..367f02e
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include "dnsdist-session-cache.hh"
+
+TLSSessionCache g_sessionCache;
+
+void TLSSessionCache::cleanup(time_t now)
+{
+  #warning WRITEME
+}
+
+void TLSSessionCache::putSession(const ComboAddress& remote, std::unique_ptr<TLSSession>&& session)
+{
+  std::lock_guard<decltype(d_lock)> lock(d_lock);
+  auto& entry = d_sessions[remote];
+  entry.d_session = std::move(session);
+}
+
+std::unique_ptr<TLSSession> TLSSessionCache::getSession(const ComboAddress& remote, time_t now)
+{
+  std::lock_guard<decltype(d_lock)> lock(d_lock);
+  auto it = d_sessions.find(remote);
+  if (it == d_sessions.end()) {
+    return nullptr;
+  }
+
+  auto& entry = it->second;
+  if (entry.d_session == nullptr) {
+    return nullptr;
+  }
+
+  entry.d_lastUse = now;
+  return std::move(entry.d_session);
+}
diff --git a/pdns/dnsdistdist/dnsdist-session-cache.hh b/pdns/dnsdistdist/dnsdist-session-cache.hh
new file mode 100644 (file)
index 0000000..d1253bc
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#pragma once
+
+#include "tcpiohandler.hh"
+
+class TLSSessionCache
+{
+public:
+  TLSSessionCache()
+  {
+  }
+  void cleanup(time_t now);
+
+  void putSession(const ComboAddress& remote, std::unique_ptr<TLSSession>&& session);
+  std::unique_ptr<TLSSession> getSession(const ComboAddress& remote, time_t now);
+
+private:
+  struct Entry
+  {
+    // might become a FIFO at some point
+    std::unique_ptr<TLSSession> d_session{nullptr};
+    time_t d_lastUse{0};
+  };
+
+  std::map<ComboAddress, Entry> d_sessions;
+  std::mutex d_lock;
+};
+
+extern TLSSessionCache g_sessionCache;
index 6b11c6809412b096b4ac7f8f3d7dc96a3a9a095f..f07c6aec444510c64d6a2228ec35c1efff66151f 100644 (file)
@@ -1,9 +1,29 @@
 
+#include "dnsdist-session-cache.hh"
 #include "dnsdist-tcp-downstream.hh"
 #include "dnsdist-tcp-upstream.hh"
 
 #include "dnsparser.hh"
 
+TCPConnectionToBackend::~TCPConnectionToBackend()
+{
+  if (d_ds && d_handler) {
+    --d_ds->tcpCurrentConnections;
+    struct timeval now;
+    gettimeofday(&now, nullptr);
+
+    if (d_handler->isTLS()) {
+      cerr<<"Closing TLS connection, resumption was "<<d_handler->hasTLSSessionBeenResumed()<<endl;
+      auto session = d_handler->getTLSSession();
+      if (session) {
+        g_sessionCache.putSession(d_ds->remote, std::move(session));
+      }
+    }
+    auto diff = now - d_connectionStartTime;
+    d_ds->updateTCPMetrics(d_queries, diff.tv_sec * 1000 + diff.tv_usec / 1000);
+  }
+}
+
 void TCPConnectionToBackend::release()
 {
   d_ds->outstanding -= d_pendingResponses.size();
@@ -304,8 +324,13 @@ void TCPConnectionToBackend::queueQuery(std::shared_ptr<TCPQuerySender>& sender,
 
 bool TCPConnectionToBackend::reconnect()
 {
+  std::unique_ptr<TLSSession> tlsSession{nullptr};
   if (d_handler) {
     DEBUGLOG("closing socket "<<d_handler->getDescriptor());
+    if (d_handler->isTLS()) {
+      cerr<<"is TLS, getting a session"<<endl;
+      tlsSession = d_handler->getTLSSession();
+    }
     d_handler->close();
     d_ioState.reset();
     --d_ds->tcpCurrentConnections;
@@ -342,7 +367,19 @@ bool TCPConnectionToBackend::reconnect()
       socket->setNonBlocking();
 
       gettimeofday(&d_connectionStartTime, nullptr);
-      auto handler = std::make_unique<TCPIOHandler>(d_ds->d_tlsSubjectName, socket->releaseHandle(), timeval{0,0}, d_ds->d_tlsCtx, time(nullptr));
+      auto handler = std::make_unique<TCPIOHandler>(d_ds->d_tlsSubjectName, socket->releaseHandle(), timeval{0,0}, d_ds->d_tlsCtx, d_connectionStartTime.tv_sec);
+      if (!tlsSession && d_ds->d_tlsCtx) {
+        tlsSession = g_sessionCache.getSession(d_ds->remote, d_connectionStartTime.tv_sec);
+        if (tlsSession) {
+          cerr<<"reusing session from cache"<<endl;
+        }
+      }
+      else {
+        cerr<<"reusing session from previous connection"<<endl;
+      }
+      if (tlsSession) {
+        handler->setTLSSession(tlsSession);
+      }
       handler->tryConnect(d_ds->tcpFastOpen && isFastOpenEnabled(), d_ds->remote);
       d_queries = 0;
 
index 228bee4b3bfcc939147e0f003ddadf8390c5d315..8f7e354d2a6f7040f76bf4edd708a29661006eb8 100644 (file)
@@ -15,17 +15,7 @@ public:
     reconnect();
   }
 
-  ~TCPConnectionToBackend()
-  {
-    if (d_ds && d_handler) {
-      --d_ds->tcpCurrentConnections;
-      struct timeval now;
-      gettimeofday(&now, nullptr);
-
-      auto diff = now - d_connectionStartTime;
-      d_ds->updateTCPMetrics(d_queries, diff.tv_sec * 1000 + diff.tv_usec / 1000);
-    }
-  }
+  ~TCPConnectionToBackend();
 
   int getHandle() const
   {
index ef13a82e4e66d7016e643afbc35aa82aacb8eaf0..5c2321c4505b51c2cb448c30f0d53061b4ad89ce 100644 (file)
@@ -239,12 +239,11 @@ public:
 
   std::unique_ptr<TLSSession> getSession() const override
   {
-    throw std::runtime_error("getSession() not implemented");
+    return nullptr;
   }
 
   void setSession(std::unique_ptr<TLSSession>& session) override
   {
-    throw std::runtime_error("setSession() not implemented");
   }
 
   /* unused in that context, don't bother */
index 7c78ef65f9cf590e84c087e1c106f160ef9e797c..70260c6c722c10f11d86d056f671856d51ceedc3 100644 (file)
@@ -4,6 +4,7 @@
 /* needed for proper TCP_FASTOPEN_CONNECT detection */
 #include <netinet/tcp.h>
 
+#include "iputils.hh"
 #include "libssl.hh"
 #include "misc.hh"
 #include "noinitvector.hh"