downstream已支持session ticket。

This commit is contained in:
zhengchao
2018-10-05 21:34:57 +08:00
parent d7bf70b4b0
commit 7ac76efac2
3 changed files with 128 additions and 44 deletions

View File

@@ -100,7 +100,7 @@ char* tfe_strdup(const char* s);
#include <stdio.h>
static inline void tfe_hexdump(FILE *f, const char * title, const void * buf, unsigned int len)
static inline void tfe_hexdump2file(FILE *f, const char * title, const void * buf, unsigned int len)
{
unsigned int i, out, ofs;
const unsigned char *data = (const unsigned char *)buf;
@@ -129,3 +129,15 @@ static inline void tfe_hexdump(FILE *f, const char * title, const void * buf, un
#undef LINE_LEN
}
static inline unsigned char* tfe_hexdump(unsigned char *dst, unsigned char *src, size_t len)
{
static unsigned char hex[] = "0123456789abcdef";
while (len--) {
*dst++ = hex[*src >> 4];
*dst++ = hex[*src++ & 0xf];
}
return dst;
}

View File

@@ -32,7 +32,7 @@
#include <ssl_utils.h>
#include <platform.h>
#define SSL_EX_DATA_IDX_SSLMGR 0
int SSL_EX_DATA_IDX_SSLMGR;
#define MAX_NET_RETRIES 50
/*
@@ -66,12 +66,22 @@ enum ssl_stream_stat
SSL_DOWN_CACHE_SZ,
SSL_DOWN_CACHE_QUERY,
SSL_DOWN_CACHE_HIT,
SSL_DOWN_TICKET_NEW,
SSL_DOWN_TICKET_REUSE,
SSL_NO_CHELLO,
SSL_NO_SNI,
SSL_FAKE_CRT,
SSL_STAT_MAX
};
struct session_ticket_key
{
size_t size;
unsigned char name[16];
unsigned char hmac_key[32];
unsigned char aes_key[32];
} ;
struct ssl_mgr
{
unsigned int sslcomp;
@@ -91,6 +101,9 @@ struct ssl_mgr
struct sess_cache * down_sess_cache;
struct sess_cache * up_sess_cache;
struct session_ticket_key ticket_key;
char default_ciphers[TFE_STRING_MAX];
DH * dh;
char * ecdhcurve;
@@ -206,6 +219,8 @@ void ssl_stat_init(struct ssl_mgr * mgr)
spec[SSL_DOWN_CACHE_SZ]="dsess_cache";
spec[SSL_DOWN_CACHE_QUERY]="dcache_query";
spec[SSL_DOWN_CACHE_HIT]="dsess_hitcnt";
spec[SSL_DOWN_TICKET_NEW]="dtkt_new";
spec[SSL_DOWN_TICKET_REUSE]="dtkt_reuse";
spec[SSL_NO_CHELLO]="ssl_no_chlo";
spec[SSL_NO_SNI]="ssl_no_sni";
@@ -396,7 +411,13 @@ ssl_stream_gc_cb(evutil_socket_t fd, short what, void * arg)
struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section,
struct event_base * ev_base_gc, void * logger, screen_stat_handle_t fs)
{
struct timeval gc_delay = {0, 500*1000}; //Microseconds, we set 500 miliseconds here.
struct timeval gc_delay = {0, 500*1000}; //Microseconds, we set 500 miliseconds here.
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
,0xA3,0xAC,0xB6,0xF8,0xCA,0xC7,0xD1,0xDB,0xBE,0xA6,0xC0,0xEF,0xD3,0xD0,0xB9,0x84};
unsigned char hmac_key_def[]={0xD6,0xC8,0xD0,0xF2,0xC8,0xCB,0xBF,0xDA,0xBA,0xCD,0xBF,0xC6,0xBC,0xBC,0xA3,0xAC
,0xC8,0xCB,0xC0,0xE0,0xC9,0xE7,0xBB,0xE1,0xB5,0xC4,0xBB,0xF9,0xCA,0xAF,0x19,0x84};
struct ssl_mgr * mgr = ALLOC(struct ssl_mgr, 1);
int ret = 0;
char version_str[TFE_SYMBOL_MAX];
@@ -421,6 +442,7 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section
}
//tfe2a uses SSLv23_method, it was been deprecated and replaced with the TLS_method() in openssl 1.1.0.
mgr->sslmethod = TLS_method;
SSL_EX_DATA_IDX_SSLMGR = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
MESA_load_profile_uint_def(ini_profile, section, "ssl_compression", &(mgr->sslcomp), 1);
MESA_load_profile_uint_def(ini_profile, section, "no_ssl2", &(mgr->no_ssl2), 1);
MESA_load_profile_uint_def(ini_profile, section, "no_ssl3", &(mgr->no_ssl3), 1);
@@ -437,6 +459,13 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section
mgr->up_sess_cache = ssl_sess_cache_create(mgr->cache_slots, mgr->sess_expire_seconds, CONN_DIR_UPSTREAM);
mgr->down_sess_cache = ssl_sess_cache_create(mgr->cache_slots, mgr->sess_expire_seconds, CONN_DIR_DOWNSTREAM);
//Reference to NGINX: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_ticket_key
//Support key rotation in futher.
memcpy(mgr->ticket_key.name,key_name, sizeof(mgr->ticket_key.name));
memcpy(mgr->ticket_key.aes_key, aes_key_def, sizeof(mgr->ticket_key.aes_key));
memcpy(mgr->ticket_key.hmac_key, hmac_key_def, sizeof(mgr->ticket_key.hmac_key));
mgr->key_keeper = key_keeper_init(ini_profile, "key_keeper", logger);
if (mgr->key_keeper == NULL)
{
@@ -926,6 +955,82 @@ extern void ssl_async_upstream_create(struct future * f, struct ssl_mgr * mgr, e
ssl_async_peek_client_hello(ctx->f_peek_chello, fd_downstream, evbase, mgr->logger);
}
static int ossl_session_ticket_key_callback(SSL *ssl_conn,
unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
HMAC_CTX *hctx, int enc)
{
const EVP_MD *digest=NULL;
const EVP_CIPHER *cipher=NULL;
size_t size=0;
struct ssl_mgr * mgr = (struct ssl_mgr *) SSL_get_ex_data(ssl_conn, SSL_EX_DATA_IDX_SSLMGR);
struct session_ticket_key* key=&(mgr->ticket_key);
assert(mgr!=NULL);
digest = EVP_sha256();
unsigned char buf[32];
if (enc == 1)
{
/* encrypt session ticket */
cipher = EVP_aes_256_cbc();
size = 32;
if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) != 1)
{
TFE_LOG_ERROR(mgr->logger, "Session Ticket RAND_bytes() failed");
return -1;
}
if (EVP_EncryptInit_ex(ectx, cipher, NULL, key[0].aes_key, iv) != 1)
{
TFE_LOG_ERROR(mgr->logger, "EVP_EncryptInit_ex() failed");
return -1;
}
if (HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL) != 1)
{
TFE_LOG_ERROR(mgr->logger, "HMAC_Init_ex() failed");
return -1;
}
memcpy(name, key[0].name, 16);
ATOMIC_INC(&(mgr->stat_val[SSL_DOWN_TICKET_NEW]));
return 1;
}
else
{
/* decrypt session ticket */
if(0!=memcmp(name, key[0].name, 16))
{
TFE_LOG_INFO(mgr->logger, "ssl session ticket decrypt, key: \"%*s\" not found"
,tfe_hexdump(buf, name ,16)-buf, buf);
return 0;
}
cipher = EVP_aes_256_cbc();
size = 32;
if (HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL) != 1)
{
TFE_LOG_ERROR(mgr->logger, "HMAC_Init_ex() failed");
return -1;
}
if (EVP_DecryptInit_ex(ectx, cipher, NULL, key[0].aes_key, iv) != 1)
{
TFE_LOG_ERROR(mgr->logger, "EVP_DecryptInit_ex() failed");
return -1;
}
ATOMIC_INC(&(mgr->stat_val[SSL_DOWN_TICKET_REUSE]));
//Todo: Implement key expire.
return 1; //Return 1 indicates that the ctx and hctx have been set and the session can continue on those parameters.
}
}
/*
* Called by OpenSSL when a new src SSL session is created.
* OpenSSL increments the refcount before calling the callback and will
@@ -1006,69 +1111,34 @@ static void sslctx_set_opts(SSL_CTX * sslctx, struct ssl_mgr * mgr)
SSL_CTX_set_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
#endif /* SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */
#ifdef SSL_OP_NO_TICKET
SSL_CTX_set_options(sslctx, SSL_OP_NO_TICKET);
#endif /* SSL_OP_NO_TICKET */
#ifdef SSL_OP_NO_SSLv2
#ifdef HAVE_SSLV2
if (mgr->no_ssl2) {
#endif /* HAVE_SSLV2 */
SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2);
#ifdef HAVE_SSLV2
if (mgr->no_ssl2)
{
SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2);
}
#endif /* HAVE_SSLV2 */
#endif /* !SSL_OP_NO_SSLv2 */
#ifdef HAVE_SSLV3
if (mgr->no_ssl3) {
if (mgr->no_ssl3)
{
SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv3);
}
#endif /* HAVE_SSLV3 */
#ifdef HAVE_TLSV10
if (mgr->no_tls10)
{
SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1);
}
#endif /* HAVE_TLSV10 */
#ifdef HAVE_TLSV11
if (mgr->no_tls11)
{
SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_1);
}
#endif /* HAVE_TLSV11 */
#ifdef HAVE_TLSV12
if (mgr->no_tls12)
{
SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_2);
}
#endif /* HAVE_TLSV12 */
#ifdef SSL_OP_NO_COMPRESSION
if (!mgr->sslcomp)
{
SSL_CTX_set_options(sslctx, SSL_OP_NO_COMPRESSION);
}
#endif /* SSL_OP_NO_COMPRESSION */
}
@@ -1100,6 +1170,8 @@ static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt)
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);
ret=SSL_CTX_set_tlsext_ticket_key_cb(sslctx, ossl_session_ticket_key_callback);
assert(ret!=0);
SSL_CTX_set_session_cache_mode(sslctx, SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL);
SSL_CTX_set_session_id_context(sslctx, (const unsigned char *) mgr->ssl_session_context,
sizeof(mgr->ssl_session_context));

View File

@@ -59,7 +59,7 @@ enum tfe_stream_action __http_connection_entry_on_request(const struct tfe_strea
struct http_half_private * hf_private_req_in = to_hf_request_private(hs_private);
struct http_half_private * hf_private_req_user;
/* tfe_hexdump(stderr, __FUNCTION__, data, (unsigned int)len); */
/* tfe_hexdump2file(stderr, __FUNCTION__, data, (unsigned int)len); */
int ret = 0;
size_t __action_byptes;