Support TLS SNI on server side.

This commit is contained in:
XieHan
2021-04-06 01:53:39 +08:00
parent cc521d563b
commit 6325e8e776
5 changed files with 65 additions and 15 deletions
+4
View File
@@ -56,6 +56,8 @@ protected:
this->ssl_connect_timeout = ssl_connect_timeout;
}
SSL_CTX *get_ssl_ctx() const { return this->ssl_ctx; }
private:
virtual int create_connect_fd()
{
@@ -181,6 +183,8 @@ protected:
this->ssl_accept_timeout = ssl_accept_timeout;
}
SSL_CTX *get_ssl_ctx() const { return this->ssl_ctx; }
private:
virtual CommSession *new_session(long long seq, CommConnection *conn) = 0;
virtual void handle_stop(int error) { }
+3 -7
View File
@@ -173,7 +173,7 @@ public:
}
SSL_CTX *get_ssl_client_ctx() { return ssl_client_ctx_; }
SSL_CTX *get_ssl_server_ctx() { return ssl_server_ctx_; }
SSL_CTX *new_ssl_server_ctx() { return SSL_CTX_new(SSLv23_server_method()); }
private:
__SSLManager()
@@ -189,14 +189,11 @@ private:
ssl_client_ctx_ = SSL_CTX_new(SSLv23_client_method());
assert(ssl_client_ctx_ != NULL);
ssl_server_ctx_ = SSL_CTX_new(SSLv23_server_method());
assert(ssl_server_ctx_ != NULL);
}
~__SSLManager()
{
SSL_CTX_free(ssl_client_ctx_);
SSL_CTX_free(ssl_server_ctx_);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
//free ssl to avoid memory leak
@@ -224,7 +221,6 @@ private:
private:
SSL_CTX *ssl_client_ctx_;
SSL_CTX *ssl_server_ctx_;
};
class IOServer : public IOService
@@ -559,9 +555,9 @@ SSL_CTX *WFGlobal::get_ssl_client_ctx()
return __SSLManager::get_instance()->get_ssl_client_ctx();
}
SSL_CTX *WFGlobal::get_ssl_server_ctx()
SSL_CTX *WFGlobal::new_ssl_server_ctx()
{
return __SSLManager::get_instance()->get_ssl_server_ctx();
return __SSLManager::get_instance()->new_ssl_server_ctx();
}
ExecQueue *WFGlobal::get_exec_queue(const std::string& queue_name)
+1 -1
View File
@@ -111,7 +111,7 @@ public:
static DNSCache *get_dns_cache();
static RouteManager *get_route_manager();
static SSL_CTX *get_ssl_client_ctx();
static SSL_CTX *get_ssl_server_ctx();
static SSL_CTX *new_ssl_server_ctx();
static ExecQueue *get_exec_queue(const std::string& queue_name);
static Executor *get_compute_executor();
static IOService *get_io_service();
+45 -7
View File
@@ -49,6 +49,42 @@ private:
std::atomic<size_t> *conn_count;
};
long WFServerBase::ssl_ctx_callback(SSL *ssl, int *al, void *arg)
{
WFServerBase *server = (WFServerBase *)arg;
const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
SSL_CTX *ssl_ctx = server->get_server_ssl_ctx(servername);
if (!ssl_ctx)
return SSL_TLSEXT_ERR_NOACK;
if (ssl_ctx != server->get_ssl_ctx())
SSL_set_SSL_CTX(ssl, ssl_ctx);
return SSL_TLSEXT_ERR_OK;
}
int WFServerBase::init_ssl_ctx(const char *cert_file, const char *key_file)
{
SSL_CTX *ssl_ctx = WFGlobal::new_ssl_server_ctx();
if (!ssl_ctx)
return -1;
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
if (SSL_CTX_use_certificate_file(ssl_ctx, cert_file, SSL_FILETYPE_PEM) > 0 &&
SSL_CTX_use_PrivateKey_file(ssl_ctx, key_file, SSL_FILETYPE_PEM) > 0 &&
SSL_CTX_set_tlsext_servername_callback(ssl_ctx, ssl_ctx_callback) > 0 &&
SSL_CTX_set_tlsext_servername_arg(ssl_ctx, this) > 0)
{
this->set_ssl(ssl_ctx, this->params.ssl_accept_timeout);
return 0;
}
SSL_CTX_free(ssl_ctx);
return -1;
}
int WFServerBase::init(const struct sockaddr *bind_addr, socklen_t addrlen,
const char *cert_file, const char *key_file)
{
@@ -65,17 +101,11 @@ int WFServerBase::init(const struct sockaddr *bind_addr, socklen_t addrlen,
if (key_file && cert_file)
{
SSL_CTX *ssl_ctx = WFGlobal::get_ssl_server_ctx();
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
if (SSL_CTX_use_certificate_file(ssl_ctx, cert_file, SSL_FILETYPE_PEM) <= 0 ||
SSL_CTX_use_PrivateKey_file(ssl_ctx, key_file, SSL_FILETYPE_PEM) <= 0)
if (this->init_ssl_ctx(cert_file, key_file) < 0)
{
this->deinit();
return -1;
}
this->set_ssl(ssl_ctx, params.ssl_accept_timeout);
}
this->scheduler = WFGlobal::get_scheduler();
@@ -131,12 +161,17 @@ void WFServerBase::handle_unbound()
int WFServerBase::start(const struct sockaddr *bind_addr, socklen_t addrlen,
const char *cert_file, const char *key_file)
{
SSL_CTX *ssl_ctx;
if (this->init(bind_addr, addrlen, cert_file, key_file) >= 0)
{
if (this->scheduler->bind(this) >= 0)
return 0;
ssl_ctx = this->get_ssl_ctx();
this->deinit();
if (ssl_ctx)
SSL_CTX_free(ssl_ctx);
}
return -1;
@@ -225,6 +260,7 @@ void WFServerBase::shutdown()
void WFServerBase::wait_finish()
{
SSL_CTX *ssl_ctx = this->get_ssl_ctx();
std::unique_lock<std::mutex> lock(this->mutex);
while (!this->unbind_finish)
@@ -233,5 +269,7 @@ void WFServerBase::wait_finish()
this->deinit();
this->unbind_finish = false;
lock.unlock();
if (ssl_ctx)
SSL_CTX_free(ssl_ctx);
}
+12
View File
@@ -22,6 +22,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <openssl/ssl.h>
#include <functional>
#include <atomic>
#include <mutex>
@@ -144,6 +145,15 @@ public:
public:
size_t get_conn_count() const { return this->conn_count; }
private:
/* Override this function to implement server that supports TLS SNI.
* "servername" will be NULL if client does not set a host name.
* Returning NULL to indicate that servername is not supported. */
virtual SSL_CTX *get_server_ssl_ctx(const char *servername)
{
return this->get_ssl_ctx();
}
protected:
WFServerParams params;
@@ -153,6 +163,8 @@ protected:
private:
int init(const struct sockaddr *bind_addr, socklen_t addrlen,
const char *cert_file, const char *key_file);
int init_ssl_ctx(const char *cert_file, const char *key_file);
static long ssl_ctx_callback(SSL *ssl, int *al, void *arg);
virtual int create_listen_fd();
virtual void handle_unbound();