From dcc3c32dcdd70bdab88061c1ffe3b37c174f3588 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 5 Feb 2020 15:53:56 +0100 Subject: [PATCH] Close connections w/o sucessful TLS handshakes during 10s refs #7805 --- lib/remote/apilistener.cpp | 53 +++++++++++++++++++++++++++++++++----- lib/remote/apilistener.hpp | 11 ++++++-- 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/lib/remote/apilistener.cpp b/lib/remote/apilistener.cpp index 81385e6da..4c30c32c6 100644 --- a/lib/remote/apilistener.cpp +++ b/lib/remote/apilistener.cpp @@ -24,11 +24,14 @@ #include "base/exception.hpp" #include "base/tcpsocket.hpp" #include +#include #include #include #include +#include #include #include +#include #include #include #include @@ -435,7 +438,9 @@ void ApiListener::ListenerCoroutineProc(boost::asio::yield_context yc, const std server->async_accept(sslConn->lowest_layer(), yc); - IoEngine::SpawnCoroutine(io, [this, sslConn](asio::yield_context yc) { NewClientHandler(yc, sslConn, String(), RoleServer); }); + auto strand (Shared::Make(io)); + + IoEngine::SpawnCoroutine(*strand, [this, strand, sslConn](asio::yield_context yc) { NewClientHandler(yc, strand, sslConn, String(), RoleServer); }); } catch (const std::exception& ex) { Log(LogCritical, "ApiListener") << "Cannot accept new connection: " << ex.what(); @@ -461,8 +466,9 @@ void ApiListener::AddConnection(const Endpoint::Ptr& endpoint) } auto& io (IoEngine::Get().GetIoContext()); + auto strand (Shared::Make(io)); - IoEngine::SpawnCoroutine(io, [this, endpoint, &io, sslContext](asio::yield_context yc) { + IoEngine::SpawnCoroutine(*strand, [this, strand, endpoint, &io, sslContext](asio::yield_context yc) { String host = endpoint->GetHost(); String port = endpoint->GetPort(); @@ -474,7 +480,7 @@ void ApiListener::AddConnection(const Endpoint::Ptr& endpoint) Connect(sslConn->lowest_layer(), host, port, yc); - NewClientHandler(yc, sslConn, endpoint->GetName(), RoleClient); + NewClientHandler(yc, strand, sslConn, endpoint->GetName(), RoleClient); endpoint->SetConnecting(false); Log(LogInformation, "ApiListener") @@ -488,10 +494,13 @@ void ApiListener::AddConnection(const Endpoint::Ptr& endpoint) }); } -void ApiListener::NewClientHandler(boost::asio::yield_context yc, const std::shared_ptr& client, const String& hostname, ConnectionRole role) +void ApiListener::NewClientHandler( + boost::asio::yield_context yc, const Shared::Ptr& strand, + const std::shared_ptr&client, const String& hostname, ConnectionRole role +) { try { - NewClientHandlerInternal(yc, client, hostname, role); + NewClientHandlerInternal(yc, strand, client, hostname, role); } catch (const std::exception& ex) { Log(LogCritical, "ApiListener") << "Exception while handling new API client connection: " << DiagnosticInformation(ex, false); @@ -506,7 +515,10 @@ void ApiListener::NewClientHandler(boost::asio::yield_context yc, const std::sha * * @param client The new client. */ -void ApiListener::NewClientHandlerInternal(boost::asio::yield_context yc, const std::shared_ptr& client, const String& hostname, ConnectionRole role) +void ApiListener::NewClientHandlerInternal( + boost::asio::yield_context yc, const Shared::Ptr& strand, + const std::shared_ptr& client, const String& hostname, ConnectionRole role +) { namespace asio = boost::asio; namespace ssl = asio::ssl; @@ -533,7 +545,34 @@ void ApiListener::NewClientHandlerInternal(boost::asio::yield_context yc, const boost::system::error_code ec; - sslConn.async_handshake(role == RoleClient ? sslConn.client : sslConn.server, yc[ec]); + { + struct DoneHandshake + { + bool Done = false; + }; + + auto doneHandshake (Shared::Make()); + + IoEngine::SpawnCoroutine(*strand, [strand, client, doneHandshake](asio::yield_context yc) { + namespace sys = boost::system; + + { + boost::asio::deadline_timer timer (strand->context()); + timer.expires_from_now(boost::posix_time::microseconds(intmax_t(Configuration::TlsHandshakeTimeout * 1000000))); + + sys::error_code ec; + timer.async_wait(yc[ec]); + } + + if (!doneHandshake->Done) { + sys::error_code ec; + client->lowest_layer().cancel(ec); + } + }); + + sslConn.async_handshake(role == RoleClient ? sslConn.client : sslConn.server, yc[ec]); + doneHandshake->Done = true; + } if (ec) { // https://github.com/boostorg/beast/issues/915 diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp index e3a1b0d9a..7bac3ad94 100644 --- a/lib/remote/apilistener.hpp +++ b/lib/remote/apilistener.hpp @@ -17,6 +17,7 @@ #include "base/tlsstream.hpp" #include "base/threadpool.hpp" #include +#include #include #include #include @@ -152,8 +153,14 @@ private: bool AddListener(const String& node, const String& service); void AddConnection(const Endpoint::Ptr& endpoint); - void NewClientHandler(boost::asio::yield_context yc, const std::shared_ptr& client, const String& hostname, ConnectionRole role); - void NewClientHandlerInternal(boost::asio::yield_context yc, const std::shared_ptr& client, const String& hostname, ConnectionRole role); + void NewClientHandler( + boost::asio::yield_context yc, const Shared::Ptr& strand, + const std::shared_ptr& client, const String& hostname, ConnectionRole role + ); + void NewClientHandlerInternal( + boost::asio::yield_context yc, const Shared::Ptr& strand, + const std::shared_ptr& client, const String& hostname, ConnectionRole role + ); void ListenerCoroutineProc(boost::asio::yield_context yc, const std::shared_ptr& server, const std::shared_ptr& sslContext); WorkQueue m_RelayQueue;