up session cache校验ssl version,增加ssl状态读写的接口。

This commit is contained in:
zhengchao
2019-05-17 21:35:20 +08:00
parent 630a3dba60
commit dda60c674c
12 changed files with 263 additions and 94 deletions

View File

@@ -134,6 +134,8 @@ struct ssl_mgr
struct sess_cache * down_sess_cache;
struct sess_cache * up_sess_cache;
struct ssl_service_cache* svc_cache;
ssl_stream_new_hook* on_new_hook_func;
void* hook_u_para;
struct session_ticket_key ticket_key;
char default_ciphers[TFE_SYMBOL_MAX];
@@ -165,7 +167,7 @@ struct __ssl_stream_debug
{
evutil_socket_t fd;
};
struct ssl_bypass
struct ssl_bypass_condition
{
char bypass_ev_cert;
char bypass_ct_cert;
@@ -177,10 +179,10 @@ struct ssl_upstream_parts
struct cert_verify_param verify_param;
struct cert_verify_result verify_result;
char verify_failed_action;
char block_fake_cert;
struct ssl_service_status svc_status;
enum ssl_stream_action action;
struct ssl_bypass bypass_condition;
struct ssl_chello * client_hello;
int is_server_cert_verify_passed;
};
@@ -198,6 +200,7 @@ struct ssl_stream
struct ssl_upstream_parts up_parts;
struct ssl_downstream_parts down_parts;
};
int ssl_min_ver, ssl_max_ver;
const unsigned char* alpn_selected; //reference to SSL_ALPN_HTTP_2/SSL_ALPN_HTTP_1_1
struct ssl_stream* peer;
struct __ssl_stream_debug _do_not_use;
@@ -417,13 +420,13 @@ struct ssl_stream * ssl_stream_new(struct ssl_mgr * mgr, evutil_socket_t fd, enu
{
case CONN_DIR_DOWNSTREAM:
ATOMIC_INC(&(s_stream->mgr->stat_val[SSL_DOWN_NEW]));
s_stream->ssl = downstream_ssl_create(mgr, kyr, selected_alpn);
s_stream->down_parts.keyring = kyr;
s_stream->ssl = downstream_ssl_create(mgr, kyr, selected_alpn);
break;
case CONN_DIR_UPSTREAM:
ATOMIC_INC(&(s_stream->mgr->stat_val[SSL_UP_NEW]));
s_stream->up_parts.verify_param.no_verify_expiry_date=1;
s_stream->up_parts.client_hello = client_hello;
s_stream->up_parts.client_hello = client_hello;
s_stream->ssl = upstream_ssl_create(mgr, s_stream, fd);
break;
default: assert(0);
@@ -552,8 +555,8 @@ void ssl_manager_destroy(struct ssl_mgr * mgr)
}
struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section,
struct event_base * ev_base_gc, void * logger)
struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section,
struct event_base * ev_base_gc, void * logger, ssl_stream_new_hook* hook_func, void* hook_u_para)
{
unsigned char key_name[]="!mesalab-tfe3a~&";
unsigned char aes_key_def[]={0xC5,0xAC,0xC1,0xA6,0xB2,0xBB,0xCA,0xC7,0xE3,0xBE,0xE3,0xB2,0xC6,0xA3,0xB1,0xB9
@@ -622,7 +625,8 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section
mgr->down_sess_cache = ssl_sess_cache_create(mgr->cache_slots, mgr->sess_expire_seconds, CONN_DIR_DOWNSTREAM);
}
mgr->svc_cache=ssl_service_cache_create(mgr->cache_slots, mgr->sess_expire_seconds);
mgr->on_new_hook_func=hook_func;
mgr->hook_u_para=hook_u_para;
//Reference to NGINX: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_ticket_key
//Support key rotation in futher.
@@ -863,7 +867,8 @@ static SSL * upstream_ssl_create(struct ssl_mgr * mgr, struct ssl_stream* s_stre
if(ret == 0)
{
/* session resuming based on remote endpoint address and port */
sess = up_session_get(mgr->up_sess_cache, (struct sockaddr *) &addr, addrlen, chello->sni);
sess = up_session_get(mgr->up_sess_cache, (struct sockaddr *) &addr, addrlen, chello->sni,
SSL_get_min_proto_version(ssl), SSL_get_max_proto_version(ssl));
if (sess)
{
SSL_set_session(ssl, sess); /* increments sess refcount */
@@ -904,6 +909,16 @@ void wrap_ssl_connect_server_ctx_free(void *p)
struct ssl_connect_server_ctx * ctx = (struct ssl_connect_server_ctx *)p;
ssl_connect_server_ctx_free(ctx);
}
enum ssl_stream_action ssl_upstream_create_result_release_action(future_result_t * result)
{
struct ssl_connect_server_ctx * ctx = (struct ssl_connect_server_ctx *) result;
return ctx->s_stream->up_parts.action;
}
evutil_socket_t ssl_upstream_create_result_release_fd(future_result_t * result)
{
struct ssl_connect_server_ctx * ctx = (struct ssl_connect_server_ctx *) result;
return ctx->fd_upstream;
}
struct ssl_stream * ssl_upstream_create_result_release_stream(future_result_t * result)
{
@@ -1105,6 +1120,10 @@ static void ssl_server_connected_eventcb(struct bufferevent * bev, short events,
s_stream->up_parts.verify_result.is_hostmatched,
s_stream->up_parts.verify_result.is_ct,
s_stream->up_parts.verify_result.is_ev);
if((!s_stream->up_parts.is_server_cert_verify_passed || !s_stream->up_parts.verify_result.is_hostmatched) && s_stream->up_parts.block_fake_cert)
{
s_stream->up_parts.action=SSL_ACTION_SHUTDOWN;
}
}
if(s_stream->up_parts.is_server_cert_verify_passed)
{
@@ -1114,7 +1133,7 @@ static void ssl_server_connected_eventcb(struct bufferevent * bev, short events,
//The reference count of the SSL_SESSION is not incremented, so no need to free.
ssl_sess = SSL_get0_session(s_stream->ssl);
up_session_set(mgr->up_sess_cache, (struct sockaddr *)&(ctx->addr),
ctx->addrlen, s_upstream->client_hello->sni, ssl_sess);
ctx->addrlen, s_upstream->client_hello->sni, SSL_version(s_stream->ssl), ssl_sess);
}
}
else
@@ -1161,10 +1180,10 @@ static void ssl_server_connected_eventcb(struct bufferevent * bev, short events,
static void peek_chello_on_succ(future_result_t * result, void * user)
{
struct promise * p = (struct promise *) user;
struct ssl_connect_server_ctx * ctx = (struct ssl_connect_server_ctx *) promise_get_ctx(p);
struct ssl_connect_server_ctx* ctx = (struct ssl_connect_server_ctx *) promise_get_ctx(p);
struct event_base* evbase=tfe_proxy_get_work_thread_evbase(ctx->thread_id);
struct ssl_chello * chello = ssl_peek_result_release_chello(result);//chello has been saved in ssl_stream.
struct ssl_stream* s_stream=NULL;
struct ssl_chello* chello = ssl_peek_result_release_chello(result);//chello has been saved in ssl_stream.
if(chello->sni==NULL)
{
ATOMIC_INC(&(ctx->mgr->stat_val[SSL_NO_SNI]));
@@ -1172,8 +1191,8 @@ static void peek_chello_on_succ(future_result_t * result, void * user)
int ret=0;
struct ssl_service_status* svc_status=NULL;
clock_gettime(CLOCK_MONOTONIC, &(ctx->start));
ctx->s_stream = ssl_stream_new(ctx->mgr, ctx->fd_upstream, CONN_DIR_UPSTREAM, chello, NULL, NULL);
svc_status=&ctx->s_stream->up_parts.svc_status;
s_stream= ssl_stream_new(ctx->mgr, ctx->fd_upstream, CONN_DIR_UPSTREAM, chello, NULL, NULL);
svc_status=&s_stream->up_parts.svc_status;
ret=ssl_service_cache_read(ctx->mgr->svc_cache, chello, svc_status);
if(ret==1)
{
@@ -1184,15 +1203,25 @@ static void peek_chello_on_succ(future_result_t * result, void * user)
svc_status->is_ct,
svc_status->is_ev);
}
ctx->bev = bufferevent_openssl_socket_new(evbase, ctx->fd_upstream,
ctx->s_stream->ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE );
s_stream->up_parts.action=ctx->mgr->on_new_hook_func(s_stream, ctx->mgr->hook_u_para);
ctx->s_stream = s_stream;
if(s_stream->up_parts.action==SSL_ACTION_PASSTHROUGH)
{
promise_success(p, ctx);
wrap_ssl_connect_server_ctx_free(ctx);
}
else
{
ctx->bev = bufferevent_openssl_socket_new(evbase, ctx->fd_upstream,
ctx->s_stream->ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE );
bufferevent_openssl_set_allow_dirty_shutdown(ctx->bev, 1);
bufferevent_setcb(ctx->bev, NULL, NULL, ssl_server_connected_eventcb, p);
bufferevent_enable(ctx->bev, EV_READ | EV_WRITE); //waiting for connect event only
bufferevent_openssl_set_allow_dirty_shutdown(ctx->bev, 1);
bufferevent_setcb(ctx->bev, NULL, NULL, ssl_server_connected_eventcb, p);
bufferevent_enable(ctx->bev, EV_READ | EV_WRITE); //waiting for connect event only
future_destroy(ctx->f_peek_chello);
ctx->f_peek_chello = NULL;
future_destroy(ctx->f_peek_chello);
ctx->f_peek_chello = NULL;
}
return;
}
@@ -1316,7 +1345,7 @@ static int ossl_session_ticket_key_callback(SSL *ssl_conn,
* the refcount decrementing. In other words, return 0 if we did not
* keep a pointer to the object (which we never do here).
*/
static int ossl_sessnew_cb(SSL * ssl, SSL_SESSION * sess)
static int ossl_downsess_new_cb(SSL * ssl, SSL_SESSION * sess)
{
struct ssl_mgr * mgr = (struct ssl_mgr *) SSL_get_ex_data(ssl, SSL_CTX_EX_DATA_IDX_SSLMGR);
@@ -1343,7 +1372,7 @@ static int ossl_sessnew_cb(SSL * ssl, SSL_SESSION * sess)
* OpenSSL calls SSL_SESSION_free() after calling the callback;
* we do not need to free the reference here.
*/
static void ossl_sessremove_cb(SSL_CTX * sslctx, SSL_SESSION * sess)
static void ossl_downsess_remove_cb(SSL_CTX * sslctx, SSL_SESSION * sess)
{
struct ssl_mgr * mgr = (struct ssl_mgr *) SSL_CTX_get_ex_data(sslctx, SSL_CTX_EX_DATA_IDX_SSLMGR);
assert(mgr != NULL);
@@ -1360,7 +1389,7 @@ static void ossl_sessremove_cb(SSL_CTX * sslctx, SSL_SESSION * sess)
* Called by OpenSSL when a src SSL session is requested by the client.
OPENSSL_VERSION_NUMBER >= 0x10100000L required.
*/
static SSL_SESSION * ossl_sessget_cb(SSL * ssl, const unsigned char * id, int idlen, int * copy)
static SSL_SESSION * ossl_downsess_get_cb(SSL * ssl, const unsigned char * id, int idlen, int * copy)
{
struct ssl_mgr * mgr = (struct ssl_mgr *) SSL_get_ex_data(ssl, SSL_CTX_EX_DATA_IDX_SSLMGR);
SSL_SESSION * sess=NULL;
@@ -1470,9 +1499,9 @@ static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt, c
}
}
SSL_CTX_sess_set_new_cb(sslctx, ossl_sessnew_cb);
SSL_CTX_sess_set_remove_cb(sslctx, ossl_sessremove_cb);
SSL_CTX_sess_set_get_cb(sslctx, ossl_sessget_cb);
SSL_CTX_sess_set_new_cb(sslctx, ossl_downsess_new_cb);
SSL_CTX_sess_set_remove_cb(sslctx, ossl_downsess_remove_cb);
SSL_CTX_sess_set_get_cb(sslctx, ossl_downsess_get_cb);
if(!mgr->no_sessticket)
{
SSL_CTX_set_tlsext_ticket_key_cb(sslctx, ossl_session_ticket_key_callback);
@@ -1652,7 +1681,8 @@ void ask_keyring_on_succ(void * result, void * user)
kyr = key_keeper_release_keyring(result); //kyr will be freed at ssl downstream closing.
clock_gettime(CLOCK_MONOTONIC, &(ctx->start));
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,
ctx->origin_ssl->up_parts.client_hello, kyr,
ctx->origin_ssl?ctx->origin_ssl->alpn_selected:NULL);
ctx->downstream->peer=ctx->origin_ssl;
ctx->bev_down = bufferevent_openssl_socket_new(evbase, ctx->fd_downstream, ctx->downstream->ssl,
@@ -1877,4 +1907,57 @@ void ssl_manager_reset_trust_ca(struct ssl_mgr* mgr)
ssl_trusted_cert_storage_reset(mgr->trust_CA_store);
return;
}
int ssl_stream_set_integer_opt(struct ssl_stream *upstream, enum SSL_STREAM_OPT opt_type, int opt_val)
{
struct cert_verify_param *verify_param=&(upstream->up_parts.verify_param);
switch(opt_type)
{
case SSL_STREAM_OPT_NO_VERIFY_SELF_SIGNED:
verify_param->no_verify_self_signed=opt_val;
break;
case SSL_STREAM_OPT_NO_VERIFY_COMMON_NAME:
verify_param->no_verify_cn=opt_val;
break;
case SSL_STREAM_OPT_NO_VERIFY_ISSUER:
verify_param->no_verify_issuer=opt_val;
break;
case SSL_STREAM_OPT_NO_VERIFY_EXPIRY_DATE:
verify_param->no_verify_expiry_date=opt_val;
break;
case SST_STREAM_OPT_VERIFY_FAIL_ACTION:
upstream->up_parts.block_fake_cert=opt_val;
break;
case SSL_STREAM_OPT_PROTOCOL_MIN_VERSION:
case SSL_STREAM_OPT_PROTOCOL_MAX_VERSION:
break;
default:
return 0;
}
return 1;
}
int ssl_stream_get_integer_opt(struct ssl_stream *upstream, enum SSL_STREAM_OPT opt_type, int *opt_val)
{
struct ssl_service_status* svc=&upstream->up_parts.svc_status;
switch(opt_type)
{
case SSL_STREAM_OPT_IS_EV_CERT:
*opt_val=svc->is_ev;
break;
case SSL_STREAM_OPT_IS_CT_CERT:
*opt_val=svc->is_ct;
break;
case SSL_STREAM_OPT_IS_MUTUAL_AUTH:
*opt_val=svc->is_mutual_auth;
break;
case SSL_STREAM_OPT_PINNING_STATUS:
*opt_val=svc->pinning_status;
break;
default:
return 0;
}
return 1;
}