399 lines
11 KiB
C++
399 lines
11 KiB
C++
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include "mesa_sts.h"
|
|
#include "cJSON.h"
|
|
#include "stellar/stellar.h"
|
|
#include "stellar/session.h"
|
|
#include "stellar/stellar_mq.h"
|
|
#include "stellar/stellar_exdata.h"
|
|
#include "stellar/log.h"
|
|
|
|
#include "session_flags_internal.h"
|
|
|
|
#define _MAX_STR_LEN 64
|
|
|
|
#define UNUSED(x) (void)(x)
|
|
|
|
const char *CFG_FILE_PATH="./etc/session_flags/session_flags.toml";
|
|
|
|
uint32_t sts_random_switch = 0;
|
|
|
|
struct session_flags_init_conf g_sf_conf;
|
|
|
|
static const char* random_looking_judge_table[] = {
|
|
"frequency",
|
|
"block_frequency",
|
|
"cumulative_sums",
|
|
"runs",
|
|
"longest_run",
|
|
"rank",
|
|
"non_overlapping_template_matching",
|
|
"overlapping_template_matching",
|
|
"universal",
|
|
"random_excursions",
|
|
"random_excursions_variant",
|
|
"poker_detect",
|
|
"runs_distribution",
|
|
"self_correlation",
|
|
"binary_derivative"
|
|
};
|
|
|
|
static void session_flags_topic_free_cb(void *msg, void *msg_free_arg)
|
|
{
|
|
UNUSED(msg_free_arg);
|
|
struct session_flags_message *flags = (struct session_flags_message *)msg;
|
|
|
|
if (flags)
|
|
{
|
|
if (flags->packet_sequence_array)
|
|
{
|
|
free(flags->packet_sequence_array);
|
|
}
|
|
free(flags);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void session_flags_exdata_free_cb(int idx, void *ex_ptr, void *arg)
|
|
{
|
|
UNUSED(idx);
|
|
UNUSED(arg);
|
|
|
|
if (ex_ptr == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
free(ex_ptr);
|
|
}
|
|
|
|
void session_flags_entry(struct session *session, int topic_id, const void *msg, void *per_session_ctx, void *plugin_env)
|
|
{
|
|
UNUSED(per_session_ctx);
|
|
if (msg == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const struct packet *pkt = (const struct packet *)msg;
|
|
struct session_flags_plugin_info *sf_plugin_info = (struct session_flags_plugin_info *)plugin_env;
|
|
struct session_flags_ctx *ctx = (struct session_flags_ctx *)session_exdata_get(session, sf_plugin_info->sess_ctx_exdata_idx);
|
|
|
|
if (ctx == NULL)
|
|
{
|
|
ctx = (struct session_flags_ctx *)calloc(1, sizeof(struct session_flags_ctx));
|
|
session_exdata_set(session, sf_plugin_info->sess_ctx_exdata_idx, ctx);
|
|
|
|
session_flags_stat_init(&ctx->stat, session_get_direction(session));
|
|
}
|
|
|
|
struct session_flags_stat *stat = &ctx->stat;
|
|
session_flags_result *flags_result = NULL;
|
|
size_t pktlen = 0;
|
|
|
|
pktlen = packet_get_raw_len(pkt);
|
|
|
|
uint64_t curr_time_ms = 0;
|
|
const struct timeval *tv;
|
|
|
|
tv = packet_get_timeval(pkt);
|
|
if (tv != NULL)
|
|
{
|
|
curr_time_ms = tv->tv_sec * 1000 + tv->tv_usec / 1000;
|
|
}
|
|
|
|
flags_result = session_flags(sf_plugin_info, ctx, session, topic_id, pktlen, session_get_flow_type(session), curr_time_ms);
|
|
|
|
if ((stat->stream_live_time_ms > g_sf_conf.session_max_process_time_ms))
|
|
{
|
|
stellar_session_plugin_dettach_current_session(session);
|
|
}
|
|
|
|
uint32_t pkts_num = stat->c2s.pkts + stat->s2c.pkts;
|
|
|
|
if (flags_result != NULL)
|
|
{
|
|
if (flags_result->flags != ctx->history_flags)
|
|
{
|
|
struct session_flags_message *flags_msg = session_flags_generate_firewall_message(flags_result->flags, flags_result->identify);
|
|
if (session_mq_publish_message(session, sf_plugin_info->session_flags_topic_id, flags_msg) < 0)
|
|
{
|
|
session_flags_topic_free_cb(flags_msg, NULL);
|
|
|
|
STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "[%s] publish session flags message failed, flags:0x%x, pkts_num:%d", session_get_readable_addr(session), flags_result->flags, pkts_num);
|
|
return;
|
|
}
|
|
|
|
ctx->history_flags = flags_result->flags;
|
|
|
|
STELLAR_LOG_DEBUG(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE,
|
|
"[%s] flags:0x%x, pkts_num:%d\n \
|
|
c2s_iter: bulky: %f, CBR: %f, download: %f, interactive: %f, pseudo_unidirectional: %f, streaming: %f, CBR_CV: %f\n \
|
|
s2c_iter: bulky: %f, CBR: %f, download: %f, interactive: %f, pseudo_unidirectional: %f, streaming: %f, CBR_CV: %f\n \
|
|
iter_cnt: %d, bidirectional: %f\n", session_get_readable_addr(session), ctx->history_flags, pkts_num,
|
|
stat->iter.c2s.bulky, stat->iter.c2s.CBR, stat->iter.c2s.download, stat->iter.c2s.interactive, stat->iter.c2s.pseudo_unidirectional, stat->iter.c2s.streaming, session_flags_calculate_CV(&stat->iter.c2s.omean),
|
|
stat->iter.s2c.bulky, stat->iter.s2c.CBR, stat->iter.s2c.download, stat->iter.s2c.interactive, stat->iter.s2c.pseudo_unidirectional, stat->iter.s2c.streaming, session_flags_calculate_CV(&stat->iter.s2c.omean),
|
|
stat->iter.iter_cnt, stat->iter.bidirectional);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void session_flags_load_config(struct session_flags_plugin_info *sf_plugin_info, const char *cfg_file, struct session_flags_init_conf *g_sf_conf)
|
|
{
|
|
char errbuf[256] = {0};
|
|
|
|
FILE *fp = fopen(cfg_file, "r");
|
|
if (NULL == fp)
|
|
{
|
|
STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "Can't open config file:%s", cfg_file);
|
|
return;
|
|
}
|
|
|
|
toml_table_t *toml_root = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
|
fclose(fp);
|
|
|
|
toml_table_t *cfg_tbl = toml_table_in(toml_root, "SESSION_FLAGS");
|
|
if (NULL == cfg_tbl)
|
|
{
|
|
STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "config file:%s has no key: [SESSION_FLAGS]", cfg_file);
|
|
toml_free(toml_root);
|
|
return;
|
|
}
|
|
|
|
toml_datum_t toml_val = toml_int_in(cfg_tbl, "INTERACTIVE_STARTTIME_MS");
|
|
if (toml_val.ok)
|
|
{
|
|
g_sf_conf->interactive_starttime_ms = toml_val.u.i;
|
|
}
|
|
else
|
|
{
|
|
g_sf_conf->interactive_starttime_ms = 15000;
|
|
}
|
|
|
|
toml_val = toml_int_in(cfg_tbl, "INTERACTIVE_PULSE_NUM");
|
|
if (toml_val.ok)
|
|
{
|
|
g_sf_conf->interactive_pulse_num = toml_val.u.i;
|
|
}
|
|
else
|
|
{
|
|
g_sf_conf->interactive_pulse_num = 4;
|
|
}
|
|
|
|
toml_val = toml_int_in(cfg_tbl, "INTERACTIVE_LATENCY_MS");
|
|
if (toml_val.ok)
|
|
{
|
|
g_sf_conf->interactive_latency_ms = toml_val.u.i;
|
|
}
|
|
else
|
|
{
|
|
g_sf_conf->interactive_latency_ms = 1000;
|
|
}
|
|
|
|
toml_val = toml_int_in(cfg_tbl, "MAIN_DIR_FRONT_N_PKTS");
|
|
if (toml_val.ok)
|
|
{
|
|
g_sf_conf->main_dir_front_n_pkts = toml_val.u.i;
|
|
}
|
|
else
|
|
{
|
|
g_sf_conf->main_dir_front_n_pkts = 100;
|
|
}
|
|
|
|
toml_val = toml_int_in(cfg_tbl, "LARGE_PKTS_INIT_SIZE");
|
|
if (toml_val.ok)
|
|
{
|
|
g_sf_conf->large_ptks_init_size = toml_val.u.i;
|
|
}
|
|
else
|
|
{
|
|
g_sf_conf->large_ptks_init_size = 1000;
|
|
}
|
|
|
|
toml_val = toml_int_in(cfg_tbl, "SESSION_MAX_PROCESS_TIME_MS");
|
|
if (toml_val.ok)
|
|
{
|
|
g_sf_conf->session_max_process_time_ms = toml_val.u.i;
|
|
}
|
|
else
|
|
{
|
|
g_sf_conf->session_max_process_time_ms = 30000;
|
|
}
|
|
|
|
toml_val = toml_int_in(cfg_tbl, "FET_ENABLED");
|
|
if (toml_val.ok)
|
|
{
|
|
g_sf_conf->fet_enabled = toml_val.u.b;
|
|
}
|
|
else
|
|
{
|
|
g_sf_conf->fet_enabled = 1;
|
|
}
|
|
|
|
toml_val = toml_int_in(cfg_tbl, "RANDOM_LOOKING_UDP_IGNORE_PKTS");
|
|
if (toml_val.ok)
|
|
{
|
|
g_sf_conf->random_looking_udp_ignore_pkts = toml_val.u.i;
|
|
}
|
|
else
|
|
{
|
|
g_sf_conf->random_looking_udp_ignore_pkts = 3;
|
|
}
|
|
|
|
toml_val = toml_int_in(cfg_tbl, "TUNNELING_TLS_IGNORE_PKTS");
|
|
if (toml_val.ok)
|
|
{
|
|
g_sf_conf->tunneling_tls_ignore_pkts = toml_val.u.i;
|
|
}
|
|
else
|
|
{
|
|
g_sf_conf->tunneling_tls_ignore_pkts = 4;
|
|
}
|
|
|
|
toml_val = toml_int_in(cfg_tbl, "TUNNELING_MAX_SCAN_PKTS");
|
|
if (toml_val.ok)
|
|
{
|
|
g_sf_conf->tunneling_max_scan_pkts = toml_val.u.i;
|
|
}
|
|
else
|
|
{
|
|
g_sf_conf->tunneling_max_scan_pkts = 15;
|
|
}
|
|
|
|
toml_val = toml_string_in(cfg_tbl, "TUNNELING_PCRE_LIST");
|
|
if (toml_val.ok)
|
|
{
|
|
strncpy(g_sf_conf->tunneling_pcre_list, toml_val.u.s, sizeof(g_sf_conf->tunneling_pcre_list) - 1);
|
|
free(toml_val.u.s);
|
|
toml_val.u.s = NULL;
|
|
}
|
|
else
|
|
{
|
|
strncpy(g_sf_conf->tunneling_pcre_list, "{\"tunneling_pcre_list\":[]}", sizeof(g_sf_conf->tunneling_pcre_list) - 1);
|
|
}
|
|
|
|
toml_val = toml_string_in(cfg_tbl, "RANDOM_LOOKING_JUDGE_LIST");
|
|
if (toml_val.ok)
|
|
{
|
|
strncpy(g_sf_conf->random_looking_judge_list, toml_val.u.s, sizeof(g_sf_conf->random_looking_judge_list) - 1);
|
|
free(toml_val.u.s);
|
|
toml_val.u.s = NULL;
|
|
}
|
|
else
|
|
{
|
|
strncpy(g_sf_conf->random_looking_judge_list, "{\"random_looking_judge_list\":[]}", sizeof(g_sf_conf->random_looking_judge_list) - 1);
|
|
}
|
|
|
|
toml_free(toml_root);
|
|
}
|
|
|
|
extern "C" void *session_flags_plugin_init(struct stellar *st)
|
|
{
|
|
char random_looking_list_str[2048] = {0};
|
|
struct session_flags_plugin_info *sf_plugin_info = (struct session_flags_plugin_info *)calloc(1, sizeof(struct session_flags_plugin_info));
|
|
cJSON *json = NULL, *item = NULL;
|
|
int array_num;
|
|
|
|
sf_plugin_info->st = st;
|
|
sf_plugin_info->sess_ctx_exdata_idx = stellar_exdata_new_index(st, "SESSION_FLAGS_SESS_CTX", session_flags_exdata_free_cb, NULL);
|
|
|
|
sf_plugin_info->log_handle = stellar_get_logger(st);
|
|
if(sf_plugin_info->log_handle==NULL)
|
|
{
|
|
printf("stellar_get_logger object failed ...\n");
|
|
goto ERROR;
|
|
}
|
|
|
|
memset(&g_sf_conf, 0, sizeof(g_sf_conf));
|
|
session_flags_load_config(sf_plugin_info, CFG_FILE_PATH, &g_sf_conf);
|
|
|
|
json = cJSON_Parse(g_sf_conf.random_looking_judge_list);
|
|
if (json == NULL)
|
|
{
|
|
STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "cJSON_Parse failed, random_looking_list_str:%s", random_looking_list_str);
|
|
goto ERROR;
|
|
}
|
|
item = cJSON_GetObjectItem(json, "random_looking_judge_list");
|
|
if (item == NULL)
|
|
{
|
|
STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "cJSON_GetObjectItem failed, random_looking_list_str:%s", random_looking_list_str);
|
|
goto ERROR;
|
|
}
|
|
array_num = cJSON_GetArraySize(item);
|
|
if (array_num > STS_RANDOM_JUDGE_NUM || array_num < 0)
|
|
{
|
|
STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "array size error, array_num:%d", array_num);
|
|
goto ERROR;
|
|
}
|
|
for (int i = 0; i < array_num; i++)
|
|
{
|
|
for (int j = 0; j < STS_RANDOM_JUDGE_NUM; j++)
|
|
{
|
|
if (strcmp(cJSON_GetArrayItem(item, i)->valuestring, random_looking_judge_table[j]) == 0)
|
|
{
|
|
STS_SET_FLAG(sts_random_switch, j);
|
|
g_sf_conf.random_judge_flags_cnt++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
cJSON_Delete(json);
|
|
|
|
sf_plugin_info->plugin_id = stellar_session_plugin_register(st, NULL, NULL, sf_plugin_info);
|
|
if (sf_plugin_info->plugin_id < 0)
|
|
{
|
|
STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "stellar_session_plugin_register failed");
|
|
goto ERROR;
|
|
|
|
}
|
|
|
|
sf_plugin_info->session_flags_topic_id = stellar_mq_create_topic(st, SESSION_FLAGS_MESSAGE_TOPIC, session_flags_topic_free_cb, NULL);
|
|
if (sf_plugin_info->session_flags_topic_id < 0)
|
|
{
|
|
STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "stellar_session_mq_create_topic failed");
|
|
goto ERROR;
|
|
}
|
|
|
|
sf_plugin_info->tcp_topic_id = stellar_mq_get_topic_id(st, TOPIC_TCP_INPUT);
|
|
sf_plugin_info->udp_topic_id = stellar_mq_get_topic_id(st, TOPIC_UDP_INPUT);
|
|
if (sf_plugin_info->tcp_topic_id < 0 || sf_plugin_info->udp_topic_id < 0)
|
|
{
|
|
STELLAR_LOG_FATAL(sf_plugin_info->log_handle, SESSION_FLAGS_LOG_MODULE, "stellar_session_mq_get_topic_id failed");
|
|
goto ERROR;
|
|
}
|
|
|
|
stellar_session_mq_subscribe(st, sf_plugin_info->tcp_topic_id, session_flags_entry, sf_plugin_info->plugin_id);
|
|
stellar_session_mq_subscribe(st, sf_plugin_info->udp_topic_id, session_flags_entry, sf_plugin_info->plugin_id);
|
|
|
|
return sf_plugin_info;
|
|
|
|
ERROR:
|
|
if (sf_plugin_info != NULL)
|
|
{
|
|
free(sf_plugin_info);
|
|
}
|
|
|
|
if (json != NULL)
|
|
{
|
|
cJSON_Delete(json);
|
|
}
|
|
|
|
perror("session_flags init failed");
|
|
exit(-1);
|
|
}
|
|
|
|
extern "C" void session_flags_plugin_exit(void *plugin_ctx)
|
|
{
|
|
if (plugin_ctx == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
free(plugin_ctx);
|
|
|
|
return;
|
|
} |