From f421e4df5403f977603ab22950f83baa7fc3cffd Mon Sep 17 00:00:00 2001 From: luwenpeng Date: Mon, 17 Apr 2023 18:26:33 +0800 Subject: [PATCH] =?UTF-8?q?TSG-14789=20TFE=E6=89=AB=E6=8F=8Fservice=20chai?= =?UTF-8?q?ning=E7=AD=96=E7=95=A5=EF=BC=8C=E6=89=A7=E8=A1=8CDecrypted=20Tr?= =?UTF-8?q?affic=20Steering?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 1 + common/include/tfe_cmsg.h | 1 + platform/CMakeLists.txt | 4 + platform/include/internal/proxy.h | 1 + platform/src/acceptor_kni_v3.cpp | 9 +- platform/src/proxy.cpp | 10 +- plugin/business/CMakeLists.txt | 1 + .../business/chaining-policy/CMakeLists.txt | 4 + .../chaining-policy/src/chaining_policy.cpp | 204 ++++++++++++++++++ .../chaining-policy/src/chaining_policy.h | 8 + resource/pangu/table_info.conf | 10 + 11 files changed, 249 insertions(+), 4 deletions(-) create mode 100644 plugin/business/chaining-policy/CMakeLists.txt create mode 100644 plugin/business/chaining-policy/src/chaining_policy.cpp create mode 100644 plugin/business/chaining-policy/src/chaining_policy.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c0d8a1..6c84e83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ option(ENABLE_PLUGIN_PANGU_HTTP "Enable Pangu-HTTP business" TRUE) option(ENABLE_PLUGIN_HTTP2 "Enable HTTP2 business" TRUE) option(ENABLE_PLUGIN_SSL_POLICY "Enable SSL policy support" TRUE) option(ENABLE_PLUGIN_TCP_POLICY "Enable TCP policy support" TRUE) +option(ENABLE_PLUGIN_CHAINING_POLICY "Enable Chaining policy support" TRUE) if(ENABLE_PIC) set(CMAKE_POSITION_INDEPENDENT_CODE 1) diff --git a/common/include/tfe_cmsg.h b/common/include/tfe_cmsg.h index 26273a7..ef226a1 100644 --- a/common/include/tfe_cmsg.h +++ b/common/include/tfe_cmsg.h @@ -72,6 +72,7 @@ enum tfe_cmsg_tlv_type TFE_CMSG_UPSTREAM_TCP_USER_TIMEOUT, TFE_CMSG_TCP_PASSTHROUGH, + TFE_CMSG_TCP_DECRYPTED_TRAFFIC_STEERING, /* Share tsg scan result */ TFE_CMSG_SRC_SUB_ID, // string max size 256 diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt index 6622586..d0c2b17 100644 --- a/platform/CMakeLists.txt +++ b/platform/CMakeLists.txt @@ -52,6 +52,10 @@ if(ENABLE_PLUGIN_TCP_POLICY) target_link_libraries(tfe -Wl,--whole-archive tcp-policy -Wl,--no-whole-archive) endif() +if(ENABLE_PLUGIN_CHAINING_POLICY) + target_link_libraries(tfe -Wl,--whole-archive chaining-policy -Wl,--no-whole-archive) +endif() + if(ENABLE_PLUGIN_TRAFFIC_MIRROR) target_link_libraries(tfe -Wl,--whole-archive traffic-mirror -Wl,--no-whole-archive) endif() diff --git a/platform/include/internal/proxy.h b/platform/include/internal/proxy.h index f45ba11..3e6c442 100644 --- a/platform/include/internal/proxy.h +++ b/platform/include/internal/proxy.h @@ -132,6 +132,7 @@ struct tfe_proxy struct ssl_mgr * ssl_mgr_handler; struct tcp_policy_enforcer *tcp_ply_enforcer; struct ssl_policy_enforcer *ssl_ply_enforcer; + struct chaining_policy_enforcer *chain_ply_enforcer; struct key_keeper * key_keeper_handler; unsigned int en_kni_v1_acceptor; diff --git a/platform/src/acceptor_kni_v3.cpp b/platform/src/acceptor_kni_v3.cpp index 004c2e8..b923f93 100644 --- a/platform/src/acceptor_kni_v3.cpp +++ b/platform/src/acceptor_kni_v3.cpp @@ -19,6 +19,7 @@ #define TCP_RESTORE_TCPOPT_KIND 88 extern void tcp_policy_enforce(struct tcp_policy_enforcer *enforcer, struct tfe_cmsg *cmsg, uint64_t rule_id); +extern void chaining_policy_enforce(struct chaining_policy_enforcer *enforcer, struct tfe_cmsg *cmsg, uint64_t rule_id); struct acceptor_kni_v3 { @@ -601,8 +602,10 @@ static int payload_handler_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, s struct pkt_info pktinfo; struct tcp_restore_info restore_info; uint8_t stream_protocol_in_char = 0; + uint8_t enalbe_decrypted_traffic_steering = 0; uint16_t size = 0; uint64_t rule_id = 0; + uint64_t chaining_rule_id = 0; // only use for acceptv4 struct acceptor_kni_v3 *__ctx = (struct acceptor_kni_v3 *)data; clock_gettime(CLOCK_MONOTONIC, &(__ctx->start)); memset(&pktinfo, 0, sizeof(pktinfo)); @@ -720,6 +723,7 @@ static int payload_handler_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, s goto end; } tcp_policy_enforce(__ctx->proxy->tcp_ply_enforcer, cmsg, rule_id); + chaining_policy_enforce(__ctx->proxy->chain_ply_enforcer, cmsg, chaining_rule_id); if (overwrite_tcp_mss(cmsg, &restore_info)) { @@ -745,9 +749,12 @@ static int payload_handler_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, s } tfe_cmsg_get_value(cmsg, TFE_CMSG_TCP_RESTORE_PROTOCOL, (unsigned char *)&stream_protocol_in_char, sizeof(stream_protocol_in_char), &size); + tfe_cmsg_get_value(cmsg, TFE_CMSG_TCP_DECRYPTED_TRAFFIC_STEERING, (unsigned char *)&enalbe_decrypted_traffic_steering, sizeof(enalbe_decrypted_traffic_steering), &size); + if (steering_device_is_available() && ( (STREAM_PROTO_PLAIN == (enum tfe_stream_proto)stream_protocol_in_char && __ctx->proxy->traffic_steering_options.enable_steering_http) || - (STREAM_PROTO_SSL == (enum tfe_stream_proto)stream_protocol_in_char && __ctx->proxy->traffic_steering_options.enable_steering_ssl))) + (STREAM_PROTO_SSL == (enum tfe_stream_proto)stream_protocol_in_char && __ctx->proxy->traffic_steering_options.enable_steering_ssl) || + enalbe_decrypted_traffic_steering == 1)) { if (fake_tcp_handshake(__ctx->proxy, &restore_info) == -1) { diff --git a/platform/src/proxy.cpp b/platform/src/proxy.cpp index 575bbbb..0e3e8df 100644 --- a/platform/src/proxy.cpp +++ b/platform/src/proxy.cpp @@ -58,10 +58,11 @@ /* Systemd */ #include -extern struct ssl_policy_enforcer* ssl_policy_enforcer_create(void* logger); -extern enum ssl_stream_action ssl_policy_enforce(struct ssl_stream *upstream, void* u_para); - extern struct tcp_policy_enforcer *tcp_policy_enforcer_create(void *logger); +extern struct chaining_policy_enforcer *chaining_policy_enforcer_create(void *logger); +extern struct ssl_policy_enforcer *ssl_policy_enforcer_create(void *logger); +extern enum ssl_stream_action ssl_policy_enforce(struct ssl_stream *upstream, void *u_para); + static int signals[] = {SIGHUP, SIGPIPE, SIGUSR1, SIGUSR2}; /* Global Resource */ @@ -703,6 +704,9 @@ int main(int argc, char * argv[]) g_default_proxy->ssl_ply_enforcer = ssl_policy_enforcer_create(g_default_logger); CHECK_OR_EXIT(g_default_proxy->ssl_ply_enforcer == NULL, "Failed at creating ssl policy enforcer. Exit."); + g_default_proxy->chain_ply_enforcer = chaining_policy_enforcer_create(g_default_logger); + CHECK_OR_EXIT(g_default_proxy->chain_ply_enforcer == NULL, "Failed at creating chaining policy enforcer. Exit."); + ssl_manager_set_new_upstream_cb(g_default_proxy->ssl_mgr_handler, ssl_policy_enforce, g_default_proxy->ssl_ply_enforcer); ret = tfe_proxy_work_thread_run(g_default_proxy); CHECK_OR_EXIT(ret == 0, "Failed at creating thread. Exit."); diff --git a/plugin/business/CMakeLists.txt b/plugin/business/CMakeLists.txt index 4e67d00..0cb4670 100644 --- a/plugin/business/CMakeLists.txt +++ b/plugin/business/CMakeLists.txt @@ -3,3 +3,4 @@ add_subdirectory(doh) add_subdirectory(tsg-http) add_subdirectory(ssl-policy) add_subdirectory(tcp-policy) +add_subdirectory(chaining-policy) \ No newline at end of file diff --git a/plugin/business/chaining-policy/CMakeLists.txt b/plugin/business/chaining-policy/CMakeLists.txt new file mode 100644 index 0000000..cee66ac --- /dev/null +++ b/plugin/business/chaining-policy/CMakeLists.txt @@ -0,0 +1,4 @@ +add_library(chaining-policy src/chaining_policy.cpp) +target_link_libraries(chaining-policy PUBLIC common) +target_link_libraries(chaining-policy PUBLIC cjson) +target_link_libraries(chaining-policy PUBLIC maatframe) \ No newline at end of file diff --git a/plugin/business/chaining-policy/src/chaining_policy.cpp b/plugin/business/chaining-policy/src/chaining_policy.cpp new file mode 100644 index 0000000..8405d99 --- /dev/null +++ b/plugin/business/chaining-policy/src/chaining_policy.cpp @@ -0,0 +1,204 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "chaining_policy.h" + +enum traffic_type +{ + TRAFFIC_TYPE_NONE = 0, + TRAFFIC_TYPE_RAW = 1, + TRAFFIC_TYPE_DECRYPTED = 2, +}; + +struct chaining_param +{ + uint64_t rule_id; + int ref_cnt; + enum traffic_type type; +}; + +struct chaining_policy_enforcer +{ + struct maat *maat; + int table_id; + void *logger; +}; + +static void chaining_param_new_cb(const char *table_name, int table_id, const char *key, const char *table_line, void **ad, long argl, void *argp) +{ + cJSON *json = NULL; + cJSON *item = NULL; + cJSON *element = NULL; + size_t user_region_offset = 0; + size_t user_region_len = 0; + struct chaining_param *param = NULL; + struct chaining_policy_enforcer *enforcer = (struct chaining_policy_enforcer *)argp; + + if (maat_helper_read_column(table_line, 7, &user_region_offset, &user_region_len) < 0) + { + TFE_LOG_ERROR(enforcer->logger, "unexpected chaining rule: (invalid user region) %s", table_line); + return; + } + + char *json_str = (char *)calloc(user_region_len + 1, sizeof(char)); + memcpy(json_str, table_line + user_region_offset, user_region_len); + json = cJSON_Parse(json_str); + if (json == NULL) + { + TFE_LOG_ERROR(enforcer->logger, "unexpected chaining rule: (invalid json format) %s", table_line); + goto error_out; + } + + param = (struct chaining_param *)calloc(1, sizeof(struct chaining_param)); + param->rule_id = atoll(key); + param->ref_cnt = 1; + + item = cJSON_GetObjectItem(json, "targeted_traffic"); + if (!item || !cJSON_IsString(item)) + { + TFE_LOG_ERROR(enforcer->logger, "unexpected chaining rule: (invalid targeted_traffic param) %s", table_line); + goto error_out; + } + if (strcasecmp(item->valuestring, "raw") == 0) + { + param->type = TRAFFIC_TYPE_RAW; + } + else if (strcasecmp(item->valuestring, "decrypted") == 0) + { + param->type = TRAFFIC_TYPE_DECRYPTED; + } + else + { + TFE_LOG_ERROR(enforcer->logger, "unexpected chaining rule: (invalid targeted_traffic param) %s", table_line); + goto error_out; + } + + *ad = param; + TFE_LOG_INFO(enforcer->logger, "Add chaining rule: %lu", param->rule_id); + + cJSON_Delete(json); + free(json_str); + return; + +error_out: + if (json) + { + cJSON_Delete(json); + json = NULL; + } + + if (json_str) + { + free(json_str); + json_str = NULL; + } + + if (param) + { + free(param); + param = NULL; + } +} + +static void chaining_param_free_cb(int table_id, void **ad, long argl, void *argp) +{ + struct chaining_policy_enforcer *enforcer = (struct chaining_policy_enforcer *)argp; + struct chaining_param *param = (struct chaining_param *)*ad; + if (param == NULL) + { + return; + } + + if ((__sync_sub_and_fetch(¶m->ref_cnt, 1) == 0)) + { + TFE_LOG_INFO(enforcer->logger, "Del chaining policy %lu", param->rule_id); + free(param); + *ad = NULL; + } +} + +static void chaining_param_free(struct chaining_param *param) +{ + chaining_param_free_cb(0, (void **)¶m, 0, NULL); +} + +static void chaining_param_dup_cb(int table_id, void **to, void **from, long argl, void *argp) +{ + struct chaining_param *param = (struct chaining_param *)*from; + if (param) + { + __sync_add_and_fetch(&(param->ref_cnt), 1); + *to = param; + } + else + { + *to = NULL; + } +} + +struct chaining_policy_enforcer *chaining_policy_enforcer_create(void *logger) +{ + int ret = 0; + struct chaining_policy_enforcer *enforcer = ALLOC(struct chaining_policy_enforcer, 1); + enforcer->maat = (struct maat *)tfe_bussiness_resouce_get(STATIC_MAAT); + enforcer->logger = logger; + enforcer->table_id = maat_get_table_id(enforcer->maat, "SERVICE_CHAINING_COMPILE"); + if (enforcer->table_id < 0) + { + TFE_LOG_ERROR(enforcer->logger, "failed at register table of SERVICE_CHAINING_COMPILE, ret = %d", enforcer->table_id); + goto error_out; + } + + ret = maat_plugin_table_ex_schema_register(enforcer->maat, "SERVICE_CHAINING_COMPILE", + chaining_param_new_cb, + chaining_param_free_cb, + chaining_param_dup_cb, + 0, enforcer); + if (ret < 0) + { + TFE_LOG_ERROR(enforcer->logger, "failed at register callback of SERVICE_CHAINING_COMPILE, ret = %d", ret); + goto error_out; + } + return enforcer; + +error_out: + chaining_policy_enforcer_destory(enforcer); + return NULL; +} + +void chaining_policy_enforcer_destory(struct chaining_policy_enforcer *enforcer) +{ + if (enforcer) + { + free(enforcer); + enforcer = NULL; + } +} + +void chaining_policy_enforce(struct chaining_policy_enforcer *enforcer, struct tfe_cmsg *cmsg, uint64_t rule_id) +{ + char rule_id_str[16] = {0}; + uint8_t enalbe_decrypted_traffic_steering = 0; + + snprintf(rule_id_str, sizeof(rule_id_str), "%lu", rule_id); + struct chaining_param *param = (struct chaining_param *)maat_plugin_table_get_ex_data(enforcer->maat, enforcer->table_id, rule_id_str); + if (param == NULL) + { + TFE_LOG_INFO(enforcer->logger, "Failed to get chaining parameter of policy %lu.", rule_id); + tfe_cmsg_set(cmsg, TFE_CMSG_TCP_DECRYPTED_TRAFFIC_STEERING, (unsigned char *)&enalbe_decrypted_traffic_steering, sizeof(enalbe_decrypted_traffic_steering)); + return; + } + + if (param->type == TRAFFIC_TYPE_DECRYPTED) + { + enalbe_decrypted_traffic_steering = 1; + } + + tfe_cmsg_set(cmsg, TFE_CMSG_TCP_DECRYPTED_TRAFFIC_STEERING, (unsigned char *)&enalbe_decrypted_traffic_steering, sizeof(enalbe_decrypted_traffic_steering)); + chaining_param_free(param); +} \ No newline at end of file diff --git a/plugin/business/chaining-policy/src/chaining_policy.h b/plugin/business/chaining-policy/src/chaining_policy.h new file mode 100644 index 0000000..0fcbe81 --- /dev/null +++ b/plugin/business/chaining-policy/src/chaining_policy.h @@ -0,0 +1,8 @@ +#pragma once +#include +#include + +struct chaining_policy_enforcer; +struct chaining_policy_enforcer *chaining_policy_enforcer_create(void *logger); +void chaining_policy_enforcer_destory(struct chaining_policy_enforcer *enforcer); +void chaining_policy_enforce(struct chaining_policy_enforcer *enforcer, struct tfe_cmsg *cmsg, uint64_t rule_id); \ No newline at end of file diff --git a/resource/pangu/table_info.conf b/resource/pangu/table_info.conf index 65b34d4..cf29160 100644 --- a/resource/pangu/table_info.conf +++ b/resource/pangu/table_info.conf @@ -454,5 +454,15 @@ "key":1, "key_type":"pointer" } + }, + { + "table_id":44, + "table_name":"SERVICE_CHAINING_COMPILE", + "table_type":"plugin", + "valid_column":8, + "custom":{ + "key":1, + "key_type":"pointer" + } } ] \ No newline at end of file