From: Remi Gacogne Date: Wed, 5 May 2021 15:13:09 +0000 (+0200) Subject: dnsdist: Handle more than one cached TLS session per backend X-Git-Tag: dnsdist-1.7.0-alpha1~45^2~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ed20fc7a25cf96d39d29059817672f9e0a1d3255;p=thirdparty%2Fpdns.git dnsdist: Handle more than one cached TLS session per backend --- diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index fdc083baf0..af26d04ff5 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -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) { diff --git a/pdns/dnsdistdist/dnsdist-session-cache.cc b/pdns/dnsdistdist/dnsdist-session-cache.cc index 367f02e661..ff7e8f6c38 100644 --- a/pdns/dnsdistdist/dnsdist-session-cache.cc +++ b/pdns/dnsdistdist/dnsdist-session-cache.cc @@ -23,31 +23,57 @@ 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& 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&& session) +void TLSSessionCache::putSession(const boost::uuids::uuid& backendID, time_t now, std::unique_ptr&& session) { std::lock_guard 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 TLSSessionCache::getSession(const ComboAddress& remote, time_t now) +std::unique_ptr TLSSessionCache::getSession(const boost::uuids::uuid& backendID, time_t now) { std::lock_guard 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; } diff --git a/pdns/dnsdistdist/dnsdist-session-cache.hh b/pdns/dnsdistdist/dnsdist-session-cache.hh index d1253bc024..598c483382 100644 --- a/pdns/dnsdistdist/dnsdist-session-cache.hh +++ b/pdns/dnsdistdist/dnsdist-session-cache.hh @@ -21,7 +21,11 @@ */ #pragma once +#include +#include + #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& lock); - void putSession(const ComboAddress& remote, std::unique_ptr&& session); - std::unique_ptr getSession(const ComboAddress& remote, time_t now); + void putSession(const boost::uuids::uuid& backendID, time_t now, std::unique_ptr&& session); + std::unique_ptr 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 d_session{nullptr}; - time_t d_lastUse{0}; + std::deque> d_sessions; + time_t d_lastUsed{0}; }; - std::map d_sessions; + std::map 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; diff --git a/pdns/dnsdistdist/dnsdist-tcp-downstream.cc b/pdns/dnsdistdist/dnsdist-tcp-downstream.cc index 56ab9b21a2..f1e2baeb6d 100644 --- a/pdns/dnsdistdist/dnsdist-tcp-downstream.cc +++ b/pdns/dnsdistdist/dnsdist-tcp-downstream.cc @@ -19,7 +19,7 @@ TCPConnectionToBackend::~TCPConnectionToBackend() cerr<<"Closing TLS connection, resumption was "<hasTLSSessionBeenResumed()<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(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"<