feature for ssl chello frag.

This commit is contained in:
fumingwei
2024-06-06 00:18:21 +08:00
parent 5718d879f3
commit 46839fe9f5
3 changed files with 168 additions and 54 deletions

View File

@@ -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

View File

@@ -7,6 +7,8 @@
#include <tsg/tsg_statistic.h>
#include "tfe_mgr.h"
#include <tsg/tsg_label.h>
#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{

View File

@@ -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 != interceptbypass 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: