增加解析tls message信息

This commit is contained in:
崔一鸣
2019-12-16 21:53:05 +08:00
parent 60e35d75a1
commit 5508ddeca0
10 changed files with 3943 additions and 3343 deletions

View File

@@ -1,4 +1,4 @@
add_library(stmstat SHARED src/sslstat_entry.cpp src/ssl_utils.cpp)
add_library(stmstat SHARED src/stmstat_entry.cpp src/ssl_utils.cpp)
target_include_directories(stmstat PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(stmstat MESA_prof_load MESA_field_stat cjson)

View File

@@ -44,6 +44,42 @@ int g_stream_fail_count = 0;
int g_log_succ_count = 0;
int g_exceed_max_pkts_count = 0;
struct tls_message_type{
int message_type;
int content_type;
int handshake_type;
const char *name;
};
struct tls_message_type g_tls_types[] = {
{0, 22, 0, "hello_request_RESERVED"},
{1, 22, 1, "client_hello"},
{2, 22, 2, "server_hello"},
{3, 22, 3, "hello_verify_request_RESERVED"},
{4, 22, 4, "new_session_ticket"},
{5, 22, 5, "end_of_early_data"},
{6, 22, 6, "hello_retry_request_RESERVED"},
{7, 22, 8, "encrypted_extensions"},
{8, 22, 11, "certificate"},
{9, 22, 12, "server_key_exchange_RESERVED"},
{10, 22, 13, "certificate_request"},
{11, 22, 14, "server_hello_done_RESERVED"},
{12, 22, 15, "certificate_verify"},
{13, 22, 16, "client_key_exchange_RESERVED"},
{14, 22, 20, "finished"},
{15, 22, 21, "certificate_url_RESERVED"},
{16, 22, 22, "certificate_status_RESERVED"},
{17, 22, 23, "supplemental_data_RESERVED"},
{18, 22, 24, "key_update"},
{19, 22, 25, "compressed_certificate"},
{20, 22, 254, "message_hash"},
{21, 20, 0, "change_cipher_spec"},
{22, 21, 0, "alert"},
{23, 23, 0, "application_data"},
{24, 24, 0, "heartbeat"},
{25, 25, 0, "tls12_cid"},
};
struct pkt_stat_info{
struct timeval pkt_time;
int bytes;
@@ -65,6 +101,12 @@ struct pkt_parsed_info{
uint16_t data_len;
};
struct tls_message_info{
int dir;
int type;
int length;
};
struct pme_info{
int _errno;
char sip[INET_ADDRSTRLEN];
@@ -83,6 +125,8 @@ struct pme_info{
int last_s2c_pkt_index;
struct pkt_stat_info pkt_info_list[STREAM_PACKET_COUNT_MAX];
struct ssl_chello chello;
int tls_message_count;
struct tls_message_info tls_info_list[STREAM_PACKET_COUNT_MAX];
};
int ipv4_header_parse(const void *a_packet, struct pkt_parsed_info* pktinfo){
@@ -108,7 +152,7 @@ int ipv4_header_parse(const void *a_packet, struct pkt_parsed_info* pktinfo){
int packet_stat(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_parsed_info* pktinfo){
if(pmeinfo->total_pkts == STREAM_PACKET_COUNT_MAX){
printf("packet nums > STREAM_PACKET_COUNT_MAX\n");
LOG_INFO(g_logger, "packet nums > STREAM_PACKET_COUNT_MAX(%d)\n", STREAM_PACKET_COUNT_MAX);
g_exceed_max_pkts_count++;
return -1;
}
@@ -143,12 +187,59 @@ int chello_packet_parse(struct pme_info *pmeinfo, struct pkt_parsed_info *pktinf
int len = pktinfo->data_len;
ssl_chello_parse(&(pmeinfo->chello), (const unsigned char*)buff, len, &chello_status);
if(chello_status != CHELLO_PARSE_SUCCESS){
printf("Error: chello parse failed\n");
LOG_ERROR(g_logger, "Error: chello parse failed\n");
return -1;
}
return 0;
}
int get_tls_message_type(int content_type, int handshake_type){
int type_count = sizeof(g_tls_types) / sizeof(struct tls_message_type);
for(int i = 0; i < type_count; i++){
if(g_tls_types[i].content_type == content_type && g_tls_types[i].handshake_type == handshake_type){
return i;
}
}
return -1;
}
int tls_header_parse(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_parsed_info *pktinfo){
unsigned char *buff = (unsigned char*)pktinfo->data;
int len = pktinfo->data_len;
int i = 0;
while(i < len){
if(i + 4 >= len){
return -1;
}
int content_type = buff[i];
int handshake_type = 0;
if(buff[i] == 0x16){
if(i + 5 >= len){
return -1;
}
handshake_type = buff[i + 5];
}
int message_type = get_tls_message_type(content_type, handshake_type);
if(message_type < 0){
return -1;
}
int version = (uint16_t)(buff[i + 1] << 8) + (uint8_t)buff[i + 2];
if(version < 0x0300 || version > 0x0304){
return -1;
}
int len = (uint16_t)(buff[i + 3] << 8) + (uint8_t)buff[i + 4];
if(len < 0){
printf("%02hhx %02hhx\n", buff[i + 3], buff[i + 4]);
}
pmeinfo->tls_info_list[pmeinfo->tls_message_count].dir = stream->curdir;
pmeinfo->tls_info_list[pmeinfo->tls_message_count].type = message_type;
pmeinfo->tls_info_list[pmeinfo->tls_message_count].length = len;
pmeinfo->tls_message_count++;
i += (5 + len);
}
return 0;
}
int packet_need_filter(struct pkt_parsed_info *pktinfo){
struct iphdr *_iphdr = pktinfo->iphdr.v4;
int ttl = _iphdr->ttl;
@@ -168,6 +259,7 @@ char pending_opstate(struct streaminfo *stream, struct pme_info *pmeinfo, struct
pmeinfo->last_c2s_pkt_index = -1;
pmeinfo->last_s2c_pkt_index = -1;
get_rawpkt_opt_from_streaminfo(stream, RAW_PKT_GET_TIMESTAMP, &(pmeinfo->start_time));
get_rawpkt_opt_from_streaminfo(stream, RAW_PKT_GET_TIMESTAMP, &(pmeinfo->end_time));
struct stream_tuple4_v4 *tuple4 = stream->addr.tuple4_v4;
inet_ntop(AF_INET, &(tuple4->saddr), pmeinfo->sip, INET_ADDRSTRLEN);
inet_ntop(AF_INET, &(tuple4->daddr), pmeinfo->dip, INET_ADDRSTRLEN);
@@ -181,12 +273,15 @@ char pending_opstate(struct streaminfo *stream, struct pme_info *pmeinfo, struct
pmeinfo->_errno = -1;
return APP_STATE_FAWPKT | APP_STATE_DROPME;
}
tls_header_parse(stream, pmeinfo, pktinfo);
packet_stat(stream, pmeinfo, pktinfo);
return APP_STATE_FAWPKT | APP_STATE_GIVEME;
}
char data_opstate(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_parsed_info *pktinfo){
get_rawpkt_opt_from_streaminfo(stream, RAW_PKT_GET_TIMESTAMP, &(pmeinfo->end_time));
if(packet_need_filter(pktinfo) == 0){
tls_header_parse(stream, pmeinfo, pktinfo);
int ret = packet_stat(stream, pmeinfo, pktinfo);
if(ret == -1){
return APP_STATE_FAWPKT | APP_STATE_DROPME;
@@ -195,6 +290,18 @@ char data_opstate(struct streaminfo *stream, struct pme_info *pmeinfo, struct pk
return APP_STATE_FAWPKT | APP_STATE_GIVEME;
}
void time_tostring(struct timeval tv, char *buf, int buflen){
char tmbuf[64];
time_t nowtime;
struct tm *nowtm;
nowtime = tv.tv_sec;
//printf("nowtime = %lld\n", nowtime);
nowtm = localtime(&nowtime);
strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm);
snprintf(buf, buflen, "%s.%06ld", tmbuf, tv.tv_usec);
return;
}
void output_result(struct pme_info *pmeinfo){
cJSON *log_obj = cJSON_CreateObject();
cJSON_AddStringToObject(log_obj, "sip", pmeinfo->sip);
@@ -207,6 +314,12 @@ void output_result(struct pme_info *pmeinfo){
cJSON_AddNumberToObject(log_obj, "c2s_pkts", pmeinfo->c2s_pkts);
cJSON_AddNumberToObject(log_obj, "s2c_pkts", pmeinfo->s2c_pkts);
cJSON_AddNumberToObject(log_obj, "total_pkts", pmeinfo->total_pkts);
char time_str[64] = {};
time_tostring(pmeinfo->start_time, time_str, sizeof(time_str));
cJSON_AddStringToObject(log_obj, "start_time", time_str);
time_tostring(pmeinfo->end_time, time_str, sizeof(time_str));
cJSON_AddStringToObject(log_obj, "end_time", time_str);
pmeinfo->duration = (pmeinfo->end_time.tv_sec - pmeinfo->start_time.tv_sec) * 1000 + (pmeinfo->end_time.tv_usec - pmeinfo->start_time.tv_usec) / 1000;
cJSON_AddNumberToObject(log_obj, "duration", pmeinfo->duration);
cJSON *pkt_info_list = cJSON_CreateArray();
for(int i = 0; i < pmeinfo->total_pkts; i++){
@@ -214,6 +327,8 @@ void output_result(struct pme_info *pmeinfo){
cJSON_AddNumberToObject(pkt_info, "bytes", pmeinfo->pkt_info_list[i].bytes);
cJSON_AddNumberToObject(pkt_info, "dir", pmeinfo->pkt_info_list[i].dir);
cJSON_AddNumberToObject(pkt_info, "interval", pmeinfo->pkt_info_list[i].interval);
time_tostring(pmeinfo->pkt_info_list[i].pkt_time, time_str, sizeof(time_str));
cJSON_AddStringToObject(pkt_info, "pkt_time", time_str);
cJSON_AddItemToArray(pkt_info_list, pkt_info);
}
cJSON_AddItemToObject(log_obj, "packets", pkt_info_list);
@@ -234,6 +349,17 @@ void output_result(struct pme_info *pmeinfo){
}
cJSON_AddItemToObject(tls_info, "extensions_list", extensions_list);
cJSON_AddItemToObject(log_obj, "tls", tls_info);
cJSON *tls_message_list = cJSON_CreateArray();
cJSON_AddItemToObject(tls_info, "tls_message_list", tls_message_list);
for(int i = 0; i < pmeinfo->tls_message_count; i++){
cJSON *tls_message = cJSON_CreateObject();
cJSON_AddNumberToObject(tls_message, "dir", pmeinfo->tls_info_list[i].dir);
cJSON_AddNumberToObject(tls_message, "type", pmeinfo->tls_info_list[i].type);
cJSON_AddNumberToObject(tls_message, "length", pmeinfo->tls_info_list[i].length);
cJSON_AddItemToArray(tls_message_list, tls_message);
}
char *log_msg = cJSON_PrintUnformatted(log_obj);
//printf("%s\n\n", log_msg);
LOG_INFO(g_logger, log_msg);
@@ -246,12 +372,12 @@ void output_result(struct pme_info *pmeinfo){
char close_opstate(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_parsed_info *pktinfo, const void *a_packet){
if(a_packet != NULL){
get_rawpkt_opt_from_streaminfo(stream, RAW_PKT_GET_TIMESTAMP, &(pmeinfo->end_time));
if(packet_need_filter(pktinfo) == 0){
tls_header_parse(stream, pmeinfo, pktinfo);
packet_stat(stream, pmeinfo, pktinfo);
}
}
get_rawpkt_opt_from_streaminfo(stream, RAW_PKT_GET_TIMESTAMP, &(pmeinfo->end_time));
pmeinfo->duration = (pmeinfo->end_time.tv_sec - pmeinfo->start_time.tv_sec) * 1000 + (pmeinfo->end_time.tv_usec - pmeinfo->start_time.tv_usec) / 1000;
return APP_STATE_FAWPKT | APP_STATE_DROPME;
}
@@ -262,8 +388,8 @@ void pme_info_destroy(struct pme_info *pmeinfo){
extern "C" char stmstat_entry(struct streaminfo *stream, void** pme, int thread_seq, const void* a_packet){
if(g_count % 10 == 5){
printf("handle %d packets\n", g_count);
printf("stream_count: %d\nsucc_count: %d\nfail_count: %d\ng_log_succ_count: %d, g_exceed_max_pkts_count: %d\n",
LOG_DEBUG(g_logger, "handle %d packets\n", g_count);
LOG_DEBUG(g_logger, "stream_count: %d\nsucc_count: %d\nfail_count: %d\ng_log_succ_count: %d, g_exceed_max_pkts_count: %d\n",
g_stream_count, g_stream_succ_count, g_stream_fail_count, g_log_succ_count, g_exceed_max_pkts_count);
}
g_count++;