]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Handle more than one cached TLS session per backend
authorRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 5 May 2021 15:13:09 +0000 (17:13 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 26 Aug 2021 14:30:27 +0000 (16:30 +0200)
pdns/dnsdist.hh
pdns/dnsdistdist/dnsdist-session-cache.cc
pdns/dnsdistdist/dnsdist-session-cache.hh
pdns/dnsdistdist/dnsdist-tcp-downstream.cc

index fdc083baf04a0572175b428b7a64744bdfc9fdee..af26d04ff5ef84401f7ca24d565e580a15f03c14 100644 (file)
@@ -793,6 +793,10 @@ struct DownstreamState
   {
     return d_stopped;
   }
+  const boost::uuids::uuid& getID() const
+  {
+    return id;
+  }
 
   void updateTCPMetrics(size_t nbQueries, uint64_t durationMs)
   {
index 367f02e661285dc0af9540adbcf0afde3dd1552b..ff7e8f6c38af7ea4c10ffb8c65e55f781d283ae2 100644 (file)
 
 TLSSessionCache g_sessionCache;
 
-void TLSSessionCache::cleanup(time_t now)
+time_t const TLSSessionCache::s_cleanupDelay{60};
+time_t const TLSSessionCache::s_sessionValidity{600};
+
+
+void TLSSessionCache::cleanup(time_t now, const std::lock_guard<std::mutex>& lock)
 {
-  #warning WRITEME
+  time_t cutOff = now + s_sessionValidity;
+
+  for (auto it = d_sessions.begin(); it != d_sessions.end(); )
+  {
+    if (it->second.d_lastUsed > cutOff || it->second.d_sessions.size() == 0) {
+      it = d_sessions.erase(it);
+    }
+    else {
+      ++it;
+    }
+  }
+
+  d_nextCleanup = now + s_cleanupDelay;
 }
 
-void TLSSessionCache::putSession(const ComboAddress& remote, std::unique_ptr<TLSSession>&& session)
+void TLSSessionCache::putSession(const boost::uuids::uuid& backendID, time_t now, 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);
+  if (d_nextCleanup == 0 || now > d_nextCleanup) {
+    cleanup(now, lock);
+  }
+
+  auto& entry = d_sessions[backendID];
+  if (entry.d_sessions.size() >= d_maxSessionsPerBackend) {
+    entry.d_sessions.pop_back();
+  }
+  entry.d_sessions.push_front(std::move(session));
 }
 
-std::unique_ptr<TLSSession> TLSSessionCache::getSession(const ComboAddress& remote, time_t now)
+std::unique_ptr<TLSSession> TLSSessionCache::getSession(const boost::uuids::uuid& backendID, time_t now)
 {
   std::lock_guard<decltype(d_lock)> lock(d_lock);
-  auto it = d_sessions.find(remote);
+  auto it = d_sessions.find(backendID);
   if (it == d_sessions.end()) {
     return nullptr;
   }
 
   auto& entry = it->second;
-  if (entry.d_session == nullptr) {
+  if (entry.d_sessions.size() == 0) {
     return nullptr;
   }
 
-  entry.d_lastUse = now;
-  return std::move(entry.d_session);
+  entry.d_lastUsed = now;
+  auto value = std::move(entry.d_sessions.front());
+  entry.d_sessions.pop_front();
+
+  return value;
 }
index d1253bc024b865b4ed73883492d8178233b96b33..598c48338297c18727c43e4f0e320656d094dd3d 100644 (file)
  */
 #pragma once
 
+#include <deque>
+#include <map>
+
 #include "tcpiohandler.hh"
+#include "uuid-utils.hh"
 
 class TLSSessionCache
 {
@@ -29,21 +33,26 @@ public:
   TLSSessionCache()
   {
   }
-  void cleanup(time_t now);
+  void cleanup(time_t now, const std::lock_guard<std::mutex>& lock);
 
-  void putSession(const ComboAddress& remote, std::unique_ptr<TLSSession>&& session);
-  std::unique_ptr<TLSSession> getSession(const ComboAddress& remote, time_t now);
+  void putSession(const boost::uuids::uuid& backendID, time_t now, std::unique_ptr<TLSSession>&& session);
+  std::unique_ptr<TLSSession> getSession(const boost::uuids::uuid& backendID, time_t now);
 
 private:
-  struct Entry
+  static time_t const s_cleanupDelay;
+  static time_t const s_sessionValidity;
+
+  struct BackendEntry
   {
-    // might become a FIFO at some point
-    std::unique_ptr<TLSSession> d_session{nullptr};
-    time_t d_lastUse{0};
+    std::deque<std::unique_ptr<TLSSession>> d_sessions;
+    time_t d_lastUsed{0};
   };
 
-  std::map<ComboAddress, Entry> d_sessions;
+  std::map<boost::uuids::uuid, BackendEntry> d_sessions;
+  // do we need to shard this?
   std::mutex d_lock;
+  time_t d_nextCleanup{0};
+  uint16_t d_maxSessionsPerBackend{20};
 };
 
 extern TLSSessionCache g_sessionCache;
index 56ab9b21a2b0871188723e17a512a1c60edf0851..f1e2baeb6d4b167055a32d35861eaa95dcfde867 100644 (file)
@@ -19,7 +19,7 @@ TCPConnectionToBackend::~TCPConnectionToBackend()
       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));
+        g_sessionCache.putSession(d_ds->getID(), now.tv_sec, std::move(session));
       }
     }
     auto diff = now - d_connectionStartTime;
@@ -375,7 +375,7 @@ bool TCPConnectionToBackend::reconnect()
       gettimeofday(&d_connectionStartTime, 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);
+        tlsSession = g_sessionCache.getSession(d_ds->getID(), d_connectionStartTime.tv_sec);
         if (tlsSession) {
           cerr<<"reusing session from cache"<<endl;
         }