up session cache校验ssl version,增加ssl状态读写的接口。
This commit is contained in:
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user