From: Remi Gacogne Date: Wed, 25 Aug 2021 12:06:49 +0000 (+0200) Subject: dnsdist: Accept more than one TLS ticket from the same connection X-Git-Tag: dnsdist-1.7.0-alpha1~23^2~28 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b9944e1d554119069e5fb5df1075324e629429f4;p=thirdparty%2Fpdns.git dnsdist: Accept more than one TLS ticket from the same connection --- diff --git a/pdns/dnsdistdist/dnsdist-session-cache.cc b/pdns/dnsdistdist/dnsdist-session-cache.cc index 67de195360..18d03d8d84 100644 --- a/pdns/dnsdistdist/dnsdist-session-cache.cc +++ b/pdns/dnsdistdist/dnsdist-session-cache.cc @@ -43,18 +43,20 @@ void TLSSessionCache::cleanup(time_t now, const std::lock_guard& loc d_nextCleanup = now + s_cleanupDelay; } -void TLSSessionCache::putSession(const boost::uuids::uuid& backendID, time_t now, std::unique_ptr&& session) +void TLSSessionCache::putSessions(const boost::uuids::uuid& backendID, time_t now, std::vector>&& sessions) { std::lock_guard lock(d_lock); if (d_nextCleanup == 0 || now > d_nextCleanup) { cleanup(now, lock); } - auto& entry = d_sessions[backendID]; - if (entry.d_sessions.size() >= s_maxSessionsPerBackend) { - entry.d_sessions.pop_back(); + for (auto& session : sessions) { + auto& entry = d_sessions[backendID]; + if (entry.d_sessions.size() >= s_maxSessionsPerBackend) { + entry.d_sessions.pop_back(); + } + entry.d_sessions.push_front(std::move(session)); } - entry.d_sessions.push_front(std::move(session)); } std::unique_ptr TLSSessionCache::getSession(const boost::uuids::uuid& backendID, time_t now) diff --git a/pdns/dnsdistdist/dnsdist-session-cache.hh b/pdns/dnsdistdist/dnsdist-session-cache.hh index 6cae14034b..0c523b1b6a 100644 --- a/pdns/dnsdistdist/dnsdist-session-cache.hh +++ b/pdns/dnsdistdist/dnsdist-session-cache.hh @@ -35,7 +35,7 @@ public: } void cleanup(time_t now, const std::lock_guard& lock); - void putSession(const boost::uuids::uuid& backendID, time_t now, std::unique_ptr&& session); + void putSessions(const boost::uuids::uuid& backendID, time_t now, std::vector>&& sessions); std::unique_ptr getSession(const boost::uuids::uuid& backendID, time_t now); static void setCleanupDelay(time_t delay) diff --git a/pdns/dnsdistdist/dnsdist-tcp-downstream.cc b/pdns/dnsdistdist/dnsdist-tcp-downstream.cc index c097fe8263..da37224087 100644 --- a/pdns/dnsdistdist/dnsdist-tcp-downstream.cc +++ b/pdns/dnsdistdist/dnsdist-tcp-downstream.cc @@ -21,9 +21,9 @@ TCPConnectionToBackend::~TCPConnectionToBackend() ++d_ds->tlsResumptions; } try { - auto session = d_handler->getTLSSession(); - if (session) { - g_sessionCache.putSession(d_ds->getID(), now.tv_sec, std::move(session)); + auto sessions = d_handler->getTLSSessions(); + if (!sessions.empty()) { + g_sessionCache.putSessions(d_ds->getID(), now.tv_sec, std::move(sessions)); } } catch (const std::exception& e) { @@ -343,7 +343,14 @@ bool TCPConnectionToBackend::reconnect() ++d_ds->tlsResumptions; } try { - tlsSession = d_handler->getTLSSession(); + auto sessions = d_handler->getTLSSessions(); + if (!sessions.empty()) { + tlsSession = std::move(sessions.back()); + sessions.pop_back(); + if (!sessions.empty()) { + g_sessionCache.putSessions(d_ds->getID(), time(nullptr), std::move(sessions)); + } + } } catch (const std::exception& e) { vinfolog("Unable to get a TLS session to resume: %s", e.what()); diff --git a/pdns/dnsdistdist/dnsdist-tcp-downstream.hh b/pdns/dnsdistdist/dnsdist-tcp-downstream.hh index aafbd3dd90..a34258cb90 100644 --- a/pdns/dnsdistdist/dnsdist-tcp-downstream.hh +++ b/pdns/dnsdistdist/dnsdist-tcp-downstream.hh @@ -192,7 +192,6 @@ protected: } PacketBuffer d_responseBuffer; -#warning we do not need this and could append to the outgoing buffer right away but is it better? std::deque d_pendingQueries; std::unordered_map d_pendingResponses; std::unique_ptr& d_mplexer; diff --git a/pdns/dnsdistdist/test-dnsdisttcp_cc.cc b/pdns/dnsdistdist/test-dnsdisttcp_cc.cc index 7ea89e2b87..884780b28c 100644 --- a/pdns/dnsdistdist/test-dnsdisttcp_cc.cc +++ b/pdns/dnsdistdist/test-dnsdisttcp_cc.cc @@ -242,9 +242,9 @@ public: return false; } - std::unique_ptr getSession() override + std::vector> getSessions() override { - return nullptr; + return {}; } void setSession(std::unique_ptr& session) override diff --git a/pdns/tcpiohandler.cc b/pdns/tcpiohandler.cc index e957d66bbe..0bc0d7376f 100644 --- a/pdns/tcpiohandler.cc +++ b/pdns/tcpiohandler.cc @@ -456,13 +456,9 @@ public: return false; } - std::unique_ptr getSession() override + std::vector> getSessions() override { - if (d_tlsSession) { - return std::move(d_tlsSession); - } - - throw std::runtime_error("Unable to get an OpenSSL session"); + return std::move(d_tlsSessions); } void setSession(std::unique_ptr& session) override @@ -480,9 +476,9 @@ public: native.release(); } - void setNewTicket(SSL_SESSION* session) + void addNewTicket(SSL_SESSION* session) { - d_tlsSession = std::unique_ptr(new OpenSSLSession(std::unique_ptr(session, SSL_SESSION_free))); + d_tlsSessions.push_back(std::unique_ptr(new OpenSSLSession(std::unique_ptr(session, SSL_SESSION_free)))); } static int s_tlsConnIndex; @@ -490,9 +486,9 @@ public: private: static std::atomic_flag s_initTLSConnIndex; + std::vector> d_tlsSessions; std::shared_ptr d_feContext; std::unique_ptr d_conn; - std::unique_ptr d_tlsSession{nullptr}; std::string d_hostname; struct timeval d_timeout; }; @@ -652,7 +648,7 @@ public: return 0; } - conn->setNewTicket(session); + conn->addNewTicket(session); return 1; } @@ -1007,7 +1003,7 @@ public: if (ret != GNUTLS_E_SUCCESS || sess.size <= 4) { throw std::runtime_error("Error getting GnuTLSSession: " + std::string(gnutls_strerror(ret))); } - conn->d_tlsSession = std::unique_ptr(new GnuTLSSession(sess)); + conn->d_tlsSessions.push_back(std::unique_ptr(new GnuTLSSession(sess))); return 0; } @@ -1360,13 +1356,9 @@ public: return false; } - std::unique_ptr getSession() override + std::vector> getSessions() override { - if (d_tlsSession) { - return std::move(d_tlsSession); - } - - throw std::runtime_error("No GnuTLSSession available yet"); + return std::move(d_tlsSessions); } void setSession(std::unique_ptr& session) override @@ -1406,9 +1398,9 @@ public: } private: + std::vector> d_tlsSessions; std::shared_ptr d_ticketsKey; std::unique_ptr d_conn; - std::unique_ptr d_tlsSession{nullptr}; std::string d_host; bool d_client{false}; bool d_handshakeDone{false}; diff --git a/pdns/tcpiohandler.hh b/pdns/tcpiohandler.hh index fcde2c62ae..b531466b5f 100644 --- a/pdns/tcpiohandler.hh +++ b/pdns/tcpiohandler.hh @@ -36,7 +36,7 @@ public: virtual std::vector getNextProtocol() const = 0; virtual LibsslTLSVersion getTLSVersion() const = 0; virtual bool hasSessionBeenResumed() const = 0; - virtual std::unique_ptr getSession() = 0; + virtual std::vector> getSessions() = 0; virtual void setSession(std::unique_ptr& session) = 0; virtual void close() = 0; @@ -521,13 +521,13 @@ public: } } - std::unique_ptr getTLSSession() + std::vector> getTLSSessions() { if (!d_conn) { - throw std::runtime_error("Trying to get a TLS session from a non-TLS handler"); + throw std::runtime_error("Trying to get TLS sessions from a non-TLS handler"); } - return d_conn->getSession(); + return d_conn->getSessions(); } private: