在downstream ssl create 中处理alpn扩展选项的回调。
This commit is contained in:
@@ -48,6 +48,9 @@ int SSL_PEER_CERT_VERIFY_FAILED=0;
|
|||||||
*/
|
*/
|
||||||
#define DFLT_CIPHERS "ALL:-aNULL"
|
#define DFLT_CIPHERS "ALL:-aNULL"
|
||||||
|
|
||||||
|
static unsigned char SSL_ALPN_HTTP_1_1[]={8, 'h', 't', 't', 'p', '/', '1', '.', '1',0};
|
||||||
|
static unsigned char SSL_ALPN_HTTP_2[]={2, 'h','2',0};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Default elliptic curve for EC cipher suites.
|
* Default elliptic curve for EC cipher suites.
|
||||||
*/
|
*/
|
||||||
@@ -99,6 +102,7 @@ struct ssl_mgr
|
|||||||
unsigned int no_tls11;
|
unsigned int no_tls11;
|
||||||
unsigned int no_tls12;
|
unsigned int no_tls12;
|
||||||
unsigned int no_sessticket;
|
unsigned int no_sessticket;
|
||||||
|
unsigned int no_alpn;
|
||||||
|
|
||||||
CONST_SSL_METHOD * (* sslmethod)(void); //Parameter of SSL_CTX_new
|
CONST_SSL_METHOD * (* sslmethod)(void); //Parameter of SSL_CTX_new
|
||||||
int ssl_min_version, ssl_max_version;
|
int ssl_min_version, ssl_max_version;
|
||||||
@@ -151,6 +155,7 @@ struct ssl_stream
|
|||||||
struct ssl_chello * client_hello; //dir=upstream, a little weird, which send by downstream client.
|
struct ssl_chello * client_hello; //dir=upstream, a little weird, which send by downstream client.
|
||||||
struct keyring * keyring; //dir=downstream.
|
struct keyring * keyring; //dir=downstream.
|
||||||
};
|
};
|
||||||
|
const unsigned char* alpn_selected;
|
||||||
struct __ssl_stream_debug _do_not_use;
|
struct __ssl_stream_debug _do_not_use;
|
||||||
int is_peer_cert_verify_passed;
|
int is_peer_cert_verify_passed;
|
||||||
};
|
};
|
||||||
@@ -320,7 +325,7 @@ void ssl_stat_init(struct ssl_mgr * mgr)
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt);
|
static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt, const unsigned char* selected_alpn);
|
||||||
static SSL * upstream_ssl_create(struct ssl_mgr * mgr, const struct ssl_chello * chello, evutil_socket_t fd);
|
static SSL * upstream_ssl_create(struct ssl_mgr * mgr, const struct ssl_chello * chello, evutil_socket_t fd);
|
||||||
static void sslctx_set_opts(SSL_CTX * sslctx, struct ssl_mgr * mgr);
|
static void sslctx_set_opts(SSL_CTX * sslctx, struct ssl_mgr * mgr);
|
||||||
|
|
||||||
@@ -333,7 +338,7 @@ struct ssl_chello * ssl_peek_result_release_chello(future_result_t * result)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ssl_stream * ssl_stream_new(struct ssl_mgr * mgr, evutil_socket_t fd, enum tfe_conn_dir dir,
|
struct ssl_stream * ssl_stream_new(struct ssl_mgr * mgr, evutil_socket_t fd, enum tfe_conn_dir dir,
|
||||||
struct ssl_chello * client_hello, struct keyring * kyr)
|
struct ssl_chello * client_hello, struct keyring * kyr, const unsigned char* selected_alpn)
|
||||||
{
|
{
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -346,7 +351,7 @@ struct ssl_stream * ssl_stream_new(struct ssl_mgr * mgr, evutil_socket_t fd, enu
|
|||||||
{
|
{
|
||||||
case CONN_DIR_DOWNSTREAM:
|
case CONN_DIR_DOWNSTREAM:
|
||||||
ATOMIC_INC(&(s_stream->mgr->stat_val[SSL_DOWN_NEW]));
|
ATOMIC_INC(&(s_stream->mgr->stat_val[SSL_DOWN_NEW]));
|
||||||
s_stream->ssl = downstream_ssl_create(mgr, kyr);
|
s_stream->ssl = downstream_ssl_create(mgr, kyr, selected_alpn);
|
||||||
s_stream->keyring = kyr;
|
s_stream->keyring = kyr;
|
||||||
break;
|
break;
|
||||||
case CONN_DIR_UPSTREAM:
|
case CONN_DIR_UPSTREAM:
|
||||||
@@ -383,7 +388,10 @@ static void ssl_stream_free(struct ssl_stream * s_stream)
|
|||||||
break;
|
break;
|
||||||
default: assert(0);
|
default: assert(0);
|
||||||
}
|
}
|
||||||
|
if(s_stream->alpn_selected)
|
||||||
|
{
|
||||||
|
s_stream->alpn_selected=NULL;
|
||||||
|
}
|
||||||
s_stream->mgr = NULL;
|
s_stream->mgr = NULL;
|
||||||
free(s_stream);
|
free(s_stream);
|
||||||
return;
|
return;
|
||||||
@@ -521,6 +529,8 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section
|
|||||||
MESA_load_profile_string_def(ini_profile, section, "default_ciphers", mgr->default_ciphers,
|
MESA_load_profile_string_def(ini_profile, section, "default_ciphers", mgr->default_ciphers,
|
||||||
sizeof(mgr->default_ciphers), DFLT_CIPHERS);
|
sizeof(mgr->default_ciphers), DFLT_CIPHERS);
|
||||||
MESA_load_profile_uint_def(ini_profile, section, "no_session_ticket", &(mgr->no_sessticket), 0);
|
MESA_load_profile_uint_def(ini_profile, section, "no_session_ticket", &(mgr->no_sessticket), 0);
|
||||||
|
MESA_load_profile_uint_def(ini_profile, section, "no_alpn", &(mgr->no_alpn), 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -794,10 +804,10 @@ static SSL * upstream_ssl_create(struct ssl_mgr * mgr, const struct ssl_chello *
|
|||||||
{
|
{
|
||||||
SSL_set_tlsext_host_name(ssl, chello->sni);
|
SSL_set_tlsext_host_name(ssl, chello->sni);
|
||||||
}
|
}
|
||||||
if (chello->alpn)
|
if (chello->alpn && !mgr->no_alpn)
|
||||||
{
|
{
|
||||||
ret=SSL_set_alpn_protos(ssl, (unsigned char*)chello->alpn, strlen(chello->alpn));
|
ret=SSL_set_alpn_protos(ssl, (unsigned char*)chello->alpn, strlen(chello->alpn));
|
||||||
assert(0);
|
assert(ret==0);
|
||||||
}
|
}
|
||||||
/* lower memory footprint for idle connections */
|
/* lower memory footprint for idle connections */
|
||||||
SSL_set_mode(ssl, SSL_get_mode(ssl) | SSL_MODE_RELEASE_BUFFERS);
|
SSL_set_mode(ssl, SSL_get_mode(ssl) | SSL_MODE_RELEASE_BUFFERS);
|
||||||
@@ -1017,6 +1027,24 @@ static void ssl_server_connected_eventcb(struct bufferevent * bev, short events,
|
|||||||
{
|
{
|
||||||
log_ssl_master_key(s_stream->ssl, ctx->fd_upstream, CONN_DIR_UPSTREAM, mgr->fp_master_key);
|
log_ssl_master_key(s_stream->ssl, ctx->fd_upstream, CONN_DIR_UPSTREAM, mgr->fp_master_key);
|
||||||
}
|
}
|
||||||
|
const unsigned char *alpn_data=NULL;
|
||||||
|
unsigned int alpn_len=0;
|
||||||
|
SSL_get0_alpn_selected(s_stream->ssl, &alpn_data, &alpn_len);
|
||||||
|
if(alpn_len>0&&alpn_data!=NULL)
|
||||||
|
{
|
||||||
|
if(0==memcmp(alpn_data, SSL_ALPN_HTTP_1_1+1, alpn_len))
|
||||||
|
{
|
||||||
|
s_stream->alpn_selected=SSL_ALPN_HTTP_1_1;
|
||||||
|
}
|
||||||
|
else if(0==memcmp(alpn_data, SSL_ALPN_HTTP_2+1, alpn_len))
|
||||||
|
{
|
||||||
|
s_stream->alpn_selected=SSL_ALPN_HTTP_2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s_stream->alpn_selected=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
promise_success(p, ctx);
|
promise_success(p, ctx);
|
||||||
}
|
}
|
||||||
wrap_ssl_connect_server_ctx_free(ctx);
|
wrap_ssl_connect_server_ctx_free(ctx);
|
||||||
@@ -1033,7 +1061,7 @@ static void peek_chello_on_succ(future_result_t * result, void * user)
|
|||||||
{
|
{
|
||||||
ATOMIC_INC(&(ctx->mgr->stat_val[SSL_NO_SNI]));
|
ATOMIC_INC(&(ctx->mgr->stat_val[SSL_NO_SNI]));
|
||||||
}
|
}
|
||||||
ctx->s_stream = ssl_stream_new(ctx->mgr, ctx->fd_upstream, CONN_DIR_UPSTREAM, chello, NULL);
|
ctx->s_stream = ssl_stream_new(ctx->mgr, ctx->fd_upstream, CONN_DIR_UPSTREAM, chello, NULL, NULL);
|
||||||
ctx->bev = bufferevent_openssl_socket_new(ctx->evbase, ctx->fd_upstream,
|
ctx->bev = bufferevent_openssl_socket_new(ctx->evbase, ctx->fd_upstream,
|
||||||
ctx->s_stream->ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS);
|
ctx->s_stream->ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS);
|
||||||
|
|
||||||
@@ -1274,11 +1302,34 @@ static void sslctx_set_opts(SSL_CTX * sslctx, struct ssl_mgr * mgr)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
||||||
|
unsigned char *outlen, const unsigned char *in,
|
||||||
|
unsigned int inlen, void *arg) {
|
||||||
|
int rv;
|
||||||
|
const unsigned char* selected_alpn=(const unsigned char*)arg;
|
||||||
|
(void)ssl;
|
||||||
|
unsigned char* _out=NULL;
|
||||||
|
unsigned char _outlen=0;
|
||||||
|
rv=SSL_select_next_proto(&_out, &_outlen, in, inlen, selected_alpn, strlen((const char*)selected_alpn));
|
||||||
|
if(rv==OPENSSL_NPN_NEGOTIATED)
|
||||||
|
{
|
||||||
|
*out=_out;
|
||||||
|
*outlen=_outlen;
|
||||||
|
return SSL_TLSEXT_ERR_OK;
|
||||||
|
}
|
||||||
|
else //rv==OPENSSL_NPN_NO_OVERLAP
|
||||||
|
{
|
||||||
|
return SSL_TLSEXT_ERR_NOACK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create and set up a new SSL_CTX instance for terminating SSL.
|
* Create and set up a new SSL_CTX instance for terminating SSL.
|
||||||
* Set up all the necessary callbacks, the keyring, the keyring chain and key.
|
* Set up all the necessary callbacks, the keyring, the keyring chain and key.
|
||||||
*/
|
*/
|
||||||
static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt)
|
static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt, const unsigned char* selected_alpn)
|
||||||
{
|
{
|
||||||
SSL_CTX * sslctx = SSL_CTX_new(mgr->sslmethod());
|
SSL_CTX * sslctx = SSL_CTX_new(mgr->sslmethod());
|
||||||
if (!sslctx) return NULL;
|
if (!sslctx) return NULL;
|
||||||
@@ -1332,7 +1383,10 @@ static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt)
|
|||||||
SSL_CTX_set_tmp_ecdh(sslctx, ecdh);
|
SSL_CTX_set_tmp_ecdh(sslctx, ecdh);
|
||||||
EC_KEY_free(ecdh);
|
EC_KEY_free(ecdh);
|
||||||
}
|
}
|
||||||
|
if(!mgr->no_alpn)
|
||||||
|
{
|
||||||
|
SSL_CTX_set_alpn_select_cb(sslctx, alpn_select_proto_cb, (void*)selected_alpn);
|
||||||
|
}
|
||||||
SSL_CTX_use_certificate(sslctx, crt->cert);
|
SSL_CTX_use_certificate(sslctx, crt->cert);
|
||||||
SSL_CTX_use_PrivateKey(sslctx, crt->key);
|
SSL_CTX_use_PrivateKey(sslctx, crt->key);
|
||||||
|
|
||||||
@@ -1355,7 +1409,6 @@ static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt)
|
|||||||
/* lower memory footprint for idle connections */
|
/* lower memory footprint for idle connections */
|
||||||
SSL_set_mode(ssl, SSL_get_mode(ssl) | SSL_MODE_RELEASE_BUFFERS);
|
SSL_set_mode(ssl, SSL_get_mode(ssl) | SSL_MODE_RELEASE_BUFFERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ssl;
|
return ssl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1456,7 +1509,8 @@ void ask_keyring_on_succ(void * result, void * user)
|
|||||||
kyr = key_keeper_release_keyring(result); //kyr will be freed at ssl downstream closing.
|
kyr = key_keeper_release_keyring(result); //kyr will be freed at ssl downstream closing.
|
||||||
|
|
||||||
|
|
||||||
ctx->downstream = ssl_stream_new(mgr, ctx->fd_downstream, CONN_DIR_DOWNSTREAM, NULL, kyr);
|
ctx->downstream = ssl_stream_new(mgr, ctx->fd_downstream, CONN_DIR_DOWNSTREAM, NULL, kyr,
|
||||||
|
ctx->origin_ssl?ctx->origin_ssl->alpn_selected:NULL);
|
||||||
ctx->bev_down = bufferevent_openssl_socket_new(ctx->evbase, ctx->fd_downstream, ctx->downstream->ssl,
|
ctx->bev_down = bufferevent_openssl_socket_new(ctx->evbase, ctx->fd_downstream, ctx->downstream->ssl,
|
||||||
BUFFEREVENT_SSL_ACCEPTING, BEV_OPT_DEFER_CALLBACKS);
|
BUFFEREVENT_SSL_ACCEPTING, BEV_OPT_DEFER_CALLBACKS);
|
||||||
bufferevent_openssl_set_allow_dirty_shutdown(ctx->bev_down, 1);
|
bufferevent_openssl_set_allow_dirty_shutdown(ctx->bev_down, 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user