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

@@ -73,7 +73,7 @@ enum tfe_stream_opt_level
STREAM_OPT_LEVEL_TCP, STREAM_OPT_LEVEL_TCP,
STREAM_OPT_LEVEL_SSL //see tfe_types.h enum SSL_STREAM_OPT STREAM_OPT_LEVEL_SSL //see tfe_types.h enum SSL_STREAM_OPT
}; };
int tfe_stream_set_opt(struct tfe_stream * stream, enum tfe_stream_opt_level level, int type, const void* value, size_t size); int tfe_stream_set_integer_opt(struct tfe_stream * stream, enum tfe_stream_opt_level level, int type, int val);
/* /*
@return 0 if successful, or -1 if an error occurred @return 0 if successful, or -1 if an error occurred
*/ */

View File

@@ -159,20 +159,5 @@ char* tfe_string_addr_create_by_fd(int fd, enum tfe_conn_dir dir);
char * tfe_stream_addr_to_str(const struct tfe_stream_addr * addr); char * tfe_stream_addr_to_str(const struct tfe_stream_addr * addr);
int tfe_stream_addr_str_split(char* addr_str, const char** sip, const char** sport, const char** dip, const char** dport); int tfe_stream_addr_str_split(char* addr_str, const char** sip, const char** sport, const char** dip, const char** dport);
enum SSL_STREAM_OPT
{
SSL_STREAM_OPT_BYPASS_EV_CERT, //VALUE is an interger, SIZE=sizeof(int). 1:BYPASS, 0:INTERCEPT. DEFAULT:0.
SSL_STREAM_OPT_BYPASS_CT_CERT, //VALUE is an interger, SIZE=sizeof(int). 1:BYPASS, 0:INTERCEPT. DEFAULT:0.
SSL_STREAM_OPT_BYPASS_MUTUAL_AUTH, //VALUE is an interger, SIZE=sizeof(int). 1:BYPASS, 0:BLOCKED. DEFAULT:1.
SSL_STREAM_OPT_BYPASS_CERT_PINNING, //VALUE is an interger, SIZE=sizeof(int). 1:BYPASS, 0:BLOCKED. DEFAULT:1.
SSL_STREAM_OPT_VERIFY_SELF_SIGNED, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:1.
SSL_STREAM_OPT_VERIFY_COMMON_NAME, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:1.
SSL_STREAM_OPT_VERIFY_ISSUER, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:1.
SSL_STREAM_OPT_VERIFY_EXPIRY_DATE, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:1.
SST_STREAM_OPT_VERIFY_FAIL_ACTION, //VALUE is an interger, SIZE=sizeof(int). 1:PASSTHROUGH, 0:BLOCK. DEFAULT:1.
SSL_STREAM_OPT_PROTOCOL_MIN_VERSION,
SSL_STREAM_OPT_PROTOCOL_MAX_VERSION
};

View File

@@ -1,7 +1,8 @@
add_executable(tfe src/key_keeper.cpp src/kni_acceptor.cpp src/ssl_stream.cpp add_executable(tfe src/key_keeper.cpp src/kni_acceptor.cpp src/ssl_stream.cpp
src/ssl_sess_cache.cpp src/ssl_service_cache.cpp src/ssl_sess_cache.cpp src/ssl_service_cache.cpp
src/ssl_trusted_cert_storage.cpp src/ev_root_ca_metadata.cpp src/ssl_trusted_cert_storage.cpp src/ev_root_ca_metadata.cpp
src/ssl_utils.cpp src/tcp_stream.cpp src/main.cpp src/proxy.cpp) src/ssl_policy.cpp src/ssl_utils.cpp
src/tcp_stream.cpp src/main.cpp src/proxy.cpp)
target_include_directories(tfe PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include/external) target_include_directories(tfe PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include/external)
target_include_directories(tfe PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include/internal) target_include_directories(tfe PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include/internal)

View File

@@ -104,8 +104,8 @@ struct tfe_stream_private
unsigned int nr_plugin_ctxs; unsigned int nr_plugin_ctxs;
struct plugin_ctx * plugin_ctxs; struct plugin_ctx * plugin_ctxs;
/* TCP forward without scan or decode when the passthough is set */ /* TCP forward without scan or decode when the tcp_passthough is set */
bool passthough; bool tcp_passthough;
/* For defer connection setup */ /* For defer connection setup */
evutil_socket_t defer_fd_downstream; evutil_socket_t defer_fd_downstream;

View File

@@ -8,8 +8,8 @@ struct sess_cache;
struct sess_cache * ssl_sess_cache_create(unsigned int slot_size, unsigned int expire_seconds, enum tfe_conn_dir served); struct sess_cache * ssl_sess_cache_create(unsigned int slot_size, unsigned int expire_seconds, enum tfe_conn_dir served);
void ssl_sess_cache_destroy(struct sess_cache * cache); void ssl_sess_cache_destroy(struct sess_cache * cache);
void up_session_set(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni, SSL_SESSION * value); void up_session_set(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni, int version, SSL_SESSION * sess);
SSL_SESSION * up_session_get(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni); SSL_SESSION * up_session_get(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni, int min_ver, int max_ver);
void down_session_set(struct sess_cache * cache, const SSL_SESSION * sess); void down_session_set(struct sess_cache * cache, const SSL_SESSION * sess);
void down_session_del(struct sess_cache * cache, const SSL_SESSION * sess); void down_session_del(struct sess_cache * cache, const SSL_SESSION * sess);

View File

@@ -8,14 +8,6 @@
struct ssl_stream; struct ssl_stream;
struct ssl_mgr; struct ssl_mgr;
typedef void ssl_stream_new_cb(struct ssl_stream *, void* u_para);
typedef void ssl_stream_free_cb(struct ssl_stream *, void* u_para);
struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section, struct event_base * ev_base_gc,
void * logger);
//, ssl_stream_new_cb* new_func, ssl_stream_free_cb* free_func, void* u_para);
void ssl_manager_destroy(struct ssl_mgr * mgr);
unsigned long ssl_stream_log_error(struct bufferevent * bev, enum tfe_conn_dir dir, struct ssl_mgr* mgr);
enum ssl_stream_action enum ssl_stream_action
{ {
@@ -24,7 +16,17 @@ enum ssl_stream_action
SSL_ACTION_SHUTDOWN SSL_ACTION_SHUTDOWN
}; };
typedef enum ssl_stream_action ssl_stream_new_hook(struct ssl_stream *upstream, void* u_para);
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* u_para);
void ssl_manager_destroy(struct ssl_mgr * mgr);
unsigned long ssl_stream_log_error(struct bufferevent * bev, enum tfe_conn_dir dir, struct ssl_mgr* mgr);
enum ssl_stream_action ssl_upstream_create_result_release_action(future_result_t * result); enum ssl_stream_action ssl_upstream_create_result_release_action(future_result_t * result);
evutil_socket_t ssl_upstream_create_result_release_fd(future_result_t * result);
struct ssl_stream * ssl_upstream_create_result_release_stream(future_result_t * result); struct ssl_stream * ssl_upstream_create_result_release_stream(future_result_t * result);
struct bufferevent * ssl_upstream_create_result_release_bev(future_result_t * result); struct bufferevent * ssl_upstream_create_result_release_bev(future_result_t * result);
void ssl_async_upstream_create(struct future * f, struct ssl_mgr * mgr, evutil_socket_t fd_upstream, void ssl_async_upstream_create(struct future * f, struct ssl_mgr * mgr, evutil_socket_t fd_upstream,
@@ -43,6 +45,22 @@ int ssl_manager_add_crl(struct ssl_mgr* mgr, const char* pem_file);
int ssl_manager_del_crl(struct ssl_mgr* mgr, const char* pem_file); int ssl_manager_del_crl(struct ssl_mgr* mgr, const char* pem_file);
void ssl_manager_reset_trust_ca(struct ssl_mgr* mgr); void ssl_manager_reset_trust_ca(struct ssl_mgr* mgr);
//s_stream must be upstream. enum SSL_STREAM_OPT
int ssl_stream_set_opt(struct ssl_stream *s_stream, enum SSL_STREAM_OPT type, const void* value, size_t size); {
SSL_STREAM_OPT_IS_EV_CERT, //0:FALSE, 1:TRUE.
SSL_STREAM_OPT_IS_CT_CERT, //0:FALSE, 1:TRUE.
SSL_STREAM_OPT_IS_MUTUAL_AUTH, //0:FALSE, 1:TRUE.
SSL_STREAM_OPT_PINNING_STATUS, //0:FALSE, 1:TRUE.
SSL_STREAM_OPT_NO_VERIFY_SELF_SIGNED, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:0.
SSL_STREAM_OPT_NO_VERIFY_COMMON_NAME, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:1.
SSL_STREAM_OPT_NO_VERIFY_ISSUER, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:0.
SSL_STREAM_OPT_NO_VERIFY_EXPIRY_DATE, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:0.
SST_STREAM_OPT_VERIFY_FAIL_ACTION, //VALUE is an interger, SIZE=sizeof(int). 1:PASSTHROUGH, 0:BLOCK. DEFAULT:1.
SSL_STREAM_OPT_PROTOCOL_MIN_VERSION,
SSL_STREAM_OPT_PROTOCOL_MAX_VERSION
};
//s_stream must be upstream.
int ssl_stream_set_integer_opt(struct ssl_stream *upstream, enum SSL_STREAM_OPT opt_type, int opt_val);
int ssl_stream_get_integer_opt(struct ssl_stream *upstream, enum SSL_STREAM_OPT opt_type, int *opt_val);

View File

@@ -335,6 +335,8 @@ int tfe_stat_init(struct tfe_proxy * proxy, const char * profile)
proxy->fs_handle = fs_handle; proxy->fs_handle = fs_handle;
return 0; return 0;
} }
extern struct ssl_policy_enforcer* ssl_policy_enforcer_create(void);
extern enum ssl_stream_action ssl_policy_enforce(struct ssl_stream *upstream, void* u_para);
int main(int argc, char * argv[]) int main(int argc, char * argv[])
{ {
@@ -382,8 +384,10 @@ int main(int argc, char * argv[])
g_default_proxy->gcev = event_new(g_default_proxy->evbase, -1, EV_PERSIST, __gc_handler_cb, g_default_proxy); g_default_proxy->gcev = event_new(g_default_proxy->evbase, -1, EV_PERSIST, __gc_handler_cb, g_default_proxy);
CHECK_OR_EXIT(g_default_proxy->gcev, "Failed at creating GC event. Exit. "); CHECK_OR_EXIT(g_default_proxy->gcev, "Failed at creating GC event. Exit. ");
/* SSL INIT */ /* SSL INIT */
g_default_proxy->ssl_mgr_handler = ssl_manager_init(main_profile, "ssl", g_default_proxy->evbase, g_default_logger); g_default_proxy->ssl_mgr_handler = ssl_manager_init(main_profile, "ssl", g_default_proxy->evbase, g_default_logger,
ssl_policy_enforce, ssl_policy_enforcer_create());
CHECK_OR_EXIT(g_default_proxy->ssl_mgr_handler, "Failed at init SSL manager. Exit."); CHECK_OR_EXIT(g_default_proxy->ssl_mgr_handler, "Failed at init SSL manager. Exit.");
for (size_t i = 0; i < (sizeof(signals) / sizeof(int)); i++) for (size_t i = 0; i < (sizeof(signals) / sizeof(int)); i++)

View File

@@ -0,0 +1,30 @@
#include <ssl_stream.h>
#include <tfe_utils.h>
struct ssl_policy_enforcer
{
};
struct ssl_policy_enforcer* ssl_policy_enforcer_create(void)
{
return NULL;
}
enum ssl_stream_action ssl_policy_enforce(struct ssl_stream *upstream, void* u_para)
{
UNUSED struct ssl_policy_enforcer* enforcer=(struct ssl_policy_enforcer*)u_para;
UNUSED int ret=0;
int pinning_staus=0, is_ev=0;
ret=ssl_stream_get_integer_opt(upstream, SSL_STREAM_OPT_PINNING_STATUS, &pinning_staus);
assert(ret==1);
ret=ssl_stream_get_integer_opt(upstream, SSL_STREAM_OPT_IS_EV_CERT, &is_ev);
assert(ret==1);
if(pinning_staus>0||is_ev)
{
return SSL_ACTION_PASSTHROUGH;
}
else
{
return SSL_ACTION_INTERCEPT;
}
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include <ssl_stream.h>
struct ssl_policy_enforcer;
struct ssl_policy_enforcer* ssl_policy_enforcer_create(void);
enum ssl_stream_action ssl_policy_enforce(struct ssl_stream *upstream, void* u_para);

View File

@@ -17,6 +17,7 @@ struct asn1_sess
{ {
unsigned char * buff; unsigned char * buff;
size_t size; size_t size;
int version;
}; };
struct sess_set_args struct sess_set_args
@@ -24,6 +25,11 @@ struct sess_set_args
MESA_htable_handle hash; MESA_htable_handle hash;
struct asn1_sess * new_sess; struct asn1_sess * new_sess;
}; };
struct sess_get_args
{
SSL_SESSION *sess;
int version;
};
struct sess_cache struct sess_cache
{ {
@@ -41,7 +47,7 @@ static void ssl_sess_free_serialized(void * data)
return; return;
} }
static struct asn1_sess * ssl_sess_serialize(SSL_SESSION * sess) static struct asn1_sess * ssl_sess_serialize(SSL_SESSION * sess, int version)
{ {
struct asn1_sess * result = ALLOC(struct asn1_sess, 1); struct asn1_sess * result = ALLOC(struct asn1_sess, 1);
@@ -62,6 +68,7 @@ static struct asn1_sess * ssl_sess_serialize(SSL_SESSION * sess)
j=i2d_SSL_SESSION(sess, &(temp)); j=i2d_SSL_SESSION(sess, &(temp));
assert(i == j); assert(i == j);
assert(result->buff + i == temp); assert(result->buff + i == temp);
result->version=version;
return result; return result;
} }
@@ -101,6 +108,8 @@ static int ssl_sess_verify_cb(void * data, int eliminate_type)
static long sess_cache_get_cb(void * data, const uchar * key, uint size, void * user_arg) static long sess_cache_get_cb(void * data, const uchar * key, uint size, void * user_arg)
{ {
struct sess_get_args *result=(struct sess_get_args *)user_arg;
SSL_SESSION * sess = NULL; SSL_SESSION * sess = NULL;
int is_valid = 0; int is_valid = 0;
if (data == NULL) if (data == NULL)
@@ -119,7 +128,8 @@ static long sess_cache_get_cb(void * data, const uchar * key, uint size, void *
} }
else else
{ {
*(SSL_SESSION **) user_arg = sess; result->sess=sess;
result->version=asn1->version;
return SESS_CACHE_FOUND; return SESS_CACHE_FOUND;
} }
} }
@@ -137,6 +147,7 @@ static long sess_cache_set_cb(void * data, const uchar * key, uint size, void *
cur_asn1->size = new_asn1->size; cur_asn1->size = new_asn1->size;
cur_asn1->buff = ALLOC(unsigned char, cur_asn1->size); cur_asn1->buff = ALLOC(unsigned char, cur_asn1->size);
memcpy(cur_asn1->buff, new_asn1->buff, cur_asn1->size); memcpy(cur_asn1->buff, new_asn1->buff, cur_asn1->size);
cur_asn1->version=new_asn1->version;
return SESS_CACHE_UPDATE_OLD; return SESS_CACHE_UPDATE_OLD;
} }
else else
@@ -178,16 +189,20 @@ static size_t upsess_mk_key(struct sockaddr * res, socklen_t addrlen, const char
} }
void up_session_set(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni, void up_session_set(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni,
SSL_SESSION * sess) int version, SSL_SESSION * sess)
{ {
unsigned char * key = NULL; unsigned char * key = NULL;
size_t key_size = 0; size_t key_size = 0;
long cb_ret = 0; long cb_ret = 0;
assert(cache->served_for == CONN_DIR_UPSTREAM); assert(cache->served_for == CONN_DIR_UPSTREAM);
if(!SSL_SESSION_is_resumable(sess))
{
return;
}
key_size = upsess_mk_key(addr, addr_len, sni, &key); key_size = upsess_mk_key(addr, addr_len, sni, &key);
struct asn1_sess * asn1 = NULL; struct asn1_sess * asn1 = NULL;
asn1 = ssl_sess_serialize(sess); asn1 = ssl_sess_serialize(sess, version);
struct sess_set_args set_args={.hash = cache->hash, .new_sess = asn1}; struct sess_set_args set_args={.hash = cache->hash, .new_sess = asn1};
MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_set_cb, &set_args, &cb_ret); MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_set_cb, &set_args, &cb_ret);
@@ -200,9 +215,9 @@ void up_session_set(struct sess_cache * cache, struct sockaddr * addr, socklen_t
return; return;
} }
SSL_SESSION * up_session_get(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni) SSL_SESSION * up_session_get(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni, int min_ver, int max_ver)
{ {
SSL_SESSION * sess = NULL; struct sess_get_args args={NULL, 0};
long cb_ret = 0; long cb_ret = 0;
size_t key_size = 0; size_t key_size = 0;
@@ -210,14 +225,14 @@ SSL_SESSION * up_session_get(struct sess_cache * cache, struct sockaddr * addr,
unsigned char * key = NULL; unsigned char * key = NULL;
key_size = upsess_mk_key(addr, addr_len, sni, &key); key_size = upsess_mk_key(addr, addr_len, sni, &key);
MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_get_cb, &sess, &cb_ret); MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_get_cb, &args, &cb_ret);
// printf("%s %s\n", __FUNCTION__, key); // printf("%s %s\n", __FUNCTION__, key);
free(key); free(key);
key = NULL; key = NULL;
if (cb_ret == SESS_CACHE_FOUND) if (cb_ret == SESS_CACHE_FOUND && args.version>=min_ver && args.version<=max_ver)
{ {
ATOMIC_INC(&(cache->hit_cnt)); ATOMIC_INC(&(cache->hit_cnt));
return sess; return args.sess;
} }
else else
{ {
@@ -232,7 +247,7 @@ void down_session_set(struct sess_cache * cache, const SSL_SESSION * sess)
struct asn1_sess * asn1 = NULL; struct asn1_sess * asn1 = NULL;
long cb_ret = 0; long cb_ret = 0;
assert(cache->served_for == CONN_DIR_DOWNSTREAM); assert(cache->served_for == CONN_DIR_DOWNSTREAM);
asn1 = ssl_sess_serialize((SSL_SESSION *) sess); asn1 = ssl_sess_serialize((SSL_SESSION *) sess, 0);
/* /*
* SSL_SESSION_get_id() returns a pointer to the internal session id value for the session s. * SSL_SESSION_get_id() returns a pointer to the internal session id value for the session s.

View File

@@ -134,6 +134,8 @@ struct ssl_mgr
struct sess_cache * down_sess_cache; struct sess_cache * down_sess_cache;
struct sess_cache * up_sess_cache; struct sess_cache * up_sess_cache;
struct ssl_service_cache* svc_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; struct session_ticket_key ticket_key;
char default_ciphers[TFE_SYMBOL_MAX]; char default_ciphers[TFE_SYMBOL_MAX];
@@ -165,7 +167,7 @@ struct __ssl_stream_debug
{ {
evutil_socket_t fd; evutil_socket_t fd;
}; };
struct ssl_bypass struct ssl_bypass_condition
{ {
char bypass_ev_cert; char bypass_ev_cert;
char bypass_ct_cert; char bypass_ct_cert;
@@ -177,10 +179,10 @@ struct ssl_upstream_parts
struct cert_verify_param verify_param; struct cert_verify_param verify_param;
struct cert_verify_result verify_result; struct cert_verify_result verify_result;
char verify_failed_action; char block_fake_cert;
struct ssl_service_status svc_status; struct ssl_service_status svc_status;
enum ssl_stream_action action;
struct ssl_bypass bypass_condition;
struct ssl_chello * client_hello; struct ssl_chello * client_hello;
int is_server_cert_verify_passed; int is_server_cert_verify_passed;
}; };
@@ -198,6 +200,7 @@ struct ssl_stream
struct ssl_upstream_parts up_parts; struct ssl_upstream_parts up_parts;
struct ssl_downstream_parts down_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 const unsigned char* alpn_selected; //reference to SSL_ALPN_HTTP_2/SSL_ALPN_HTTP_1_1
struct ssl_stream* peer; struct ssl_stream* peer;
struct __ssl_stream_debug _do_not_use; struct __ssl_stream_debug _do_not_use;
@@ -417,8 +420,8 @@ 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, selected_alpn);
s_stream->down_parts.keyring = kyr; s_stream->down_parts.keyring = kyr;
s_stream->ssl = downstream_ssl_create(mgr, kyr, selected_alpn);
break; break;
case CONN_DIR_UPSTREAM: case CONN_DIR_UPSTREAM:
ATOMIC_INC(&(s_stream->mgr->stat_val[SSL_UP_NEW])); ATOMIC_INC(&(s_stream->mgr->stat_val[SSL_UP_NEW]));
@@ -553,7 +556,7 @@ void ssl_manager_destroy(struct ssl_mgr * mgr)
struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section, struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section,
struct event_base * ev_base_gc, void * logger) 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 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 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->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->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 //Reference to NGINX: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_ticket_key
//Support key rotation in futher. //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) if(ret == 0)
{ {
/* session resuming based on remote endpoint address and port */ /* 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) if (sess)
{ {
SSL_set_session(ssl, sess); /* increments sess refcount */ 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; struct ssl_connect_server_ctx * ctx = (struct ssl_connect_server_ctx *)p;
ssl_connect_server_ctx_free(ctx); 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) 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_hostmatched,
s_stream->up_parts.verify_result.is_ct, s_stream->up_parts.verify_result.is_ct,
s_stream->up_parts.verify_result.is_ev); 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) 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. //The reference count of the SSL_SESSION is not incremented, so no need to free.
ssl_sess = SSL_get0_session(s_stream->ssl); ssl_sess = SSL_get0_session(s_stream->ssl);
up_session_set(mgr->up_sess_cache, (struct sockaddr *)&(ctx->addr), 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 else
@@ -1163,7 +1182,7 @@ static void peek_chello_on_succ(future_result_t * result, void * user)
struct promise * p = (struct promise *) 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 event_base* evbase=tfe_proxy_get_work_thread_evbase(ctx->thread_id);
struct ssl_stream* s_stream=NULL;
struct ssl_chello* chello = ssl_peek_result_release_chello(result);//chello has been saved in ssl_stream. struct ssl_chello* chello = ssl_peek_result_release_chello(result);//chello has been saved in ssl_stream.
if(chello->sni==NULL) if(chello->sni==NULL)
{ {
@@ -1172,8 +1191,8 @@ static void peek_chello_on_succ(future_result_t * result, void * user)
int ret=0; int ret=0;
struct ssl_service_status* svc_status=NULL; struct ssl_service_status* svc_status=NULL;
clock_gettime(CLOCK_MONOTONIC, &(ctx->start)); clock_gettime(CLOCK_MONOTONIC, &(ctx->start));
ctx->s_stream = ssl_stream_new(ctx->mgr, ctx->fd_upstream, CONN_DIR_UPSTREAM, chello, NULL, NULL); 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; svc_status=&s_stream->up_parts.svc_status;
ret=ssl_service_cache_read(ctx->mgr->svc_cache, chello, svc_status); ret=ssl_service_cache_read(ctx->mgr->svc_cache, chello, svc_status);
if(ret==1) if(ret==1)
{ {
@@ -1184,6 +1203,15 @@ static void peek_chello_on_succ(future_result_t * result, void * user)
svc_status->is_ct, svc_status->is_ct,
svc_status->is_ev); svc_status->is_ev);
} }
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->bev = bufferevent_openssl_socket_new(evbase, ctx->fd_upstream,
ctx->s_stream->ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE ); ctx->s_stream->ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE );
@@ -1193,6 +1221,7 @@ static void peek_chello_on_succ(future_result_t * result, void * user)
future_destroy(ctx->f_peek_chello); future_destroy(ctx->f_peek_chello);
ctx->f_peek_chello = NULL; ctx->f_peek_chello = NULL;
}
return; 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 * the refcount decrementing. In other words, return 0 if we did not
* keep a pointer to the object (which we never do here). * 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); 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; * OpenSSL calls SSL_SESSION_free() after calling the callback;
* we do not need to free the reference here. * 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); struct ssl_mgr * mgr = (struct ssl_mgr *) SSL_CTX_get_ex_data(sslctx, SSL_CTX_EX_DATA_IDX_SSLMGR);
assert(mgr != NULL); 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. * Called by OpenSSL when a src SSL session is requested by the client.
OPENSSL_VERSION_NUMBER >= 0x10100000L required. 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); struct ssl_mgr * mgr = (struct ssl_mgr *) SSL_get_ex_data(ssl, SSL_CTX_EX_DATA_IDX_SSLMGR);
SSL_SESSION * sess=NULL; 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_new_cb(sslctx, ossl_downsess_new_cb);
SSL_CTX_sess_set_remove_cb(sslctx, ossl_sessremove_cb); SSL_CTX_sess_set_remove_cb(sslctx, ossl_downsess_remove_cb);
SSL_CTX_sess_set_get_cb(sslctx, ossl_sessget_cb); SSL_CTX_sess_set_get_cb(sslctx, ossl_downsess_get_cb);
if(!mgr->no_sessticket) if(!mgr->no_sessticket)
{ {
SSL_CTX_set_tlsext_ticket_key_cb(sslctx, ossl_session_ticket_key_callback); 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. kyr = key_keeper_release_keyring(result); //kyr will be freed at ssl downstream closing.
clock_gettime(CLOCK_MONOTONIC, &(ctx->start)); 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->origin_ssl?ctx->origin_ssl->alpn_selected:NULL);
ctx->downstream->peer=ctx->origin_ssl; ctx->downstream->peer=ctx->origin_ssl;
ctx->bev_down = bufferevent_openssl_socket_new(evbase, ctx->fd_downstream, ctx->downstream->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); ssl_trusted_cert_storage_reset(mgr->trust_CA_store);
return; 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;
}

