add local endpoint selection for tls client connections

This commit is contained in:
Alexandros Konstantinakis-Karmis 2020-05-29 15:25:20 +03:00
parent ef41583614
commit 90071f8318
6 changed files with 91 additions and 3 deletions

View File

@ -78,6 +78,16 @@ session::session(boost::asio::io_service &io_service,
impl_->start_resolve(host, service); impl_->start_resolve(host, service);
} }
session::session(boost::asio::io_service &io_service,
boost::asio::ssl::context &tls_ctx,
const boost::asio::ip::tcp::endpoint &local_endpoint,
const std::string &host,
const std::string &service)
: impl_(std::make_shared<session_tls_impl>(
io_service, tls_ctx, local_endpoint, host, service, boost::posix_time::seconds(60))) {
impl_->start_resolve(host, service);
}
session::session(boost::asio::io_service &io_service, session::session(boost::asio::io_service &io_service,
boost::asio::ssl::context &tls_ctx, const std::string &host, boost::asio::ssl::context &tls_ctx, const std::string &host,
const std::string &service, const std::string &service,
@ -87,6 +97,17 @@ session::session(boost::asio::io_service &io_service,
impl_->start_resolve(host, service); impl_->start_resolve(host, service);
} }
session::session(boost::asio::io_service &io_service,
boost::asio::ssl::context &tls_ctx,
const boost::asio::ip::tcp::endpoint &local_endpoint,
const std::string &host,
const std::string &service,
const boost::posix_time::time_duration &connect_timeout)
: impl_(std::make_shared<session_tls_impl>(io_service, tls_ctx, local_endpoint, host,
service, connect_timeout)) {
impl_->start_resolve(host, service);
}
session::~session() {} session::~session() {}
session::session(session &&other) noexcept : impl_(std::move(other.impl_)) {} session::session(session &&other) noexcept : impl_(std::move(other.impl_)) {}

View File

@ -33,7 +33,7 @@ session_tls_impl::session_tls_impl(
boost::asio::io_service &io_service, boost::asio::ssl::context &tls_ctx, boost::asio::io_service &io_service, boost::asio::ssl::context &tls_ctx,
const std::string &host, const std::string &service, const std::string &host, const std::string &service,
const boost::posix_time::time_duration &connect_timeout) const boost::posix_time::time_duration &connect_timeout)
: session_impl(io_service, connect_timeout), socket_(io_service, tls_ctx) { : session_impl(io_service, connect_timeout), tcp_socket_(io_service), socket_(tcp_socket_, tls_ctx) {
// this callback setting is no effect is // this callback setting is no effect is
// ssl::context::set_verify_mode(boost::asio::ssl::verify_peer) is // ssl::context::set_verify_mode(boost::asio::ssl::verify_peer) is
// not used, which is what we want. // not used, which is what we want.
@ -44,6 +44,27 @@ session_tls_impl::session_tls_impl(
} }
} }
session_tls_impl::session_tls_impl(
boost::asio::io_service &io_service, boost::asio::ssl::context &tls_ctx,
const boost::asio::ip::tcp::endpoint &local_endpoint,
const std::string &host, const std::string &service,
const boost::posix_time::time_duration &connect_timeout)
: session_impl(io_service, connect_timeout), tcp_socket_(io_service), socket_(tcp_socket_, tls_ctx) {
// this callback setting is no effect is
// ssl::context::set_verify_mode(boost::asio::ssl::verify_peer) is
// not used, which is what we want.
tcp_socket_.open(local_endpoint.protocol());
boost::asio::socket_base::reuse_address option(true);
tcp_socket_.set_option(option);
tcp_socket_.bind(local_endpoint);
socket_.set_verify_callback(boost::asio::ssl::rfc2818_verification(host));
auto ssl = socket_.native_handle();
if (!util::numeric_host(host.c_str())) {
SSL_set_tlsext_host_name(ssl, host.c_str());
}
}
session_tls_impl::~session_tls_impl() {} session_tls_impl::~session_tls_impl() {}
void session_tls_impl::start_connect(tcp::resolver::iterator endpoint_it) { void session_tls_impl::start_connect(tcp::resolver::iterator endpoint_it) {

View File

@ -35,7 +35,7 @@ namespace client {
using boost::asio::ip::tcp; using boost::asio::ip::tcp;
using ssl_socket = boost::asio::ssl::stream<tcp::socket>; using ssl_socket = boost::asio::ssl::stream<tcp::socket&>;
class session_tls_impl : public session_impl { class session_tls_impl : public session_impl {
public: public:
@ -43,6 +43,12 @@ public:
boost::asio::ssl::context &tls_ctx, const std::string &host, boost::asio::ssl::context &tls_ctx, const std::string &host,
const std::string &service, const std::string &service,
const boost::posix_time::time_duration &connect_timeout); const boost::posix_time::time_duration &connect_timeout);
session_tls_impl(boost::asio::io_service &io_service,
boost::asio::ssl::context &tls_ctx,
const boost::asio::ip::tcp::endpoint & local_endpoint,
const std::string &host,
const std::string &service,
const boost::posix_time::time_duration &connect_timeout);
virtual ~session_tls_impl(); virtual ~session_tls_impl();
virtual void start_connect(tcp::resolver::iterator endpoint_it); virtual void start_connect(tcp::resolver::iterator endpoint_it);
@ -56,6 +62,7 @@ public:
virtual void shutdown_socket(); virtual void shutdown_socket();
private: private:
tcp::socket tcp_socket_;
ssl_socket socket_; ssl_socket socket_;
}; };

View File

@ -193,5 +193,27 @@ bool tls_h2_negotiated(ssl_socket &socket) {
return util::check_h2_is_selected(StringRef{next_proto, next_proto_len}); return util::check_h2_is_selected(StringRef{next_proto, next_proto_len});
} }
bool tls_h2_negotiated(ssl_tcp_socket &socket) {
auto ssl = socket.native_handle();
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len = 0;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (next_proto == nullptr) {
SSL_get0_alpn_selected(ssl, &next_proto, &next_proto_len);
}
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
if (next_proto == nullptr) {
return false;
}
return util::check_h2_is_selected(StringRef{next_proto, next_proto_len});
}
} // namespace asio_http2 } // namespace asio_http2
} // namespace nghttp2 } // namespace nghttp2

