feature(adapt maat): PXY_SSL_FINGERPRINT adapt uuid

This commit is contained in:
luwenpeng
2024-09-25 10:46:57 +08:00
parent d93edf9880
commit 4ef367ac41
7 changed files with 151 additions and 121 deletions

View File

@@ -9,6 +9,7 @@
#include <time.h> #include <time.h>
#include <dirent.h> //scan_dir #include <dirent.h> //scan_dir
#include <stdbool.h> #include <stdbool.h>
#include <uuid/uuid.h>
#include "kafka.h" #include "kafka.h"
#define LOG_TAG_CTRLPKT "CTRL_PACKET" #define LOG_TAG_CTRLPKT "CTRL_PACKET"
@@ -22,6 +23,8 @@
#define TFE_FAKE_C_DEFAULT_TTL 60 #define TFE_FAKE_C_DEFAULT_TTL 60
#define TFE_FAKE_S_DEFAULT_TTL 65 #define TFE_FAKE_S_DEFAULT_TTL 65
#define UUID_STRING_SIZE 37
#ifndef TFE_CONFIG_BACKLOG_DEFAULT #ifndef TFE_CONFIG_BACKLOG_DEFAULT
#define TFE_CONFIG_BACKLOG_DEFAULT 20 #define TFE_CONFIG_BACKLOG_DEFAULT 20
#endif #endif

View File

@@ -61,7 +61,6 @@ timeout_debug=0
[ssl] [ssl]
ssl_debug=0 ssl_debug=0
ssl_ja3_table=PXY_SSL_FINGERPRINT
# ssl version Not available, configured via TSG website # ssl version Not available, configured via TSG website
# ssl_max_version=tls13 # ssl_max_version=tls13
# ssl_min_version=ssl3 # ssl_min_version=ssl3

View File

@@ -39,7 +39,7 @@ struct ssl_service_cache
unsigned int fail_as_proto_err_count; unsigned int fail_as_proto_err_count;
unsigned int fail_time_window; unsigned int fail_time_window;
}; };
struct ssl_service_cache* ssl_service_cache_create(unsigned int slot_size, unsigned int expire_seconds, int fail_as_pinning_cnt, int fail_as_proto_err_cnt, int fail_time_win, char *ja3_table_name); struct ssl_service_cache* ssl_service_cache_create(unsigned int slot_size, unsigned int expire_seconds, int fail_as_pinning_cnt, int fail_as_proto_err_cnt, int fail_time_win);
void ssl_service_cache_destroy(struct ssl_service_cache* cache); void ssl_service_cache_destroy(struct ssl_service_cache* cache);
int ssl_service_cache_read(struct ssl_service_cache *svc_cache, const struct ssl_chello *chello, const struct tfe_stream *tcp_stream, struct ssl_service_status *result); int ssl_service_cache_read(struct ssl_service_cache *svc_cache, const struct ssl_chello *chello, const struct tfe_stream *tcp_stream, struct ssl_service_status *result);

View File