View File

@@ -341,6 +341,10 @@ int tfe_stream_action_set_opt(const struct tfe_stream * stream, enum tfe_stream_
return 0; return 0;
} }
int tfe_stream_set_integer_opt(struct tfe_stream * stream, enum tfe_stream_opt_level level, int type, int val)
{
return 1;
}
/* ==================================================================================================================== /* ====================================================================================================================
* CONNECTION STRUCTURE AND OPERATION FUCTIONS * CONNECTION STRUCTURE AND OPERATION FUCTIONS
* ===================================================================================================================*/ * ===================================================================================================================*/
@@ -795,7 +799,15 @@ static tfe_conn_private * __conn_private_create_by_bev(struct tfe_stream_private
__conn_private->bev = bev; __conn_private->bev = bev;
__conn_private->fd = bufferevent_getfd(bev); __conn_private->fd = bufferevent_getfd(bev);
if(stream->tcp_passthough)
{
bufferevent_setcb(__conn_private->bev, __stream_bev_passthrough_readcb,
__stream_bev_passthrough_writecb, __stream_bev_passthrough_eventcb, stream);
}
else
{
bufferevent_setcb(__conn_private->bev, __stream_bev_readcb, __stream_bev_writecb, __stream_bev_eventcb, stream); bufferevent_setcb(__conn_private->bev, __stream_bev_readcb, __stream_bev_writecb, __stream_bev_eventcb, stream);
}
bufferevent_disable(__conn_private->bev, EV_READ | EV_WRITE); bufferevent_disable(__conn_private->bev, EV_READ | EV_WRITE);
struct tfe_proxy * proxy_ref = stream->proxy_ref; struct tfe_proxy * proxy_ref = stream->proxy_ref;
@@ -825,7 +837,7 @@ static tfe_conn_private * __conn_private_create_by_fd(struct tfe_stream_private
goto __errout; goto __errout;
} }
if (stream->passthough) if (stream->tcp_passthough)
{ {
bufferevent_setcb(__conn_private->bev, __stream_bev_passthrough_readcb, bufferevent_setcb(__conn_private->bev, __stream_bev_passthrough_readcb,
__stream_bev_passthrough_writecb, __stream_bev_passthrough_eventcb, stream); __stream_bev_passthrough_writecb, __stream_bev_passthrough_eventcb, stream);
@@ -896,7 +908,21 @@ void ssl_downstream_create_on_fail(enum e_future_error err, const char * what, v
void ssl_upstream_create_on_success(future_result_t * result, void * user) void ssl_upstream_create_on_success(future_result_t * result, void * user)
{ {
struct tfe_stream_private * _stream = (struct tfe_stream_private *) user; struct tfe_stream_private * _stream = (struct tfe_stream_private *) user;
evutil_socket_t fd=-1;
enum ssl_stream_action ssl_action=ssl_upstream_create_result_release_action(result);
if(SSL_ACTION_PASSTHROUGH==ssl_action)
{
_stream->tcp_passthough=1;
fd=ssl_upstream_create_result_release_fd(result);
_stream->conn_upstream=__conn_private_create_by_fd(_stream, fd);
_stream->conn_downstream=__conn_private_create_by_fd(_stream, _stream->defer_fd_downstream);
}
else if(SSL_ACTION_SHUTDOWN==ssl_action)
{
tfe_stream_destory(_stream);
}
else
{
struct ssl_stream * upstream = ssl_upstream_create_result_release_stream(result); struct ssl_stream * upstream = ssl_upstream_create_result_release_stream(result);
struct bufferevent * bev = ssl_upstream_create_result_release_bev(result); struct bufferevent * bev = ssl_upstream_create_result_release_bev(result);
assert(upstream != NULL && bev != NULL); assert(upstream != NULL && bev != NULL);
@@ -919,6 +945,7 @@ void ssl_upstream_create_on_success(future_result_t * result, void * user)
ssl_async_downstream_create(_stream->future_downstream_create, _stream->ssl_mgr, ssl_async_downstream_create(_stream->future_downstream_create, _stream->ssl_mgr,
_stream->ssl_upstream, _stream->defer_fd_downstream, _stream->keyring_id, _stream->thread_ref->thread_id); _stream->ssl_upstream, _stream->defer_fd_downstream, _stream->keyring_id, _stream->thread_ref->thread_id);
} }
}
void ssl_upstream_create_on_fail(enum e_future_error err, const char * what, void * user) void ssl_upstream_create_on_fail(enum e_future_error err, const char * what, void * user)
{ {
@@ -948,7 +975,7 @@ struct tfe_stream * tfe_stream_create(struct tfe_proxy * pxy, struct tfe_thread_
void __stream_access_log_write(struct tfe_stream_private * stream) void __stream_access_log_write(struct tfe_stream_private * stream)
{ {
const char * str_passthrough = stream->passthough ? "PASSTHROUGH" : "-"; const char * str_passthrough = stream->tcp_passthough ? "PASSTHROUGH" : "-";
const char * str_kill = stream->need_to_be_kill ? "KILL" : "-"; const char * str_kill = stream->need_to_be_kill ? "KILL" : "-";
char str_log_event[TFE_STRING_MAX] = ""; char str_log_event[TFE_STRING_MAX] = "";
@@ -1259,7 +1286,7 @@ int tfe_stream_option_set(struct tfe_stream * stream, enum tfe_stream_option opt
else if (opt == TFE_STREAM_OPT_PASSTHROUGH) else if (opt == TFE_STREAM_OPT_PASSTHROUGH)
{ {
assert(sz_arg == sizeof(bool)); assert(sz_arg == sizeof(bool));
_stream->passthough = *(bool *) arg; _stream->tcp_passthough = *(bool *) arg;
} }
else if (opt == TFE_STREAM_OPT_KEYRING_ID) else if (opt == TFE_STREAM_OPT_KEYRING_ID)
{ {