TSG-2967 TFE 使用 JA3 优化 SSL pinning

This commit is contained in:
luwenpeng
2020-08-24 17:52:55 +08:00
parent 1e5b2ceaed
commit 9d15d655ed
8 changed files with 717 additions and 56 deletions

View File

@@ -43,9 +43,11 @@
#include <ssl_utils.h>
#include <ssl_service_cache.h>
#include <platform.h>
#include <ssl_ja3.h>
static int SSL_CTX_EX_DATA_IDX_SSLMGR;
static int SSL_EX_DATA_IDX_SSLSTREAM;
static unsigned int ssl_ja3_debug;
#define MAX_NET_RETRIES 50
#define LATENCY_WARNING_THRESHOLD_MS 1000
@@ -64,7 +66,7 @@ static unsigned char SSL_ALPN_HTTP_2[]={2, 'h','2',0};
*/
#define DFLT_CURVE "prime256v1"
extern long long certstore_is_unavailable;
extern long long certstore_is_unavailable;
enum ssl_stream_stat
{
@@ -636,7 +638,8 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section
goto error_out;
}
MESA_load_profile_string_def(ini_profile, section, "ssl_min_version", version_str, sizeof(version_str), "ssl3");
MESA_load_profile_uint_def(ini_profile, section, "ssl_ja3_debug", &(ssl_ja3_debug), 0);
MESA_load_profile_string_def(ini_profile, section, "ssl_min_version", version_str, sizeof(version_str), "ssl3");
mgr->ssl_min_version = sslver_str2num(version_str);
if (mgr->ssl_min_version < 0)
@@ -818,7 +821,16 @@ static void peek_client_hello_cb(evutil_socket_t fd, short what, void * arg)
{
case CHELLO_PARSE_SUCCESS:
{
promise_dettach_ctx(promise);
if (ssl_ja3_debug)
{
char *addr = tfe_string_addr_create_by_fd(fd, CONN_DIR_DOWNSTREAM);
struct ssl_ja3 *fingerprint = ssl_ja3_generate_fingerprint(buf, n);
TFE_LOG_INFO(ctx->logger, "ja3:%s, hash:%s addr:%s\n", fingerprint ? fingerprint->ja3 : "null", fingerprint ? fingerprint->ja3_hash : "null", addr);
ssl_ja3_free(fingerprint);
free(addr);
}
promise_dettach_ctx(promise);
ctx->chello=chello;
promise_success(promise, ctx);
peek_client_hello_ctx_free(ctx);
@@ -890,7 +902,7 @@ int ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
struct ssl_stream* s_upstream=NULL;
s_upstream=(struct ssl_stream*)SSL_get_ex_data(ssl, SSL_EX_DATA_IDX_SSLSTREAM);
s_upstream->up_parts.svc_status.is_mutual_auth=1;
ssl_service_cache_write(s_upstream->mgr->svc_cache, s_upstream->up_parts.client_hello, s_upstream->tcp_stream->addr, &s_upstream->up_parts.svc_status);
ssl_service_cache_write(s_upstream->mgr->svc_cache, s_upstream->up_parts.client_hello, s_upstream->tcp_stream, &s_upstream->up_parts.svc_status);
return 0;
}
@@ -1206,18 +1218,18 @@ void ssl_stream_process_error(struct ssl_stream * s_stream, unsigned long sslerr
{
s_upstream->svc_status.cli_pinning_status=PINNING_ST_PINNING;
ssl_stream_set_cmsg_integer(s_stream, TFE_CMSG_SSL_PINNING_STATE, PINNING_ST_PINNING);
ssl_service_cache_write(mgr->svc_cache, s_upstream->client_hello, s_stream->tcp_stream->addr, &s_upstream->svc_status);
ssl_service_cache_write(mgr->svc_cache, s_upstream->client_hello, s_stream->tcp_stream, &s_upstream->svc_status);
}
else if(sslerr>0 && sslerr!=SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN)
{
s_upstream->svc_status.has_protocol_errors=1;
ssl_service_cache_write(mgr->svc_cache, s_upstream->client_hello, s_stream->tcp_stream->addr, &s_upstream->svc_status);
ssl_service_cache_write(mgr->svc_cache, s_upstream->client_hello, s_stream->tcp_stream, &s_upstream->svc_status);
}
break;
case CONN_DIR_UPSTREAM:
s_upstream=&(s_stream->up_parts);
s_upstream->svc_status.has_protocol_errors=1;
ssl_service_cache_write(mgr->svc_cache, s_stream->up_parts.client_hello, s_stream->tcp_stream->addr, &(s_stream->up_parts.svc_status));
ssl_service_cache_write(mgr->svc_cache, s_stream->up_parts.client_hello, s_stream->tcp_stream, &(s_stream->up_parts.svc_status));
break;
default:
assert(0);
@@ -1238,7 +1250,7 @@ void ssl_stream_process_zero_eof(struct ssl_stream * s_stream, struct ssl_mgr* m
{
s_upstream->svc_status.cli_pinning_status=PINNING_ST_MAYBE_PINNING;
ssl_stream_set_cmsg_integer(s_stream, TFE_CMSG_SSL_PINNING_STATE, PINNING_ST_MAYBE_PINNING);
ssl_service_cache_write(mgr->svc_cache, s_stream->peer->up_parts.client_hello, s_stream->tcp_stream->addr, &(s_stream->peer->up_parts.svc_status));
ssl_service_cache_write(mgr->svc_cache, s_stream->peer->up_parts.client_hello, s_stream->tcp_stream, &(s_stream->peer->up_parts.svc_status));
}
s_stream->error=SSL_STREAM_R_CLIENT_CLOSED;
return;
@@ -1311,7 +1323,7 @@ static void ssl_server_connected_eventcb(struct bufferevent * bev, short events,
error_str, sizeof(error_str), &(s_stream->up_parts.verify_result));
s_upstream->svc_status.is_ct=s_upstream->verify_result.is_ct;
s_upstream->svc_status.is_ev=s_upstream->verify_result.is_ev;
ssl_service_cache_write(mgr->svc_cache, s_upstream->client_hello, s_stream->tcp_stream->addr, &(s_upstream->svc_status));
ssl_service_cache_write(mgr->svc_cache, s_upstream->client_hello, s_stream->tcp_stream, &(s_upstream->svc_status));
TFE_LOG_DEBUG(mgr->logger, "stream:%s sni:%s hostmatch:%d, ct:%d, ev:%d",
s_stream->tcp_stream->str_stream_info,
s_upstream->client_hello->sni,
@@ -1401,18 +1413,19 @@ static void peek_chello_on_succ(future_result_t * result, void * user)
clock_gettime(CLOCK_MONOTONIC, &(ctx->start));
s_stream= ssl_stream_new(ctx->mgr, ctx->fd_upstream, CONN_DIR_UPSTREAM, chello, NULL, NULL, ctx->tcp_stream);
svc_status=&s_stream->up_parts.svc_status;
ret=ssl_service_cache_read(ctx->mgr->svc_cache, chello, s_stream->tcp_stream->addr, svc_status);
ret=ssl_service_cache_read(ctx->mgr->svc_cache, chello, s_stream->tcp_stream, svc_status);
if(ret==1)
{
addr_string=tfe_stream_addr_to_str(s_stream->tcp_stream->addr);
TFE_LOG_DEBUG(ctx->mgr->logger, "%s %s service status pinning:%d, mauth:%d, err:%d, ct:%d, ev:%d",
TFE_LOG_DEBUG(ctx->mgr->logger, "%s %s service status pinning:%d, mauth:%d, err:%d, ct:%d, ev:%d, app_not_pinning:%d",
addr_string,
chello->sni,
svc_status->cli_pinning_status,
svc_status->is_mutual_auth,
svc_status->has_protocol_errors,
svc_status->is_ct,
svc_status->is_ev);
svc_status->is_ev,
svc_status->is_app_not_pinning);
free(addr_string);
addr_string=NULL;
}
@@ -1914,7 +1927,7 @@ static void ssl_client_connected_eventcb(struct bufferevent * bev, short events,
// struct ssl_service_status svc_status;
// memset(&svc_status, 0, sizeof(svc_status));
// svc_status.is_app_not_pinning=1;
// ssl_service_cache_write(mgr->svc_cache, s_upstream->client_hello, s_stream->tcp_stream->addr, &svc_status);
// ssl_service_cache_write(mgr->svc_cache, s_upstream->client_hello, s_stream->tcp_stream, &svc_status);
promise_success(p, ctx);
}
@@ -2022,7 +2035,7 @@ void ssl_stream_free(struct ssl_stream * s_stream, struct event_base * evbase, s
struct ssl_service_status svc_status;
memset(&svc_status, 0, sizeof(svc_status));
svc_status.is_app_not_pinning = 1;
ssl_service_cache_write(s_stream->mgr->svc_cache, s_stream->up_parts.client_hello, s_stream->tcp_stream->addr, &svc_status);
ssl_service_cache_write(s_stream->mgr->svc_cache, s_stream->up_parts.client_hello, s_stream->tcp_stream, &svc_status);
}
const char * sni = (s_stream->up_parts.client_hello && s_stream->up_parts.client_hello->sni) ? s_stream->up_parts.client_hello->sni : "null";
TFE_LOG_DEBUG(g_default_logger, "ssl up stream close, rx_offset:%d, sni:%s", rx_offset_this_time, sni);