View File

@ -62,9 +62,11 @@ void split_path(uri_ref &dst, InputIt first, InputIt last) {
using boost::asio::ip::tcp; using boost::asio::ip::tcp;
using ssl_socket = boost::asio::ssl::stream<tcp::socket>; using ssl_socket = boost::asio::ssl::stream<tcp::socket&>;
using ssl_tcp_socket = boost::asio::ssl::stream<tcp::socket>;
bool tls_h2_negotiated(ssl_socket &socket); bool tls_h2_negotiated(ssl_socket &socket);
bool tls_h2_negotiated(ssl_tcp_socket &socket);
} // namespace asio_http2 } // namespace asio_http2

View File

@ -175,6 +175,13 @@ public:
boost::asio::ssl::context &tls_context, const std::string &host, boost::asio::ssl::context &tls_context, const std::string &host,
const std::string &service); const std::string &service);
// save as previous with pegged local endpoint
session(boost::asio::io_service &io_service,
boost::asio::ssl::context &tls_context,
const boost::asio::ip::tcp::endpoint &local_endpoint,
const std::string &host,
const std::string &service);
// Starts HTTP/2 session by connecting to |host| and |service| // Starts HTTP/2 session by connecting to |host| and |service|
// (e.g., "443") using encrypted SSL/TLS connection with given // (e.g., "443") using encrypted SSL/TLS connection with given
// connect timeout. // connect timeout.
@ -183,6 +190,14 @@ public:
const std::string &service, const std::string &service,
const boost::posix_time::time_duration &connect_timeout); const boost::posix_time::time_duration &connect_timeout);
// same as previous with pegged local endpoint
session(boost::asio::io_service &io_service,
boost::asio::ssl::context &tls_context,
const boost::asio::ip::tcp::endpoint &local_endpoint,
const std::string &host,
const std::string &service,
const boost::posix_time::time_duration &connect_timeout);
~session(); ~session();
session(session &&other) noexcept; session(session &&other) noexcept;