diff options
| author | wangmenglan <[email protected]> | 2023-05-26 18:50:18 +0800 |
|---|---|---|
| committer | wangmenglan <[email protected]> | 2023-06-02 19:51:45 +0800 |
| commit | 4d262813384164aa139871be504fdf68ed8dcc3b (patch) | |
| tree | 8a6d6d48e455e32a204160328b691a9e77d91a65 /common/src | |
| parent | f00ef6596352b4e39f32df1c8be55de1e1a7deec (diff) | |
TFE Packet IO支持带封装报文格式v4.8.20-20230602
Diffstat (limited to 'common/src')
| -rw-r--r-- | common/src/io_uring.cpp | 2 | ||||
| -rw-r--r-- | common/src/tfe_ctrl_packet.cpp | 96 | ||||
| -rw-r--r-- | common/src/tfe_fieldstat.cpp | 13 | ||||
| -rw-r--r-- | common/src/tfe_packet_io.cpp | 345 | ||||
| -rw-r--r-- | common/src/tfe_raw_packet.cpp | 76 |
5 files changed, 403 insertions, 129 deletions
diff --git a/common/src/io_uring.cpp b/common/src/io_uring.cpp index e9af2f4..4066ce1 100644 --- a/common/src/io_uring.cpp +++ b/common/src/io_uring.cpp @@ -224,7 +224,7 @@ int io_uring_submit_write_entry(struct io_uring_instance *instance, const char * if (len > instance->config.buff_size) { - TFE_LOG_ERROR(g_default_logger, "IO_URING: the length of the sent data is greater than the capacity of the io_uring buffer"); + TFE_LOG_ERROR(g_default_logger, "IO_URING: the length of the sent data [%d] is greater than the capacity of the io_uring buffer [%d]", len, instance->config.buff_size); return -1; } diff --git a/common/src/tfe_ctrl_packet.cpp b/common/src/tfe_ctrl_packet.cpp index c9bd977..b86d276 100644 --- a/common/src/tfe_ctrl_packet.cpp +++ b/common/src/tfe_ctrl_packet.cpp @@ -29,6 +29,8 @@ enum { MPACK_ARRAY_ACK_SIDS, MPACK_ARRAY_SEQ_ROUTE_CTX, MPACK_ARRAY_ACK_ROUTE_CTX, + MPACK_ARRAY_SEQ_PKG_HEADER, + MPACK_ARRAY_ACK_PKG_HEADER, }; struct mpack_mmap_id2type @@ -74,9 +76,14 @@ struct mpack_mmap_id2type {.id = 32, .type = TFE_CMSG_TLV_NR_MAX, .str_name = "TFE_SEQ_SIDS", .size = 2, .array_index = MPACK_ARRAY_SEQ_SIDS}, {.id = 33, .type = TFE_CMSG_TLV_NR_MAX, .str_name = "TFE_ACK_SIDS", .size = 2, .array_index = MPACK_ARRAY_ACK_SIDS}, {.id = 34, .type = TFE_CMSG_TLV_NR_MAX, .str_name = "TFE_SEQ_ROUTE_CTX", .size = 1, .array_index = MPACK_ARRAY_SEQ_ROUTE_CTX}, - {.id = 35, .type = TFE_CMSG_TLV_NR_MAX, .str_name = "TFE_ACK_ROUTE_CTX", .size = 1, .array_index = MPACK_ARRAY_ACK_ROUTE_CTX} + {.id = 35, .type = TFE_CMSG_TLV_NR_MAX, .str_name = "TFE_ACK_ROUTE_CTX", .size = 1, .array_index = MPACK_ARRAY_ACK_ROUTE_CTX}, + {.id = 36, .type = TFE_CMSG_TLV_NR_MAX, .str_name = "TFE_SEQ_PKG_HEADER", .size = 1, .array_index = MPACK_ARRAY_SEQ_PKG_HEADER}, + {.id = 37, .type = TFE_CMSG_TLV_NR_MAX, .str_name = "TFE_ACK_PKG_HEADER", .size = 1, .array_index = MPACK_ARRAY_ACK_PKG_HEADER}, + {.id = 38, .type = TFE_CMSG_TLV_NR_MAX, .str_name = "TFE_FLAG", .size = 1, .array_index = MPACK_ARRAY_INIT} }; +extern void * g_packet_io_logger; + static int fqdn_id_set_cmsg(struct ctrl_pkt_parser *handler, mpack_node_t node, int table_index) { char empty_str[4] = {0}; @@ -114,15 +121,33 @@ static int sids_array_parse_mpack(struct ctrl_pkt_parser *handler, mpack_node_t static int route_ctx_parse_mpack(struct ctrl_pkt_parser *handler, mpack_node_t node, int table_index, int is_seq) { struct route_ctx *ctx = is_seq ? &handler->seq_route_ctx : &handler->ack_route_ctx; - if (mpack_node_array_length(node) > 64) { + size_t len = mpack_node_bin_size(node); + if (len < 0 || len > 64) { + TFE_LOG_ERROR(g_packet_io_logger, "%s: session %lu unexpected control packet: (%s route len[%ld] is invalid)", LOG_TAG_CTRLPKT, handler->session_id, is_seq ? "seq" : "ack", len); return -1; } - ctx->len = mpack_node_array_length(node); - for (int i = 0; i < ctx->len; i++) - { - ctx->data[i] = mpack_node_u8(mpack_node_array_at(node, i)); + ctx->len = len; + memcpy(ctx->data, mpack_node_bin_data(node), len); + return 0; +} + +static int pkt_header_parse_mpack(struct ctrl_pkt_parser *handler, mpack_node_t node, int table_index, int is_seq) +{ + char **header = is_seq ? &handler->seq_header : &handler->ack_header; + int *header_len = is_seq ? &handler->seq_len : &handler->ack_len; + size_t len = mpack_node_bin_size(node); + if (len < 0) { + TFE_LOG_ERROR(g_packet_io_logger, "%s: session %lu unexpected control packet: (%s package header len[%ld] is invalid)", LOG_TAG_CTRLPKT, handler->session_id, is_seq ? "seq" : "ack", len); + return -1; } + + if (len == 0) + return 0; + + *header = (char *)calloc(len, sizeof(char)); + memcpy(*header, mpack_node_bin_data(node), len); + *header_len = len; return 0; } @@ -155,8 +180,13 @@ static int proxy_parse_messagepack(mpack_node_t node, void *ctx, void *logger) switch (mpack_node_type(ptr)) { case mpack_type_uint: - value = mpack_node_u64(ptr); - tfe_cmsg_set(handler->cmsg, mpack_table[i].type, (const unsigned char *)&value, mpack_table[i].size); + if (i == 38) { + handler->intercpet_data = mpack_node_u8(ptr); + } + else { + value = mpack_node_u64(ptr); + tfe_cmsg_set(handler->cmsg, mpack_table[i].type, (const unsigned char *)&value, mpack_table[i].size); + } break; case mpack_type_str: mpack_node_copy_cstr(ptr, cmsg_str, sizeof(cmsg_str)); @@ -165,6 +195,33 @@ static int proxy_parse_messagepack(mpack_node_t node, void *ctx, void *logger) case mpack_type_nil: tfe_cmsg_set(handler->cmsg, mpack_table[i].type, (const unsigned char *)empty_str, 0); break; + case mpack_type_bin: + switch(mpack_table[i].array_index) + { + case MPACK_ARRAY_SEQ_ROUTE_CTX: + ret = route_ctx_parse_mpack(handler, ptr, i, 1); + if (ret != 0) + return -1; + break; + case MPACK_ARRAY_ACK_ROUTE_CTX: + ret = route_ctx_parse_mpack(handler, ptr, i, 0); + if (ret != 0) + return -1; + break; + case MPACK_ARRAY_SEQ_PKG_HEADER: + ret = pkt_header_parse_mpack(handler, ptr, i, 1); + if (ret != 0) + return -1; + break; + case MPACK_ARRAY_ACK_PKG_HEADER: + ret = pkt_header_parse_mpack(handler, ptr, i, 0); + if (ret != 0) + return -1; + break; + default: + break; + } + break; case mpack_type_array: switch(mpack_table[i].array_index) { @@ -181,16 +238,6 @@ static int proxy_parse_messagepack(mpack_node_t node, void *ctx, void *logger) if (ret != 0) return -1; break; - case MPACK_ARRAY_SEQ_ROUTE_CTX: - ret = route_ctx_parse_mpack(handler, ptr, i, 1); - if (ret != 0) - return -1; - break; - case MPACK_ARRAY_ACK_ROUTE_CTX: - ret = route_ctx_parse_mpack(handler, ptr, i, 0); - if (ret != 0) - return -1; - break; default: break; } @@ -306,7 +353,6 @@ int ctrl_packet_parser_parse(void *ctx, const char* data, size_t length, void *l } handler->cmsg = tfe_cmsg_init(); - tfe_cmsg_dup(handler->cmsg); proxy_map = mpack_node_map_cstr(params, "proxy"); ret = proxy_parse_messagepack(proxy_map, handler, logger); if (ret != 0) @@ -318,7 +364,6 @@ succ: error: mpack_tree_destroy(&tree); tfe_cmsg_destroy(handler->cmsg); - tfe_cmsg_destroy(handler->cmsg); return -1; } @@ -348,7 +393,16 @@ void ctrl_packet_cmsg_destroy(struct ctrl_pkt_parser *handler) { if (handler) { tfe_cmsg_destroy(handler->cmsg); - tfe_cmsg_destroy(handler->cmsg); + + if (handler->seq_header) { + free(handler->seq_header); + handler->seq_header = NULL; + } + + if (handler->ack_header) { + free(handler->ack_header); + handler->ack_header = NULL; + } } } diff --git a/common/src/tfe_fieldstat.cpp b/common/src/tfe_fieldstat.cpp index 6e37d58..b9ec2a6 100644 --- a/common/src/tfe_fieldstat.cpp +++ b/common/src/tfe_fieldstat.cpp @@ -4,13 +4,12 @@ #include "tfe_stream.h" #include "tfe_resource.h" -void tfe_set_intercept_metric(struct tfe_stream *stream, int hit_count, int downstream_rx_pkts, int downstream_rx_bytes, int upstream_rx_pkts, int upstream_rx_bytes) +void tfe_set_intercept_metric(struct tfe_cmsg *cmsg, int hit_count, int downstream_rx_pkts, int downstream_rx_bytes, int upstream_rx_pkts, int upstream_rx_bytes, int thread_id) { int ret; uint16_t out_size; struct tfe_fieldstat_metric_t *fieldstat = (struct tfe_fieldstat_metric_t *)tfe_bussiness_resouce_get(DYNAMIC_FIELDSTAT); - struct tfe_cmsg *cmsg = tfe_stream_get0_cmsg(stream); if (cmsg == NULL) { return; @@ -126,27 +125,27 @@ void tfe_set_intercept_metric(struct tfe_stream *stream, int hit_count, int down if (hit_count > 0) { - fieldstat_dynamic_table_metric_value_incrby(fieldstat->instance, fieldstat->table_id, fieldstat->column_array[COLUMN_HIT_COUNT], "proxy_rule_hits", hit_count, temp_tags, (size_t)nr_tags, stream->thread_id); + fieldstat_dynamic_table_metric_value_incrby(fieldstat->instance, fieldstat->table_id, fieldstat->column_array[COLUMN_HIT_COUNT], "proxy_rule_hits", hit_count, temp_tags, (size_t)nr_tags, thread_id); } if (in_pkts > 0) { - fieldstat_dynamic_table_metric_value_incrby(fieldstat->instance, fieldstat->table_id, fieldstat->column_array[COLUMN_IN_PKTS], "proxy_rule_hits", in_pkts, temp_tags, (size_t)nr_tags, stream->thread_id); + fieldstat_dynamic_table_metric_value_incrby(fieldstat->instance, fieldstat->table_id, fieldstat->column_array[COLUMN_IN_PKTS], "proxy_rule_hits", in_pkts, temp_tags, (size_t)nr_tags, thread_id); } if (in_bytes > 0) { - fieldstat_dynamic_table_metric_value_incrby(fieldstat->instance, fieldstat->table_id, fieldstat->column_array[COLUMN_IN_BYTES], "proxy_rule_hits", in_bytes, temp_tags, (size_t)nr_tags, stream->thread_id); + fieldstat_dynamic_table_metric_value_incrby(fieldstat->instance, fieldstat->table_id, fieldstat->column_array[COLUMN_IN_BYTES], "proxy_rule_hits", in_bytes, temp_tags, (size_t)nr_tags, thread_id); } if (out_pkts > 0) { - fieldstat_dynamic_table_metric_value_incrby(fieldstat->instance, fieldstat->table_id, fieldstat->column_array[COLUMN_OUT_PKTS], "proxy_rule_hits", out_pkts, temp_tags, (size_t)nr_tags, stream->thread_id); + fieldstat_dynamic_table_metric_value_incrby(fieldstat->instance, fieldstat->table_id, fieldstat->column_array[COLUMN_OUT_PKTS], "proxy_rule_hits", out_pkts, temp_tags, (size_t)nr_tags, thread_id); } if (out_bytes > 0) { - fieldstat_dynamic_table_metric_value_incrby(fieldstat->instance, fieldstat->table_id, fieldstat->column_array[COLUMN_OUT_BYTES], "proxy_rule_hits", out_bytes, temp_tags, (size_t)nr_tags, stream->thread_id); + fieldstat_dynamic_table_metric_value_incrby(fieldstat->instance, fieldstat->table_id, fieldstat->column_array[COLUMN_OUT_BYTES], "proxy_rule_hits", out_bytes, temp_tags, (size_t)nr_tags, thread_id); } } diff --git a/common/src/tfe_packet_io.cpp b/common/src/tfe_packet_io.cpp index e829e22..3eefc5b 100644 --- a/common/src/tfe_packet_io.cpp +++ b/common/src/tfe_packet_io.cpp @@ -31,7 +31,7 @@ #include "bpf_obj.h" #include "tfe_session_table.h" #include "tfe_packet_io.h" - +#include "tfe_fieldstat.h" /****************************************************************************** @@ -40,6 +40,10 @@ #define RX_BURST_MAX 128 + +#define IS_SINGLE 0x01 +#define IS_TUNNEL 0x02 + #define TRAFFIC_IS_DECRYPTED (1 << 0) #define SET_TRAFFIC_IS_DECRYPTED(field) (field | TRAFFIC_IS_DECRYPTED) #define CLEAR_TRAFFIC_IS_DECRYPTED(field) (field & ~TRAFFIC_IS_DECRYPTED) @@ -198,7 +202,6 @@ static int tap_write(int tap_fd, const char *data, int data_len, void *logger) static struct metadata *metadata_new() { struct metadata *meta = (struct metadata *)calloc(1, sizeof(struct metadata)); - return meta; } @@ -275,6 +278,16 @@ static void session_ctx_free(struct session_ctx *ctx) ctx->ctrl_meta = NULL; } + if (ctx->c2s_info.header_data) { + free(ctx->c2s_info.header_data); + ctx->c2s_info.header_data = NULL; + } + + if (ctx->s2c_info.header_data) { + free(ctx->s2c_info.header_data); + ctx->s2c_info.header_data = NULL; + } + free(ctx); ctx = NULL; } @@ -293,6 +306,12 @@ static int add_ether_header(void *raw_data, char *src_mac, char *dst_mac){ return 0; } +static int add_ether_proto(void *raw_data, uint16_t proto){ + struct ethhdr *ether_hdr = (struct ethhdr*)raw_data; + ether_hdr->h_proto = htons(proto); // ETH_P_IP + return 0; +} + static int fake_tcp_handshake(struct tfe_proxy *proxy, struct tcp_restore_info *restore_info) { char buffer[1500] = {0}; @@ -962,9 +981,9 @@ static int packet_io_set_metadata(marsio_buff_t *tx_buff, struct metadata *meta, return 0; } -static void packet_io_dump_metadata(marsio_buff_t *tx_buff, struct metadata *meta, void *logger) +static void packet_io_dump_metadata(struct metadata *meta, void *logger) { - TFE_LOG_DEBUG(logger, "%s: META={session_id: %lu, raw_len: %d, is_e2i_dir: %d, is_ctrl_pkt: %d, l7offset: %d, is_decrypted: %u, sids_num: %d}", LOG_TAG_PKTIO, meta->session_id, meta->raw_len, meta->is_e2i_dir, meta->is_ctrl_pkt, meta->l7offset, meta->is_decrypted, meta->sids.num); + TFE_LOG_ERROR(logger, "%s: META={session_id: %lu, raw_len: %d, is_e2i_dir: %d, is_ctrl_pkt: %d, l7offset: %d, is_decrypted: %u, sids_num: %d}", LOG_TAG_PKTIO, meta->session_id, meta->raw_len, meta->is_e2i_dir, meta->is_ctrl_pkt, meta->l7offset, meta->is_decrypted, meta->sids.num); } /* @@ -1154,15 +1173,32 @@ static void tcp_restore_info_dump(struct tcp_restore_info *info, uint64_t sessio } } +static void set_passthrough_reason(struct tfe_cmsg *cmsg, char *reason) +{ + uint8_t ssl_intercept_status = SSL_ACTION_PASSTHROUGH; + + tfe_cmsg_set(cmsg, TFE_CMSG_SSL_PASSTHROUGH_REASON, (const unsigned char *)&reason, strlen(reason)); + tfe_cmsg_set(cmsg, TFE_CMSG_SSL_INTERCEPT_STATE, (const unsigned char *)&ssl_intercept_status, (uint16_t)sizeof(ssl_intercept_status)); + tfe_cmsg_set_flag(cmsg, TFE_CMSG_FLAG_USER0); +} + // return 0 : success // return -1 : error static int handle_session_opening(struct metadata *meta, struct ctrl_pkt_parser *parser, int thread_seq, void *ctx) { + int ret = 0; int fd_downstream = 0; int fd_upstream = 0; int fd_fake_c = 0; int fd_fake_s = 0; uint16_t size = 0; + uint8_t is_passthrough = 0; + uint8_t hit_no_intercept = 0; + uint16_t out_size = 0; + char reason_hit_no_intercept[] = "Hit No Intercept"; + char reason_invalid_intercept_param[] = "Invalid Intercept Param"; + char reason_invalid_tcp_policy_param[] = "Invalid tcp policy Param"; + char reason_underlying_stream_error[] = "Underlying Stream Error"; unsigned int stream_common_direction; uint8_t stream_protocol_in_char = 0; @@ -1187,81 +1223,118 @@ static int handle_session_opening(struct metadata *meta, struct ctrl_pkt_parser uint16_t offset = (char *)payload - meta->raw_data; TFE_LOG_ERROR(logger, "%s: incorrect dataoffset in the control zone of session %lu, offset:%u, l7offset:%u, payload:%p, raw_data:%p", LOG_TAG_PKTIO, meta->session_id, offset, meta->l7offset, payload, meta->raw_data); } - raw_packet_parser_get_most_inner_tuple4(&raw_parser, &inner_tuple4, logger); - intercept_policy_enforce(thread->ref_proxy->int_ply_enforcer, parser->cmsg); - tcp_policy_enforce(thread->ref_proxy->tcp_ply_enforcer, parser->cmsg); - for (int i = 0; i < parser->sce_policy_id_num; i++) { - chaining_policy_enforce(thread->ref_proxy->chain_ply_enforcer, parser->cmsg, parser->sce_policy_ids[i]); - } + if (parser->intercpet_data == 0) { + ret = intercept_policy_enforce(thread->ref_proxy->int_ply_enforcer, parser->cmsg); + if (ret != 0) { + is_passthrough = 1; + set_passthrough_reason(parser->cmsg, reason_invalid_intercept_param); + goto passthrough; + } - tcp_restore_set_from_cmsg(parser->cmsg, &restore_info); - tcp_restore_set_from_pkg(&inner_tuple4, &restore_info); + tfe_cmsg_get_value(parser->cmsg, TFE_CMSG_HIT_NO_INTERCEPT, (unsigned char *)&hit_no_intercept, sizeof(hit_no_intercept), &out_size); + if (hit_no_intercept == 1) { + is_passthrough = 1; + set_passthrough_reason(parser->cmsg, reason_hit_no_intercept); + goto passthrough; + } - if (overwrite_tcp_mss(parser->cmsg, &restore_info, meta->session_id, logger)) - { - goto end; - } - tcp_restore_info_dump(&restore_info, meta->session_id, logger); + ret = tcp_policy_enforce(thread->ref_proxy->tcp_ply_enforcer, parser->cmsg); + if (ret != 0) { + is_passthrough = 1; + set_passthrough_reason(parser->cmsg, reason_invalid_tcp_policy_param); + goto passthrough; + } - // tcp repair C2S - fd_upstream = tfe_tcp_restore_fd_create(&(restore_info.client), &(restore_info.server), packet_io->config.dev_tap, 0x65); - if (fd_upstream < 0) - { - TFE_LOG_ERROR(logger, "%s: session %lu Failed at tcp_restore_fd_create(UPSTREAM)", LOG_TAG_PKTIO, meta->session_id); - goto end; - } + for (int i = 0; i < parser->sce_policy_id_num; i++) { + chaining_policy_enforce(thread->ref_proxy->chain_ply_enforcer, parser->cmsg, parser->sce_policy_ids[i]); + } - // tcp repair S2C - fd_downstream = tfe_tcp_restore_fd_create(&(restore_info.server), &(restore_info.client), packet_io->config.dev_tap, 0x65); - if (fd_downstream < 0) - { - TFE_LOG_ERROR(logger, "%s: session %lu Failed at tcp_restore_fd_create(DOWNSTREAM)", LOG_TAG_PKTIO, meta->session_id); - goto end; - } + tcp_restore_set_from_cmsg(parser->cmsg, &restore_info); + tcp_restore_set_from_pkg(&inner_tuple4, &restore_info); - tfe_cmsg_get_value(parser->cmsg, TFE_CMSG_TCP_RESTORE_PROTOCOL, (unsigned char *)&stream_protocol_in_char, sizeof(stream_protocol_in_char), &size); - tfe_cmsg_get_value(parser->cmsg, TFE_CMSG_TCP_DECRYPTED_TRAFFIC_STEERING, (unsigned char *)&enable_decrypted_traffic_steering, sizeof(enable_decrypted_traffic_steering), &size); - if ((STREAM_PROTO_PLAIN == (enum tfe_stream_proto)stream_protocol_in_char && thread->ref_proxy->traffic_steering_options.enable_steering_http) || - (STREAM_PROTO_SSL == (enum tfe_stream_proto)stream_protocol_in_char && thread->ref_proxy->traffic_steering_options.enable_steering_ssl) || - enable_decrypted_traffic_steering == 1) - { - if (fake_tcp_handshake(thread->ref_proxy, &restore_info) == -1) - { - TFE_LOG_ERROR(logger, "%s: session %lu Failed at fake_tcp_handshake()", LOG_TAG_PKTIO, meta->session_id); - goto end; - } + if (overwrite_tcp_mss(parser->cmsg, &restore_info, meta->session_id, logger)) { + is_passthrough = 1; + set_passthrough_reason(parser->cmsg, reason_invalid_tcp_policy_param); + goto passthrough; + } + tcp_restore_info_dump(&restore_info, meta->session_id, logger); + + // tcp repair C2S + fd_upstream = tfe_tcp_restore_fd_create(&(restore_info.client), &(restore_info.server), packet_io->config.dev_tap, 0x65); + if (fd_upstream < 0) { + TFE_LOG_ERROR(logger, "%s: session %lu Failed at tcp_restore_fd_create(UPSTREAM)", LOG_TAG_PKTIO, meta->session_id); + is_passthrough = 1; + set_passthrough_reason(parser->cmsg, reason_invalid_tcp_policy_param); + goto passthrough; + } - fd_fake_c = tfe_tcp_restore_fd_create(&(restore_info.client), &(restore_info.server), thread->ref_proxy->traffic_steering_options.device_client, thread->ref_proxy->traffic_steering_options.so_mask_client); - if (fd_fake_c < 0) - { - TFE_LOG_ERROR(logger, "%s: session %lu Failed at tcp_restore_fd_create(fd_fake_c)", LOG_TAG_PKTIO, meta->session_id); - goto end; - } + // tcp repair S2C + fd_downstream = tfe_tcp_restore_fd_create(&(restore_info.server), &(restore_info.client), packet_io->config.dev_tap, 0x65); + if (fd_downstream < 0) + { + TFE_LOG_ERROR(logger, "%s: session %lu Failed at tcp_restore_fd_create(DOWNSTREAM)", LOG_TAG_PKTIO, meta->session_id); + is_passthrough = 1; + set_passthrough_reason(parser->cmsg, reason_invalid_tcp_policy_param); + goto passthrough; + } - fd_fake_s = tfe_tcp_restore_fd_create(&(restore_info.server), &(restore_info.client), thread->ref_proxy->traffic_steering_options.device_server, thread->ref_proxy->traffic_steering_options.so_mask_server); - if (fd_fake_s < 0) - { - TFE_LOG_ERROR(logger, "%s: session %lu Failed at tcp_restore_fd_create(fd_fake_s)", LOG_TAG_PKTIO, meta->session_id); - goto end; - } - } + tfe_cmsg_get_value(parser->cmsg, TFE_CMSG_TCP_RESTORE_PROTOCOL, (unsigned char *)&stream_protocol_in_char, sizeof(stream_protocol_in_char), &size); + tfe_cmsg_get_value(parser->cmsg, TFE_CMSG_TCP_DECRYPTED_TRAFFIC_STEERING, (unsigned char *)&enable_decrypted_traffic_steering, sizeof(enable_decrypted_traffic_steering), &size); + if ((STREAM_PROTO_PLAIN == (enum tfe_stream_proto)stream_protocol_in_char && thread->ref_proxy->traffic_steering_options.enable_steering_http) || + (STREAM_PROTO_SSL == (enum tfe_stream_proto)stream_protocol_in_char && thread->ref_proxy->traffic_steering_options.enable_steering_ssl) || + enable_decrypted_traffic_steering == 1) + { + if (fake_tcp_handshake(thread->ref_proxy, &restore_info) == -1) + { + TFE_LOG_ERROR(logger, "%s: session %lu Failed at fake_tcp_handshake()", LOG_TAG_PKTIO, meta->session_id); + is_passthrough = 1; + set_passthrough_reason(parser->cmsg, reason_invalid_tcp_policy_param); + goto passthrough; + } - if (tfe_proxy_fds_accept(thread->ref_proxy, fd_downstream, fd_upstream, fd_fake_c, fd_fake_s, parser->cmsg) < 0) - { - TFE_LOG_ERROR(logger, "%s: session %lu Failed at tfe_proxy_fds_accept()", LOG_TAG_PKTIO, meta->session_id); - goto end; - } + fd_fake_c = tfe_tcp_restore_fd_create(&(restore_info.client), &(restore_info.server), thread->ref_proxy->traffic_steering_options.device_client, thread->ref_proxy->traffic_steering_options.so_mask_client); + if (fd_fake_c < 0) + { + TFE_LOG_ERROR(logger, "%s: session %lu Failed at tcp_restore_fd_create(fd_fake_c)", LOG_TAG_PKTIO, meta->session_id); + is_passthrough = 1; + set_passthrough_reason(parser->cmsg, reason_invalid_tcp_policy_param); + goto passthrough; + } - // E -> I - if (meta->is_e2i_dir) - stream_common_direction = 'I'; - // I -> E - else - stream_common_direction = 'E'; - tfe_cmsg_set(parser->cmsg, TFE_CMSG_COMMON_DIRECTION, (const unsigned char *)&stream_common_direction, sizeof(stream_common_direction)); + fd_fake_s = tfe_tcp_restore_fd_create(&(restore_info.server), &(restore_info.client), thread->ref_proxy->traffic_steering_options.device_server, thread->ref_proxy->traffic_steering_options.so_mask_server); + if (fd_fake_s < 0) + { + TFE_LOG_ERROR(logger, "%s: session %lu Failed at tcp_restore_fd_create(fd_fake_s)", LOG_TAG_PKTIO, meta->session_id); + is_passthrough = 1; + set_passthrough_reason(parser->cmsg, reason_invalid_tcp_policy_param); + goto passthrough; + } + } + + if (tfe_proxy_fds_accept(thread->ref_proxy, fd_downstream, fd_upstream, fd_fake_c, fd_fake_s, parser->cmsg) < 0) + { + TFE_LOG_ERROR(logger, "%s: session %lu Failed at tfe_proxy_fds_accept()", LOG_TAG_PKTIO, meta->session_id); + is_passthrough = 1; + set_passthrough_reason(parser->cmsg, reason_invalid_tcp_policy_param); + goto passthrough; + } + + // E -> I + if (meta->is_e2i_dir) + stream_common_direction = 'I'; + // I -> E + else + stream_common_direction = 'E'; + tfe_cmsg_set(parser->cmsg, TFE_CMSG_COMMON_DIRECTION, (const unsigned char *)&stream_common_direction, sizeof(stream_common_direction)); + } + else if (parser->intercpet_data & (IS_SINGLE | IS_TUNNEL)) { + is_passthrough = 1; + set_passthrough_reason(parser->cmsg, reason_underlying_stream_error); + } +passthrough: s_ctx = session_ctx_new(); s_ctx->raw_meta_i2e = metadata_new(); s_ctx->raw_meta_e2i = metadata_new(); @@ -1271,6 +1344,7 @@ static int handle_session_opening(struct metadata *meta, struct ctrl_pkt_parser s_ctx->session_id = meta->session_id; s_ctx->session_addr = addr_tuple4_to_str(&inner_tuple4); s_ctx->cmsg = parser->cmsg; + s_ctx->is_passthrough = is_passthrough; metadata_deep_copy(s_ctx->ctrl_meta, meta); ether_hdr = (struct ethhdr *)(s_ctx->ctrl_meta->raw_data); @@ -1289,6 +1363,12 @@ static int handle_session_opening(struct metadata *meta, struct ctrl_pkt_parser sids_copy(&s_ctx->ctrl_meta->sids, &meta->sids); route_ctx_copy(&s_ctx->ctrl_meta->route_ctx, &meta->route_ctx); + + if (parser->seq_len > 0) + raw_traffic_decapsulate(&raw_parser, parser->seq_header, parser->seq_len, &s_ctx->c2s_info.header_data, &s_ctx->c2s_info.header_len, &s_ctx->c2s_info.is_ipv4); + if (parser->ack_len > 0) + raw_traffic_decapsulate(&raw_parser, parser->ack_header, parser->ack_len, &s_ctx->s2c_info.header_data, &s_ctx->s2c_info.header_len, &s_ctx->s2c_info.is_ipv4); + if (s_ctx->c2s_info.is_e2i_dir) { sids_copy(&s_ctx->raw_meta_e2i->sids, &parser->seq_sids); route_ctx_copy(&s_ctx->raw_meta_e2i->route_ctx, &parser->seq_route_ctx); @@ -1307,10 +1387,12 @@ static int handle_session_opening(struct metadata *meta, struct ctrl_pkt_parser session_table_insert(thread->session_table, s_ctx->session_id, &(s_ctx->c2s_info.tuple4), s_ctx, session_value_free_cb); ATOMIC_INC(&(packet_io_fs->session_num)); + tfe_cmsg_dup(parser->cmsg); + if (parser->seq_header) + FREE(&parser->seq_header); + if (parser->ack_header) + FREE(&parser->ack_header); return 0; -end: - ctrl_packet_cmsg_destroy(parser); - return -1; } // return 0 : success @@ -1343,6 +1425,7 @@ static int handle_session_closing(struct metadata *meta, struct ctrl_pkt_parser TFE_LOG_INFO(logger, "%s: session %lu closing", LOG_TAG_PKTIO, s_ctx->session_id); session_table_delete_by_id(thread->session_table, meta->session_id); ATOMIC_DEC(&(packet_io_fs->session_num)); + tfe_set_intercept_metric(s_ctx->cmsg, 1, s_ctx->c2s_info.rx.n_pkts, s_ctx->c2s_info.rx.n_bytes, s_ctx->s2c_info.rx.n_pkts, s_ctx->s2c_info.rx.n_bytes, thread_seq); return 0; } @@ -1429,14 +1512,16 @@ static int handle_raw_packet_from_nf(struct packet_io *handle, marsio_buff_t *rx struct packet_io_thread_ctx *thread = (struct packet_io_thread_ctx *)ctx; struct packet_io *packet_io = thread->ref_io; struct packet_io_fs *packet_io_fs = thread->ret_fs_state; + int is_ipv4 = 0; + char *header = NULL; + int header_len = 0; void * logger = thread->logger; int raw_len = marsio_buff_datalen(rx_buff); char *raw_data = marsio_buff_mtod(rx_buff); struct metadata meta; - if (packet_io_get_metadata(rx_buff, &meta, logger) == -1) - { + if (packet_io_get_metadata(rx_buff, &meta, logger) == -1) { TFE_LOG_ERROR(logger, "%s: unexpected control packet, unable to get metadata\n\tMETA={session_id: %lu, raw_len: %d, is_e2i_dir: %d, is_ctrl_pkt: %d, l7offset: %d, is_decrypted: %u, sids_num: %d}", LOG_TAG_PKTIO, meta.session_id, meta.raw_len, meta.is_e2i_dir, meta.is_ctrl_pkt, meta.l7offset, meta.is_decrypted, meta.sids.num); throughput_metrics_inc(&packet_io_fs->raw_pkt_rx, 1, raw_len); @@ -1446,8 +1531,7 @@ static int handle_raw_packet_from_nf(struct packet_io *handle, marsio_buff_t *rx } struct session_node *node = session_table_search_by_id(thread->session_table, meta.session_id); - if (node == NULL) - { + if (node == NULL) { throughput_metrics_inc(&packet_io_fs->raw_pkt_rx, 1, raw_len); throughput_metrics_inc(&packet_io_fs->raw_bypass, 1, raw_len); marsio_send_burst(handle->dev_nf_interface.mr_path, thread_seq, &rx_buff, 1); @@ -1456,6 +1540,17 @@ static int handle_raw_packet_from_nf(struct packet_io *handle, marsio_buff_t *rx struct session_ctx *s_ctx = (struct session_ctx *)node->val_data; + if (s_ctx->is_passthrough > 0) { + throughput_metrics_inc(&packet_io_fs->raw_pkt_rx, 1, raw_len); + throughput_metrics_inc(&packet_io_fs->raw_bypass, 1, raw_len); + if (meta.is_e2i_dir == s_ctx->c2s_info.is_e2i_dir) + throughput_metrics_inc(&s_ctx->c2s_info.rx, 1, raw_len); + else + throughput_metrics_inc(&s_ctx->s2c_info.rx, 1, raw_len); + marsio_send_burst(handle->dev_nf_interface.mr_path, thread_seq, &rx_buff, 1); + return 0; + } + if (meta.is_decrypted) { throughput_metrics_inc(&packet_io_fs->decrypt_rx, 1, raw_len); @@ -1485,31 +1580,64 @@ static int handle_raw_packet_from_nf(struct packet_io *handle, marsio_buff_t *rx else { throughput_metrics_inc(&packet_io_fs->raw_pkt_rx, 1, raw_len); - if (meta.is_e2i_dir) - { - if (metadata_is_empty(s_ctx->raw_meta_e2i)) - { + if (meta.is_e2i_dir) { + if (metadata_is_empty(s_ctx->raw_meta_e2i)) { metadata_deep_copy(s_ctx->raw_meta_e2i, &meta); } s_ctx->raw_meta_e2i->sids = meta.sids; } - else - { - if (metadata_is_empty(s_ctx->raw_meta_i2e)) - { + else { + if (metadata_is_empty(s_ctx->raw_meta_i2e)) { metadata_deep_copy(s_ctx->raw_meta_i2e, &meta); } s_ctx->raw_meta_i2e->sids = meta.sids; } - // send to tap0 - add_ether_header(raw_data, packet_io->config.src_mac, packet_io->config.tap_mac); - if (packet_io->config.enable_iouring) { - io_uring_submit_write_entry(thread->tap_ctx->io_uring_fd, raw_data, raw_len); + + if (meta.is_e2i_dir == s_ctx->c2s_info.is_e2i_dir) { + header = s_ctx->c2s_info.header_data; + header_len = s_ctx->c2s_info.header_len; + is_ipv4 = s_ctx->c2s_info.is_ipv4; + throughput_metrics_inc(&s_ctx->c2s_info.rx, 1, raw_len); + } + else { + header = s_ctx->s2c_info.header_data; + header_len = s_ctx->s2c_info.header_len; + is_ipv4 = s_ctx->s2c_info.is_ipv4; + throughput_metrics_inc(&s_ctx->s2c_info.rx, 1, raw_len); + } + + if (header != NULL) { + char *packet_buff = NULL; + int packet_len = sizeof(struct ethhdr) + raw_len - header_len; + packet_buff = (char *)calloc(packet_len, sizeof(char)); + memcpy(packet_buff + sizeof(struct ethhdr), raw_data + header_len, raw_len - header_len); + add_ether_header(packet_buff, packet_io->config.src_mac, packet_io->config.tap_mac); + if (is_ipv4) + add_ether_proto(packet_buff, ETH_P_IP); + else + add_ether_proto(packet_buff, ETH_P_IPV6); + + if (packet_io->config.enable_iouring) { + io_uring_submit_write_entry(thread->tap_ctx->io_uring_fd, packet_buff, packet_len); + } + else { + tap_write(thread->tap_ctx->tap_fd, packet_buff, packet_len, logger); + } + throughput_metrics_inc(&packet_io_fs->tap_pkt_tx, 1, packet_len); + if (packet_buff) + free(packet_buff); } else { - tap_write(thread->tap_ctx->tap_fd, raw_data, raw_len, logger); + // send to tap0 + add_ether_header(raw_data, packet_io->config.src_mac, packet_io->config.tap_mac); + if (packet_io->config.enable_iouring) { + io_uring_submit_write_entry(thread->tap_ctx->io_uring_fd, raw_data, raw_len); + } + else { + tap_write(thread->tap_ctx->tap_fd, raw_data, raw_len, logger); + } + throughput_metrics_inc(&packet_io_fs->tap_pkt_tx, 1, raw_len); } - throughput_metrics_inc(&packet_io_fs->tap_pkt_tx, 1, raw_len); uint8_t flag = tfe_cmsg_get_flag(s_ctx->cmsg); if (flag & TFE_CMSG_FLAG_USER0) { @@ -1881,7 +2009,12 @@ void handle_raw_packet_from_tap(const char *data, int len, void *args) struct packet_io_fs *packet_io_fs = thread->ret_fs_state; struct addr_tuple4 inner_addr; struct raw_pkt_parser raw_parser; + struct metadata meta = {0}; void * logger = thread->logger; + char *dst = NULL; + char *header = NULL; + int header_len = 0; + int packet_len = 0; memset(&inner_addr, 0, sizeof(struct addr_tuple4)); raw_packet_parser_init(&raw_parser, 0, LAYER_TYPE_ALL, 8); @@ -1906,28 +2039,21 @@ void handle_raw_packet_from_tap(const char *data, int len, void *args) return; } - char *dst = marsio_buff_append(tx_buffs[0], len); - memcpy(dst, data, len); - - struct metadata meta = {0}; - meta.session_id = s_ctx->session_id; - meta.raw_data = dst; - meta.raw_len = len; - meta.is_decrypted = 0; - meta.is_ctrl_pkt = 0; - meta.l7offset = 0; - if (memcmp(&inner_addr, &s_ctx->c2s_info.tuple4, sizeof(struct addr_tuple4)) == 0) { meta.is_e2i_dir = s_ctx->c2s_info.is_e2i_dir; src_mac = s_ctx->client_mac; dst_mac = s_ctx->server_mac; + header = s_ctx->c2s_info.header_data; + header_len = s_ctx->c2s_info.header_len; } else { meta.is_e2i_dir = s_ctx->s2c_info.is_e2i_dir; src_mac = s_ctx->server_mac; dst_mac = s_ctx->client_mac; + header = s_ctx->s2c_info.header_data; + header_len = s_ctx->s2c_info.header_len; } if (meta.is_e2i_dir) @@ -1941,8 +2067,27 @@ void handle_raw_packet_from_tap(const char *data, int len, void *args) route_ctx_copy(&meta.route_ctx, &s_ctx->raw_meta_i2e->route_ctx); } + if (header != NULL) { + packet_len = len + header_len - sizeof(struct ethhdr); + dst = marsio_buff_append(tx_buffs[0], packet_len); + memcpy(dst, header, header_len); + memcpy(dst + header_len, data + sizeof(struct ethhdr), len - sizeof(struct ethhdr)); + } + else { + packet_len = len; + dst = marsio_buff_append(tx_buffs[0], len); + memcpy(dst, data, len); + } + + meta.session_id = s_ctx->session_id; + meta.raw_data = dst; + meta.raw_len = packet_len; + meta.is_decrypted = 0; + meta.is_ctrl_pkt = 0; + meta.l7offset = 0; + packet_io_set_metadata(tx_buffs[0], &meta, logger); add_ether_header(dst, src_mac, dst_mac); - throughput_metrics_inc(&packet_io_fs->raw_pkt_tx, 1, len); + throughput_metrics_inc(&packet_io_fs->raw_pkt_tx, 1, packet_len); marsio_send_burst(packet_io->dev_nf_interface.mr_path, thread->thread_index, tx_buffs, 1); } diff --git a/common/src/tfe_raw_packet.cpp b/common/src/tfe_raw_packet.cpp index 97d67a6..838cd73 100644 --- a/common/src/tfe_raw_packet.cpp +++ b/common/src/tfe_raw_packet.cpp @@ -399,6 +399,82 @@ uint64_t raw_packet_parser_get_hash_value(struct raw_pkt_parser *handler, enum l return hash_value; } +static const struct layer_result *raw_packet_parser_get_most_inner_layer(struct raw_pkt_parser *handler, enum layer_type layer_type) +{ + const struct layer_result *layer_result = NULL; + struct layer_results *results = &handler->results; + + for (int8_t i = results->layers_used - 1; i >= 0; i--) + { + const struct layer_result *layer = &results->layers[i]; + enum layer_type type = layer->type; + + // first get L4 layer + if (type & layer_type) + { + layer_result = layer; + break; + } + } + + if (layer_result == NULL) + return NULL; + + return layer_result; +} + +static const struct layer_result *raw_packet_parser_get_most_outer_layer(struct raw_pkt_parser *handler, enum layer_type layer_type) +{ + const struct layer_result *layer_result = NULL; + struct layer_results *results = &handler->results; + + for (int8_t i = 0; i <= results->layers_used - 1; i++) + { + const struct layer_result *layer = &results->layers[i]; + enum layer_type type = layer->type; + + // first get L4 layer + if (type & layer_type) + { + layer_result = layer; + break; + } + } + + if (layer_result == NULL) + return NULL; + + return layer_result; +} + +int raw_traffic_decapsulate(struct raw_pkt_parser *handler, char *raw_data, int raw_len, char **header, int *header_len, int *is_ipv4) +{ + const struct layer_result *l2_tun_layer_result = NULL; + const struct layer_result *l3_layer_result = NULL; + const struct layer_result *l4_layer_result = NULL; + + l4_layer_result = raw_packet_parser_get_most_inner_layer(handler, LAYER_TYPE_L4); + if (l4_layer_result == NULL) + return -1; + + if (l4_layer_result->type != LAYER_TYPE_TCP) + return -1; + + l3_layer_result = raw_packet_parser_get_most_inner_layer(handler, LAYER_TYPE_L3); + if (l3_layer_result == NULL) + return -1; + + *is_ipv4 = l3_layer_result->type == LAYER_TYPE_IPV4 ? 1 : 0; + l2_tun_layer_result = raw_packet_parser_get_most_outer_layer(handler, LAYER_TYPE_L2_TUN); + if (l2_tun_layer_result == NULL) + return -1; + + *header_len = l3_layer_result->offset; + *header = (char *)calloc(*header_len, sizeof(char)); + memcpy(*header, raw_data, *header_len); + return 0; +} + /****************************************************************************** * Private API ******************************************************************************/ |
