diff --git a/conf/kni/kni.conf b/conf/kni/kni.conf index 802b659..2b685d4 100644 --- a/conf/kni/kni.conf +++ b/conf/kni/kni.conf @@ -8,6 +8,9 @@ tun_name = tun_kni src_mac_addr = 00:0e:c6:d6:72:c1 dst_mac_addr = fe:65:b7:03:50:bd + +reassembled_packets_num = 2 + [tfe0] enabled = 1 dev_eth_symbol = ens1f5 diff --git a/entry/include/kni_entry.h b/entry/include/kni_entry.h index 45e37e3..df656c5 100644 --- a/entry/include/kni_entry.h +++ b/entry/include/kni_entry.h @@ -7,6 +7,8 @@ #include #include "tfe_mgr.h" #include +#include "tsg/ssl.h" +#include "MESA/stream_inc/stream_rawpkt.h" #define BURST_MAX 1 #define CALLER_SAPP 0 @@ -151,6 +153,7 @@ struct pme_info{ struct proxy_tcp_option pxy_tcp_option; int pxy_tcp_option_is_scan; struct session_attribute_label *session_attribute; + int check_data_packets_num; }; struct wrapped_packet{ @@ -232,6 +235,7 @@ struct kni_handle{ struct proxy_tcp_option pxy_tcp_option; int session_attribute_id; int log_level; + int reassembled_packets_num; }; struct traceid2pme_search_cb_args{ diff --git a/entry/src/kni_entry.cpp b/entry/src/kni_entry.cpp index ee1bc7b..32c08b4 100644 --- a/entry/src/kni_entry.cpp +++ b/entry/src/kni_entry.cpp @@ -58,6 +58,10 @@ static __attribute__((__used__)) const char * GIT_VERSION_UNKNOWN = NULL; } #endif +#define INTERCEPT_RET_CODE_OK (APP_STATE_DROPPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME) +#define INTERCEPT_RET_CODE_FAIL (APP_STATE_FAWPKT | APP_STATE_KILL_FOLLOW | APP_STATE_DROPME) +#define INTERCEPT_RET_CODE_BYPASS (APP_STATE_FAWPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME) +#define INTERCEPT_RET_CODE_NEED_NEXT (APP_STATE_DROPPKT | APP_STATE_GIVEME) struct kni_handle *g_kni_handle = NULL; struct kni_field_stat_handle *g_kni_fs_handle = NULL; @@ -655,13 +659,10 @@ error_out: return NULL; } -static char* add_cmsg_to_packet(struct pme_info *pmeinfo, struct streaminfo *stream, struct pkt_info *pktinfo, int *len){ - //tcp option: kind 88, len 4, control_info_len - void * logger = g_kni_handle->local_logger; - char *new_pkt = (char*)ALLOC(struct wrapped_packet, 1); +static int rebuild_packet_to_add_tcp_option(struct pme_info *pmeinfo, struct pkt_info *pktinfo, char *new_pkt){ + //char *new_pkt = (char*)ALLOC(struct wrapped_packet, 1); int offset = 0; //iphdr - KNI_LOG_DEBUG(logger, "Kni add cmsg to packet malloc buffer size:%d",sizeof(struct wrapped_packet)); if(pmeinfo->addr_type == ADDR_TYPE_IPV6){ memcpy(new_pkt, (void*)pktinfo->iphdr.v6, pktinfo->iphdr_len); } @@ -686,18 +687,10 @@ static char* add_cmsg_to_packet(struct pme_info *pmeinfo, struct streaminfo *str //data memcpy(new_pkt + offset, (void*)pktinfo->data, pktinfo->data_len); offset += pktinfo->data_len; - //kni_cmsg_serialize_header - uint16_t header_len = 0; - unsigned char* header = kni_cmsg_serialize_header_new(pmeinfo, stream, pktinfo, &header_len); - if(header == NULL){ - KNI_LOG_ERROR(logger, "Kni add cmsg to packet: serialize_header failed"); - goto error_out; - } - memcpy(new_pkt + offset, (void*)header, header_len); - offset += header_len; - KNI_LOG_DEBUG(logger, "Kni add cmsg to packet:offset=%d,header_len=%d, tcp_data_len=%d",offset,header_len,pktinfo->data_len); - FREE(&header); - //ipv6 + return offset; +} + +static void set_new_packet_checksum(struct pme_info *pmeinfo, struct pkt_info *pktinfo, char *new_pkt, int offset){ if(pmeinfo->addr_type == ADDR_TYPE_IPV6){ kni_ipv6_header_parse((void*)new_pkt, pktinfo); pktinfo->iphdr.v6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(offset - sizeof(ip6_hdr)); @@ -712,9 +705,33 @@ static char* add_cmsg_to_packet(struct pme_info *pmeinfo, struct streaminfo *str iphdr->check = 0; iphdr->check = kni_ip_checksum((void*)iphdr, pktinfo->iphdr_len); //tcphdr: checkdum + struct tcphdr *tcphdr = (struct tcphdr*)(new_pkt + pktinfo->iphdr_len); tcphdr->check = 0; tcphdr->check = kni_tcp_checksum((void*)tcphdr, offset - pktinfo->iphdr_len, iphdr->saddr, iphdr->daddr); } +} + +static char* add_cmsg_to_packet(struct pme_info *pmeinfo, struct streaminfo *stream, struct pkt_info *pktinfo, int *len){ + //tcp option: kind 88, len 4, control_info_len + void * logger = g_kni_handle->local_logger; + char *new_pkt = (char*)ALLOC(struct wrapped_packet, 1); + int offset = 0; + //iphdr + KNI_LOG_DEBUG(logger, "Kni add cmsg to packet malloc buffer size:%d",sizeof(struct wrapped_packet)); + offset = rebuild_packet_to_add_tcp_option(pmeinfo, pktinfo, new_pkt); + + uint16_t header_len = 0; + unsigned char* header = kni_cmsg_serialize_header_new(pmeinfo, stream, pktinfo, &header_len); + if(header == NULL){ + KNI_LOG_ERROR(logger, "Kni add cmsg to packet: serialize_header failed"); + goto error_out; + } + memcpy(new_pkt + offset, (void*)header, header_len); + offset += header_len; + KNI_LOG_DEBUG(logger, "Kni add cmsg to packet:offset=%d,header_len=%d, tcp_data_len=%d",offset,header_len,pktinfo->data_len); + FREE(&header); + //ipv6 + set_new_packet_checksum(pmeinfo, pktinfo, new_pkt, offset); *len = offset; return new_pkt; @@ -1200,19 +1217,16 @@ static void set_timestamp_depend_first_data(struct streaminfo *stream, struct pm } } -static int first_data_intercept(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_info *pktinfo, int thread_seq){ +static int is_stream_can_intercept(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_info *pktinfo, int thread_seq){ FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCP_READY_STM], 0, FS_OP_ADD, 1); - //FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCP_READY_BYTE], 0, FS_OP_ADD, pktinfo->ip_totlen); void *logger = g_kni_handle->local_logger; - char *buff = NULL; - int ret, len; + int ret; //intercept_error: TCP CTEAT LINK NOT BYSYN or TCP_CREATE_LINK_MODE error unsigned char intercept_stream_link_mode; int intercept_stream_link_mode_len = sizeof(unsigned char); unsigned short stream_tunnel_type = STREAM_TUNNLE_NON; int stream_tunnel_type_len = sizeof(unsigned short); - int has_dup_traffic; - int have_dup_pkt_len = sizeof(has_dup_traffic); + ret=MESA_get_stream_opt(stream, MSO_TCP_CREATE_LINK_MODE, (void *)&intercept_stream_link_mode, &intercept_stream_link_mode_len); if(ret == 0){ if(intercept_stream_link_mode != TCP_CTEAT_LINK_BYSYN){ @@ -1228,7 +1242,6 @@ static int first_data_intercept(struct streaminfo *stream, struct pme_info *pmei FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCPERR_GET_LINK_MODE_ERR], 0, FS_OP_ADD, 1); goto error_out; } - ret=MESA_get_stream_opt(stream, MSO_STREAM_TUNNEL_TYPE, (void *)&stream_tunnel_type, &stream_tunnel_type_len); if(ret == 0){ if(stream_tunnel_type != STREAM_TUNNLE_NON){ @@ -1295,6 +1308,19 @@ static int first_data_intercept(struct streaminfo *stream, struct pme_info *pmei FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCPERR_NO_TFE], 0, FS_OP_ADD, 1); goto error_out; } + return INTERCEPT_RET_CODE_OK; +error_out: + return INTERCEPT_RET_CODE_FAIL; +} + +static int first_data_intercept(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_info *pktinfo, int thread_seq){ + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCP_READY_STM], 0, FS_OP_ADD, 1); + //FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCP_READY_BYTE], 0, FS_OP_ADD, pktinfo->ip_totlen); + void *logger = g_kni_handle->local_logger; + char *buff = NULL; + int ret, len; + int has_dup_traffic; + int have_dup_pkt_len = sizeof(has_dup_traffic); //dup_traffic_check if(g_kni_handle->dup_traffic_switch == 1){ @@ -1339,7 +1365,7 @@ static int first_data_intercept(struct streaminfo *stream, struct pme_info *pmei { KNI_LOG_DEBUG(g_kni_handle->local_logger, "Proxy-tcp-option: bypass Duplicated Packet first data, streamid = %d", pmeinfo->stream_traceid); FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCPERR_DUP_TRAFFIC], 0, FS_OP_ADD, 1); - return APP_STATE_FAWPKT | APP_STATE_KILL_FOLLOW | APP_STATE_DROPME; + goto error_out; } } @@ -1380,7 +1406,8 @@ static int first_data_intercept(struct streaminfo *stream, struct pme_info *pmei } } } - return APP_STATE_FAWPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; + return INTERCEPT_RET_CODE_BYPASS; + //return APP_STATE_FAWPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; } } @@ -1446,13 +1473,15 @@ static int first_data_intercept(struct streaminfo *stream, struct pme_info *pmei KNI_LOG_DEBUG(logger, "stream has dup traffic, traceid = %s", pmeinfo->stream_traceid); } FREE(&buff); - return APP_STATE_DROPPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; + return INTERCEPT_RET_CODE_OK; + //return APP_STATE_DROPPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; error_out: if(buff != NULL){ FREE(&buff); } - return APP_STATE_FAWPKT | APP_STATE_KILL_FOLLOW | APP_STATE_DROPME; + return INTERCEPT_RET_CODE_FAIL; + //return APP_STATE_FAWPKT | APP_STATE_KILL_FOLLOW | APP_STATE_DROPME; } static int dabloom_search(struct pkt_info *pktinfo, int thread_seq){ @@ -1503,6 +1532,7 @@ char* kni_maat_action_trans(enum kni_action action){ char next_data_intercept(struct pme_info *pmeinfo, const void *a_packet, struct pkt_info *pktinfo, int thread_seq){ + //return value 0 //FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCP_READY_BYTE], 0, FS_OP_ADD, pktinfo->ip_totlen); int ret, len; void *logger = g_kni_handle->local_logger; @@ -1510,7 +1540,8 @@ char next_data_intercept(struct pme_info *pmeinfo, const void *a_packet, struct struct ip6_hdr* ipv6_hdr = NULL; if(pktinfo->parse_failed == 1){ KNI_LOG_ERROR(logger, "next_data_intercept: invalid ip header, drop pkt and not send to tfe"); - return APP_STATE_DROPPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; + return INTERCEPT_RET_CODE_OK; + //return APP_STATE_DROPPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; } //search dabloom if(g_kni_handle->dup_traffic_switch == 1){ @@ -1519,12 +1550,14 @@ char next_data_intercept(struct pme_info *pmeinfo, const void *a_packet, struct if(g_kni_handle->pxy_tcp_option_enable == 1) { if(pmeinfo->pxy_tcp_option.bypass_duplicated_packet == 1){ //Bypass Duplicated Packet - return APP_STATE_FAWPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; + return INTERCEPT_RET_CODE_BYPASS; + //return APP_STATE_FAWPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; } } ret = dabloom_search(pktinfo, thread_seq); if(ret == 1){ - return APP_STATE_FAWPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; + return INTERCEPT_RET_CODE_BYPASS; + //return APP_STATE_FAWPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; } } } @@ -1539,12 +1572,14 @@ char next_data_intercept(struct pme_info *pmeinfo, const void *a_packet, struct if(pktinfo->ip_totlen > KNI_DEFAULT_MTU){ KNI_LOG_DEBUG(logger, "Next data packet exceed MTU(1500), stream traceid = %s, stream addr = %s", pmeinfo->stream_traceid, pmeinfo->stream_addr); - return APP_STATE_DROPPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; + return INTERCEPT_RET_CODE_OK; + //return APP_STATE_DROPPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; } if(g_kni_handle->ssl_dynamic_bypass_enable == 1){ if(pmeinfo->is_dynamic_bypass){ next_data_ssl_dynamic_bypass(pktinfo); - return APP_STATE_FAWPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; + return INTERCEPT_RET_CODE_BYPASS; + //return APP_STATE_FAWPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; } } @@ -1554,19 +1589,25 @@ char next_data_intercept(struct pme_info *pmeinfo, const void *a_packet, struct pmeinfo->tfe_id, pmeinfo->stream_traceid, pmeinfo->stream_addr); FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCPERR_SENDTO_TFE_FAIL], 0, FS_OP_ADD, 1); } + + KNI_LOG_INFO(logger, "Success at send continue packet to tfe%d, stream traceid = %s, stream addr = %s", + pmeinfo->tfe_id, pmeinfo->stream_traceid, pmeinfo->stream_addr); //else{ // FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCP_BYTE], 0, FS_OP_ADD, pktinfo->ip_totlen); //} - return APP_STATE_DROPPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; + return INTERCEPT_RET_CODE_OK; + //return APP_STATE_DROPPKT | APP_STATE_KILL_FOLLOW | APP_STATE_GIVEME; } -char first_data_process(struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_info *pktinfo, int thread_seq){ - //first data packet, get action + +void read_stream_intercept_status(struct streaminfo *stream, struct pme_info *pmeinfo, int thread_seq) +{ void *logger = g_kni_handle->local_logger; int maat_hit = 0; int ret = 0; struct identify_info _identify_info; ret = tsg_pull_policy_result(stream, PULL_KNI_RESULT, &(pmeinfo->maat_result), 1, &_identify_info); + pmeinfo->check_data_packets_num ++; //ret == 0, bypass and dropme if(ret == 0){ pmeinfo->action = KNI_ACTION_NONE; @@ -1590,25 +1631,89 @@ char first_data_process(struct streaminfo *stream, struct pme_info *pmeinfo, str KNI_LOG_INFO(logger, "intercept_policy_scan: %s, %s, maat_hit = %d, policy_id = %d, action = %d(%s), stream traceid = %s", pmeinfo->stream_addr, (char*)&(pmeinfo->domain), maat_hit, pmeinfo->policy_id, pmeinfo->action, action_str, pmeinfo->stream_traceid); } - switch(pmeinfo->action){ - case KNI_ACTION_INTERCEPT: - pmeinfo->ssl_intercept_state = 1; - //only action = intercept, need sendlog - pmeinfo->tld_handle = TLD_create(-1); - if(g_kni_handle->pxy_tcp_option_enable == 1) - { - KNI_LOG_DEBUG(logger, "Proxy-tcp-option: before scan status:%d ( 1 is has been scanned, other value not scan),stream traceid = %s", pmeinfo->pxy_tcp_option_is_scan,pmeinfo->stream_traceid); - if(pmeinfo->pxy_tcp_option_is_scan != 1) - { - pxy_tcp_option_get_param(g_tsg_maat_feather,(const struct streaminfo *)stream,pmeinfo,logger); - pmeinfo->pxy_tcp_option_is_scan = 1; +} + + +char deal_chello_frag(struct streaminfo *stream, struct pme_info *pmeinfo, int thread_seq) +{ + void * logger = g_kni_handle->local_logger; + int ret = 0; + struct ssl_frag_chello *ssl_frag_chell_0 = ssl_frag_chello_get0(stream); + if(ssl_frag_chell_0->p_sz > 0){ + for(int i = 0; i < (int)ssl_frag_chell_0->p_sz; i++){ + struct detain_pkt *packet = ssl_frag_chell_0->p[i]; + int len_rawpkt; + void *rawpkt = (void *)MESA_detain_rawpkt_data_get0(stream, packet, &len_rawpkt); + + struct pkt_info rawpkt_info; + memset(&rawpkt_info, 0, sizeof(rawpkt_info)); + wrapped_kni_header_parse(rawpkt, pmeinfo, &rawpkt_info); + KNI_LOG_DEBUG(logger, "Deal chello frags list[%d], stream traceid: %s, seq: %u, tcp_data_len: %d",i, pmeinfo->stream_traceid, ntohl(rawpkt_info.tcphdr->seq), rawpkt_info.data_len); + + if(i == 0){ + ret = first_data_intercept(stream, pmeinfo, &rawpkt_info, thread_seq); + // usleep(5000); + if(ret == INTERCEPT_RET_CODE_FAIL){ + break; } + } else { + char *new_pkt = (char*)ALLOC(struct wrapped_packet, 1); + int offset = 0; + offset = rebuild_packet_to_add_tcp_option(pmeinfo, &rawpkt_info, new_pkt); + set_new_packet_checksum(pmeinfo, &rawpkt_info, new_pkt, offset); + ret = next_data_intercept(pmeinfo, (void *)new_pkt, &rawpkt_info, thread_seq); + free(new_pkt); } - return first_data_intercept(stream, pmeinfo, pktinfo, thread_seq); - default: - //action != intercept,bypass and dropme - return APP_STATE_FAWPKT | APP_STATE_DROPME; + } } + ssl_frag_chello_free(stream); + return ret; +} + + + +char first_data_process(struct streaminfo *stream, struct pme_info *pmeinfo, const void *a_packet, struct pkt_info *pktinfo, int thread_seq){ + //first data packet, get action + void *logger = g_kni_handle->local_logger; + + read_stream_intercept_status(stream, pmeinfo, thread_seq); + + if(pmeinfo->check_data_packets_num == 1) + { + int ret = is_stream_can_intercept(stream, pmeinfo, pktinfo, thread_seq); + if(ret == INTERCEPT_RET_CODE_FAIL){ + return INTERCEPT_RET_CODE_FAIL; + } + } + if(pmeinfo->action != KNI_ACTION_INTERCEPT && pmeinfo->check_data_packets_num < g_kni_handle->reassembled_packets_num) + return INTERCEPT_RET_CODE_NEED_NEXT; + + if(pmeinfo->action == KNI_ACTION_INTERCEPT){ + pmeinfo->ssl_intercept_state = 1; + //only action = intercept, need sendlog + pmeinfo->tld_handle = TLD_create(-1); + if(g_kni_handle->pxy_tcp_option_enable == 1) + { + KNI_LOG_DEBUG(logger, "Proxy-tcp-option: before scan status:%d ( 1 is has been scanned, other value not scan),stream traceid = %s", pmeinfo->pxy_tcp_option_is_scan,pmeinfo->stream_traceid); + if(pmeinfo->pxy_tcp_option_is_scan != 1) + { + pxy_tcp_option_get_param(g_tsg_maat_feather,(const struct streaminfo *)stream,pmeinfo,logger); + pmeinfo->pxy_tcp_option_is_scan = 1; + } + } + + struct ssl_frag_chello *ssl_frag_chell_0 = ssl_frag_chello_get0(stream); + if(ssl_frag_chell_0 && ssl_frag_chell_0->p_sz > 0) + { + KNI_LOG_DEBUG(logger, "ssl_frag chello: packet num: %d, stream traceid = %s, data packet number: %d", ssl_frag_chell_0->p_sz, pmeinfo->stream_traceid, pmeinfo->check_data_packets_num); + return deal_chello_frag(stream, pmeinfo, thread_seq); + // ret = next_data_intercept(pmeinfo, a_packet, pktinfo, thread_seq); + } + else{ + return first_data_intercept(stream, pmeinfo, pktinfo, thread_seq); + } + } + return APP_STATE_FAWPKT | APP_STATE_DROPME; } void dup_traffic_detect(struct pme_info *pmeinfo, struct pkt_info *pktinfo){ @@ -1679,7 +1784,7 @@ static char data_opstate(struct streaminfo *stream, struct pme_info *pmeinfo, co } //first data if(stream->ptcpdetail->datalen > 0){ - return first_data_process(stream, pmeinfo, &pktinfo, thread_seq); + return first_data_process(stream, pmeinfo, a_packet, &pktinfo, thread_seq); } //before first data, may be dup_syn, syn/ack, dup_syn/ack if(pktinfo.parse_failed != 0){ @@ -2504,6 +2609,7 @@ extern "C" int kni_init(){ printf("MESA_prof_load: log_level not set, profile = %s, section = %s", profile, section); goto error_out; } + local_logger = MESA_create_runtime_log_handle(log_path, log_level); if (unlikely(local_logger == NULL)){ printf("Failed at create logger: %s", log_path); @@ -2514,7 +2620,7 @@ extern "C" int kni_init(){ //kni_git_log KNI_LOG_ERROR(local_logger, "----------kni version = %s-----------", kni_git_verison); - + MESA_load_profile_int_def(profile, section, "reassembled_packets_num", &(g_kni_handle->reassembled_packets_num), 2); char deploy_mode[KNI_SYMBOL_MAX]; ret = MESA_load_profile_string_def(profile, section, "deploy_mode", deploy_mode, sizeof(deploy_mode), "normal"); g_kni_handle->deploy_mode = KNI_DEPLOY_MODE_NORMAL; @@ -2707,6 +2813,7 @@ extern "C" int kni_init(){ FREE(&cmsg_receiver_args); goto error_out; } + return 0; error_out: