From: Remi Gacogne Date: Tue, 4 May 2021 16:44:41 +0000 (+0200) Subject: dnsdist: Add a WIP session cache X-Git-Tag: dnsdist-1.7.0-alpha1~45^2~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=32a63bdb824ba5e34b8b2d71c042166fe193b551;p=thirdparty%2Fpdns.git dnsdist: Add a WIP session cache --- diff --git a/pdns/dnsdistdist/Makefile.am b/pdns/dnsdistdist/Makefile.am index 83a579f983..07ddd1267a 100644 --- a/pdns/dnsdistdist/Makefile.am +++ b/pdns/dnsdistdist/Makefile.am @@ -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 \ diff --git a/pdns/dnsdistdist/dnsdist-healthchecks.cc b/pdns/dnsdistdist/dnsdist-healthchecks.cc index f1b1fd5925..acae3cd63e 100644 --- a/pdns/dnsdistdist/dnsdist-healthchecks.cc +++ b/pdns/dnsdistdist/dnsdist-healthchecks.cc @@ -355,7 +355,6 @@ bool queueHealthCheck(std::shared_ptr& mplexer, const std::shared else { data->d_tcpHandler = std::make_unique(ds->d_tlsSubjectName, sock.releaseHandle(), timeval{ds->checkTimeout,0}, ds->d_tlsCtx, time(nullptr)); data->d_ioState = std::make_unique(*mplexer, data->d_tcpHandler->getDescriptor()); - data->d_tcpHandler->tryConnect(ds->tcpFastOpen, ds->remote); const uint8_t sizeBytes[] = { static_cast(packetSize / 256), static_cast(packetSize % 256) }; diff --git a/pdns/dnsdistdist/dnsdist-session-cache.cc b/pdns/dnsdistdist/dnsdist-session-cache.cc new file mode 100644 index 0000000000..367f02e661 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-session-cache.cc @@ -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&& session) +{ + std::lock_guard lock(d_lock); + auto& entry = d_sessions[remote]; + entry.d_session = std::move(session); +} + +std::unique_ptr TLSSessionCache::getSession(const ComboAddress& remote, time_t now) +{ + std::lock_guard 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 index 0000000000..d1253bc024 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-session-cache.hh @@ -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&& session); + std::unique_ptr getSession(const ComboAddress& remote, time_t now); + +private: + struct Entry + { + // might become a FIFO at some point + std::unique_ptr d_session{nullptr}; + time_t d_lastUse{0}; + }; + + std::map d_sessions; + std::mutex d_lock; +}; + +extern TLSSessionCache g_sessionCache; diff --git a/pdns/dnsdistdist/dnsdist-tcp-downstream.cc b/pdns/dnsdistdist/dnsdist-tcp-downstream.cc index 6b11c68094..f07c6aec44 100644 --- a/pdns/dnsdistdist/dnsdist-tcp-downstream.cc +++ b/pdns/dnsdistdist/dnsdist-tcp-downstream.cc @@ -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 "<hasTLSSessionBeenResumed()<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& sender, bool TCPConnectionToBackend::reconnect() { + std::unique_ptr tlsSession{nullptr}; if (d_handler) { DEBUGLOG("closing socket "<getDescriptor()); + if (d_handler->isTLS()) { + cerr<<"is TLS, getting a session"<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(d_ds->d_tlsSubjectName, socket->releaseHandle(), timeval{0,0}, d_ds->d_tlsCtx, time(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); + if (tlsSession) { + cerr<<"reusing session from cache"<setTLSSession(tlsSession); + } handler->tryConnect(d_ds->tcpFastOpen && isFastOpenEnabled(), d_ds->remote); d_queries = 0; diff --git a/pdns/dnsdistdist/dnsdist-tcp-downstream.hh b/pdns/dnsdistdist/dnsdist-tcp-downstream.hh index 228bee4b3b..8f7e354d2a 100644 --- a/pdns/dnsdistdist/dnsdist-tcp-downstream.hh +++ b/pdns/dnsdistdist/dnsdist-tcp-downstream.hh @@ -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 { diff --git a/pdns/dnsdistdist/test-dnsdisttcp_cc.cc b/pdns/dnsdistdist/test-dnsdisttcp_cc.cc index ef13a82e4e..5c2321c450 100644 --- a/pdns/dnsdistdist/test-dnsdisttcp_cc.cc +++ b/pdns/dnsdistdist/test-dnsdisttcp_cc.cc @@ -239,12 +239,11 @@ public: std::unique_ptr getSession() const override { - throw std::runtime_error("getSession() not implemented"); + return nullptr; } void setSession(std::unique_ptr& session) override { - throw std::runtime_error("setSession() not implemented"); } /* unused in that context, don't bother */ diff --git a/pdns/tcpiohandler.hh b/pdns/tcpiohandler.hh index 7c78ef65f9..70260c6c72 100644 --- a/pdns/tcpiohandler.hh +++ b/pdns/tcpiohandler.hh @@ -4,6 +4,7 @@ /* needed for proper TCP_FASTOPEN_CONNECT detection */ #include +#include "iputils.hh" #include "libssl.hh" #include "misc.hh" #include "noinitvector.hh"