@@ -5,11 +5,10 @@
struct ssl_svc_ja3 struct ssl_svc_ja3
{ {
char ja3_hash[33]; uuid_t uuid;
int fingerprint_id; char ja3_hash[33];
int pinning_state; int pinning_state;
int is_valid; int ref_cnt;
int ref_cnt;
}; };
struct ssl_svc_addr struct ssl_svc_addr
@@ -20,135 +19,168 @@ struct ssl_svc_addr
const char *dport; const char *dport;
}; };
static int table_id = 0; static void ssl_svc_ja3_param_dup_cb(const char *table_name, void **to, void **from, long argl, void *argp)
static void ssl_svc_ja3_param_dup_cb(int table_id, void **to, void **from, long argl, void *argp)
{ {
struct ssl_svc_ja3 *param = (struct ssl_svc_ja3 *)*from; struct ssl_svc_ja3 *param = (struct ssl_svc_ja3 *)*from;
if (param) if (param)
{ {
__sync_add_and_fetch(&(param->ref_cnt), 1); __sync_add_and_fetch(&(param->ref_cnt), 1);
*to = param; *to = param;
} }
else else
{ {
*to = NULL; *to = NULL;
} }
return; return;
} }
static void ssl_svc_ja3_param_new_cb(const char *table_name, int table_id, const char *key, const char *table_line, void **ad, long argl, void *argp) // NOTE: key is ja3_hash
static void ssl_svc_ja3_param_new_cb(const char *table_name, const char *key, const char *table_line, void **ad, long argl, void *argp)
{ {
int is_valid = 0; cJSON *json = NULL;
int pinning_state = 0; cJSON *item = NULL;
int fingerprint_id = 0; struct ssl_svc_ja3 *param = NULL;
char ja3_hash[33] = {0};
if (sscanf(table_line, "%d\t%s\t%d\t%d", &fingerprint_id, ja3_hash, &pinning_state, &is_valid) != 4) char *json_str = strdup(table_line);
{ json = cJSON_Parse(json_str);
TFE_LOG_ERROR(g_default_logger, "Invalid JA3 policy: %s", table_line); if (json == NULL)
return; {
} TFE_LOG_ERROR(g_default_logger, "Invalid JA3 policy: (invalid json format) %s", table_line);
goto error_out;
}
struct ssl_svc_ja3 *param = ALLOC(struct ssl_svc_ja3, 1); param = ALLOC(struct ssl_svc_ja3, 1);
param->fingerprint_id = fingerprint_id; param->ref_cnt = 1;
memcpy(param->ja3_hash, ja3_hash, 32);
param->pinning_state = pinning_state;
param->is_valid = is_valid;
param->ref_cnt = 1;
*ad = param; // uuid
TFE_LOG_INFO(g_default_logger, "Add JA3 policy: id:%d, ja3_hash:%s, pinning_state:%d, is_valid:%d, ref_cnt:%d", item = cJSON_GetObjectItem(json, "uuid");
param->fingerprint_id, param->ja3_hash, param->pinning_state, param->is_valid, param->ref_cnt); if (!item || !cJSON_IsString(item))
{
TFE_LOG_ERROR(g_default_logger, "Invalid JA3 policy: (invalid uuid param) %s", table_line);
goto error_out;
}
uuid_parse(item->valuestring, param->uuid);
// ja3_hash
item = cJSON_GetObjectItem(json, "ja3_hash");
if (!item || !cJSON_IsString(item))
{
TFE_LOG_ERROR(g_default_logger, "Invalid JA3 policy: (invalid ja3_hash param) %s", table_line);
goto error_out;
}
strncpy(param->ja3_hash, item->valuestring, 32);
// pinning_state
item = cJSON_GetObjectItem(json, "pinning_state");
if (!item || !cJSON_IsNumber(item))
{
TFE_LOG_ERROR(g_default_logger, "Invalid JA3 policy: (invalid pinning_state param) %s", table_line);
goto error_out;
}
param->pinning_state = item->valueint;
*ad = param;
TFE_LOG_INFO(g_default_logger, "Add JA3 policy: uuid:%s, ja3_hash:%s, pinning_state:%d",
key, param->ja3_hash, param->pinning_state);
cJSON_Delete(json);
free(json_str);
return;
error_out:
if (json)
{
cJSON_Delete(json);
}
if (json_str)
{
free(json_str);
}
if (param)
{
free(param);
}
*ad = NULL;
return;
} }
static void ssl_svc_ja3_param_free_cb(int table_id, void **ad, long argl, void *argp) static void ssl_svc_ja3_param_free_cb(const char *table_name, void **ad, long argl, void *argp)
{ {
struct ssl_svc_ja3 *param = (struct ssl_svc_ja3 *)*ad; struct ssl_svc_ja3 *param = (struct ssl_svc_ja3 *)*ad;
if (param == NULL) if (param == NULL)
{ {
return; return;
} }
if ((__sync_sub_and_fetch(&param->ref_cnt, 1) == 0)) if ((__sync_sub_and_fetch(&param->ref_cnt, 1) == 0))
{ {
TFE_LOG_INFO(g_default_logger, "Del JA3 policy: id:%d, ja3_hash:%s, pinning_state:%d, is_valid:%d, ref_cnt:%d", char uuid_str[UUID_STRING_SIZE] = {0};
param->fingerprint_id, param->ja3_hash, param->pinning_state, param->is_valid, param->ref_cnt); uuid_unparse(param->uuid, uuid_str);
free(param); TFE_LOG_INFO(g_default_logger, "Del JA3 policy: id:%s", uuid_str);
*ad = NULL; free(param);
} *ad = NULL;
}
} }
static void ssl_svc_ja3_param_free(struct ssl_svc_ja3 *param) static void ssl_svc_ja3_param_free(struct ssl_svc_ja3 *param)
{ {
ssl_svc_ja3_param_free_cb(0, (void **)&param, 0, NULL); ssl_svc_ja3_param_free_cb(NULL, (void **)&param, 0, NULL);
return;
} }
static int ssl_svc_ja3_init(const char *table_name) static int ssl_svc_ja3_init()
{ {
table_id = maat_get_table_id(tfe_get_maat_handle(), table_name); if (maat_plugin_table_ex_schema_register(tfe_get_maat_handle(),
if (table_id < 0) "PXY_SSL_FINGERPRINT",
{ ssl_svc_ja3_param_new_cb,
TFE_LOG_ERROR(g_default_logger, "Maat table %s register failed.", table_name); ssl_svc_ja3_param_free_cb,
return 0; ssl_svc_ja3_param_dup_cb,
} 0,
int ret = maat_plugin_table_ex_schema_register(tfe_get_maat_handle(), NULL) != 0)
table_name, {
ssl_svc_ja3_param_new_cb, TFE_LOG_ERROR(g_default_logger, "failed at Maat_plugin_EX_register(PXY_SSL_FINGERPRINT)");
ssl_svc_ja3_param_free_cb, return -1
ssl_svc_ja3_param_dup_cb, }
0, else
NULL); {
if (ret < 0) return 0;
{ }
TFE_LOG_ERROR(g_default_logger, "failed at Maat_plugin_EX_register(%s), table_id = %d, ret = %d",
table_name, table_id, ret);
return 0;
}
return 1;
} }
enum ssl_ja3_pinning_status ssl_svc_ja3_scan(char *ja3_hash, const char *addr_str) enum ssl_ja3_pinning_status ssl_svc_ja3_scan(char *ja3_hash, const char *addr_str)
{ {
enum ssl_ja3_pinning_status ret = JA3_PINNING_STATUS_UNKNOWN; enum ssl_ja3_pinning_status ret = JA3_PINNING_STATUS_UNKNOWN;
struct ssl_svc_ja3 *param = NULL; struct ssl_svc_ja3 *param = NULL;
char uuid_str[UUID_STRING_SIZE] = {0};
param = (struct ssl_svc_ja3 *)maat_plugin_table_get_ex_data(tfe_get_maat_handle(), table_id, ja3_hash, strlen(ja3_hash)); param = (struct ssl_svc_ja3 *)maat_plugin_table_get_ex_data(tfe_get_maat_handle(), "PXY_SSL_FINGERPRINT", ja3_hash, strlen(ja3_hash));
if (param == NULL) if (param == NULL)
{ {
ret = JA3_PINNING_STATUS_UNKNOWN; ret = JA3_PINNING_STATUS_UNKNOWN;
goto end; goto end;
} }
TFE_LOG_INFO(g_default_logger, "Hit JA3 policy: id:%d, ja3_hash:%s, pinning_state:%d, is_valid:%d, ref_cnt:%d, addr:%s", uuid_unparse(param->uuid, uuid_str);
param->fingerprint_id, param->ja3_hash, param->pinning_state, param->is_valid, param->ref_cnt, addr_str); TFE_LOG_INFO(g_default_logger, "Hit JA3 policy: uuid:%s, ja3_hash:%s, pinning_state:%d, addr:%s",
uuid_str, param->ja3_hash, param->pinning_state, addr_str);
if (!param->is_valid)
{
ret = JA3_PINNING_STATUS_UNKNOWN;
goto end;
}
// 1 - pinning // 1 - pinning
if (param->pinning_state) if (param->pinning_state)
{
ret = JA3_PINNING_STATUS_IS_PINNING;
}
// 0 - not pinning
else
{ {
ret = JA3_PINNING_STATUS_NOT_PINNING; ret = JA3_PINNING_STATUS_IS_PINNING;
} }
// 0 - not pinning
else
{
ret = JA3_PINNING_STATUS_NOT_PINNING;
}
end: end:
if (param) if (param)
{ {
ssl_svc_ja3_param_free(param); ssl_svc_ja3_param_free(param);
param = NULL; param = NULL;
} }
return ret; return ret;
} }
struct ssl_svc_client_st struct ssl_svc_client_st
@@ -510,10 +542,9 @@ void ssl_service_cache_write(struct ssl_service_cache *svc_cache, const struct s
free(addr_str); free(addr_str);
} }
struct ssl_service_cache *ssl_service_cache_create(unsigned int slot_size, unsigned int expire_seconds, int fail_as_pinning_cnt, int fail_as_proto_err_cnt, int fail_time_win struct ssl_service_cache *ssl_service_cache_create(unsigned int slot_size, unsigned int expire_seconds, int fail_as_pinning_cnt, int fail_as_proto_err_cnt, int fail_time_win)
, char *ja3_table_name)
{ {
if (ssl_svc_ja3_init(ja3_table_name) == 0) if (ssl_svc_ja3_init() != 0)
{ {
return NULL; return NULL;
} }

View File

@@ -631,7 +631,6 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section
struct ssl_mgr * mgr = ALLOC(struct ssl_mgr, 1); struct ssl_mgr * mgr = ALLOC(struct ssl_mgr, 1);
int ret = 0; int ret = 0;
char ja3_table_name[TFE_STRING_MAX] = {0};
char version_str[TFE_SYMBOL_MAX] = {}; char version_str[TFE_SYMBOL_MAX] = {};
mgr->logger = logger; mgr->logger = logger;
mgr->ev_base_gc=ev_base_gc; mgr->ev_base_gc=ev_base_gc;
@@ -711,11 +710,10 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section
MESA_load_profile_uint_def(ini_profile, section, "service_cache_fail_time_window", MESA_load_profile_uint_def(ini_profile, section, "service_cache_fail_time_window",
&(mgr->svc_cnt_time_window), 30); &(mgr->svc_cnt_time_window), 30);
MESA_load_profile_string_def(ini_profile, section, "ssl_ja3_table", ja3_table_name, sizeof(ja3_table_name), "PXY_SSL_FINGERPRINT"); mgr->svc_cache = ssl_service_cache_create(mgr->svc_cache_slots, mgr->svc_expire_seconds,
mgr->svc_cache=ssl_service_cache_create(mgr->svc_cache_slots, mgr->svc_expire_seconds, mgr->svc_fail_as_pinning_cnt,
mgr->svc_fail_as_pinning_cnt, mgr->svc_fail_as_proto_err_cnt,
mgr->svc_fail_as_proto_err_cnt, mgr->svc_cnt_time_window);
mgr->svc_cnt_time_window, ja3_table_name);
if (mgr->svc_cache == NULL) if (mgr->svc_cache == NULL)
{ {
TFE_LOG_ERROR(logger, "Failed to create service cache"); TFE_LOG_ERROR(logger, "Failed to create service cache");

View File

@@ -275,9 +275,9 @@
{ {
"table_name": "PXY_SSL_FINGERPRINT", "table_name": "PXY_SSL_FINGERPRINT",
"table_content": [ "table_content": [
"1\t599f223c2c9ee5702f5762913889dc21\t0\t1", "{\"uuid\":\"JA300000-0000-0000-0000-000000000001\",\"ja3_hash\":\"599f223c2c9ee5702f5762913889dc21\",\"pinning_state\":1,\"is_valid\":1}",
"2\teb149984fc9c44d85ed7f12c90d818be\t1\t0", "{\"uuid\":\"JA300000-0000-0000-0000-000000000002\",\"ja3_hash\":\"eb149984fc9c44d85ed7f12c90d818be\",\"pinning_state\":1,\"is_valid\":1}",
"3\te6573e91e6eb777c0933c5b8f97f10cd\t1\t1" "{\"uuid\":\"JA300000-0000-0000-0000-000000000003\",\"ja3_hash\":\"e6573e91e6eb777c0933c5b8f97f10cd\",\"pinning_state\":1,\"is_valid\":1}"
] ]
}, },
{ {

View File

@@ -372,10 +372,9 @@
"table_id":34, "table_id":34,
"table_name":"PXY_SSL_FINGERPRINT", "table_name":"PXY_SSL_FINGERPRINT",
"table_type":"plugin", "table_type":"plugin",
"valid_column":4,
"custom": { "custom": {
"key":2, "key_type":"pointer",
"key_type":"pointer" "key_name":"ja3_hash"
} }
}, },
{ {