change processing logic: scan string for each field.

This commit is contained in:
Junzy
2024-09-11 21:03:54 +08:00
parent 4b7168f6bd
commit 3b5ce18ae2
3 changed files with 147 additions and 31 deletions

View File

@@ -1,3 +1,7 @@
[NAT_FORMAT]
magic_num=0x004e4154
version=0x0200
[NAT_FORMAT_SEND] [NAT_FORMAT_SEND]
batch_size=20 batch_size=20
host_ip=127.0.0.1 host_ip=127.0.0.1

View File

@@ -21,17 +21,82 @@
#define HW_EVENT_ADD "SESSION_BUILT" #define HW_EVENT_ADD "SESSION_BUILT"
#define HW_EVENT_DEL "SESSION_TEARDOWN" #define HW_EVENT_DEL "SESSION_TEARDOWN"
#define FORMAT_LOG_PROTOCOL_ICMP 0x01
#define FORMAT_LOG_PROTOCOL_TCP 0x06
#define FORMAT_LOG_PROTOCOL_UDP 0x17
struct nat_format_global_info g_nat_format_info; struct nat_format_global_info g_nat_format_info;
char *multicast_payload; char *multicast_payload;
int cur_pkt = 0; int cur_pkt = 0;
int udp_socket; int udp_socket;
struct sockaddr_in dst_addr; struct sockaddr_in dst_addr = {0};
// 函数:子串匹配,返回子串结尾+1的位置即值的起始位置
int get_value_offset(char *str, int str_len, const char *key) {
int i, j;
int key_len = strlen(key);
for (i = 0; i <= str_len - key_len - 1; i++) {
for (j = 0; j < key_len; j++) {
if (str[i + j]!= key[j])
break;
}
if (j == key_len)
return (i + key_len + 1);
}
return -1;
}
// 函数从字符串中提取点分十进制ip并转换为二进制数
int extract_ip(char *data, int data_len, const char *key, unsigned int *dst) {
int offset;
char tmp_ip[20];
if ((offset = get_value_offset(data, data_len, key)) == -1) { return -1; }
if (sscanf(data+offset, "%19[^,]", tmp_ip) != 1) { return -1; }
if (inet_pton(AF_INET, tmp_ip, dst) <= 0) {return -1; }
return 0;
}
// 函数从字符串中提取字符串并转为16位数
int extract_port(char *data, int data_len, const char *key, unsigned short *dst) {
int offset;
if ((offset = get_value_offset(data, data_len, key)) == -1) { return -1; }
if (sscanf(data+offset, "%hu", dst) != 1) { return -1; }
*dst = htons(*dst);
return 0;
}
// 函数从字符串中提取字符串并转为32位数
int extract_time(char *data, int data_len, const char *key, unsigned int *dst) {
int offset;
if ((offset = get_value_offset(data, data_len, key)) == -1) { return -1; }
if (sscanf(data+offset, "%u", dst) != 1) { return -1; }
return 0;
}
// 函数:从字符串中提取字符串并转为标识
int extract_protocol(char *data, int data_len, const char *key, char *dst) {
int offset;
char protocol_str[20];
if ((offset = get_value_offset(data, data_len, key)) == -1) { return -1; }
if (sscanf(data+offset, "%[^,]", protocol_str) != 1) { return -1; }
if (strcmp(protocol_str, "tcp") == 0) {
*dst = FORMAT_LOG_PROTOCOL_TCP;
} else if (strcmp(protocol_str, "udp") == 0) {
*dst = FORMAT_LOG_PROTOCOL_UDP;
} else if (strcmp(protocol_str, "icmp") == 0) {
*dst = FORMAT_LOG_PROTOCOL_ICMP;
} else {
return -1;
}
return 0;
}
// 初始化函数 // 初始化函数
int nat_format_init(void) { int nat_format_init(void) {
// 读取配置文件 // 读取配置文件
MESA_load_profile_uint_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT", "magic_num", &g_nat_format_info.magic_num, 0x004e4154);
MESA_load_profile_uint_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT", "version", &g_nat_format_info.version, 0x0200);
MESA_load_profile_uint_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_SEND", "batch_size", &g_nat_format_info.batch_size, 20); MESA_load_profile_uint_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_SEND", "batch_size", &g_nat_format_info.batch_size, 20);
MESA_load_profile_string_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_SEND", "host_ip", g_nat_format_info.host_ip, 16, "127.0.0.1"); MESA_load_profile_string_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_SEND", "host_ip", g_nat_format_info.host_ip, 16, "127.0.0.1");
MESA_load_profile_int_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_SEND", "host_port", &g_nat_format_info.host_port, 5678); MESA_load_profile_int_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_SEND", "host_port", &g_nat_format_info.host_port, 5678);
@@ -57,15 +122,20 @@ int nat_format_init(void) {
multicast_payload = (char *)malloc(PAYLOAD_LEN * g_nat_format_info.batch_size); multicast_payload = (char *)malloc(PAYLOAD_LEN * g_nat_format_info.batch_size);
memset(multicast_payload, 0, PAYLOAD_LEN * g_nat_format_info.batch_size); memset(multicast_payload, 0, PAYLOAD_LEN * g_nat_format_info.batch_size);
// 创建socket用于发包,绑定组播地址和发包端口 // 创建socket用于发包
udp_socket = socket(AF_INET, SOCK_DGRAM, 0); udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (udp_socket == -1) { if (udp_socket == -1) {
printf("UDP multicast socket creation failed:%d, %s\n", errno, strerror(errno)); printf("UDP multicast socket creation failed:%d, %s\n", errno, strerror(errno));
return -1; return -1;
} }
// 绑定组播地址
dst_addr.sin_family = AF_INET; dst_addr.sin_family = AF_INET;
dst_addr.sin_addr.s_addr = inet_addr(g_nat_format_info.multicast_ip); dst_addr.sin_addr.s_addr = inet_addr(g_nat_format_info.multicast_ip);
dst_addr.sin_port = htons(g_nat_format_info.multicast_port); dst_addr.sin_port = htons(g_nat_format_info.multicast_port);
struct in_addr multicast_addr;
inet_pton(AF_INET, g_nat_format_info.multicast_ip, &multicast_addr.s_addr);
setsockopt(udp_socket, IPPROTO_IP, IP_MULTICAST_IF, &multicast_addr, sizeof(multicast_addr));
// 绑定发包端口
struct sockaddr_in src_addr; struct sockaddr_in src_addr;
src_addr.sin_family = AF_INET; src_addr.sin_family = AF_INET;
src_addr.sin_port = htons(g_nat_format_info.host_port); src_addr.sin_port = htons(g_nat_format_info.host_port);
@@ -104,46 +174,92 @@ char nat_format_entry(struct streaminfo *a_udp, void **pme, int thread_seq, void
// 提取udp流信息 // 提取udp流信息
char *udp_data = (char *)a_udp->pudpdetail->pdata; char *udp_data = (char *)a_udp->pudpdetail->pdata;
// int32_t upd_data_len = a_udp->pudpdetail->datalen; int32_t udp_data_len = a_udp->pudpdetail->datalen;
unsigned short udp_port = a_udp->addr.tuple4_v4->source; unsigned short udp_port = ntohs(a_udp->addr.tuple4_v4->dest);
// 提取nat信息 // 提取nat信息
struct nat_payload nat_payload; struct nat_payload nat_payload;
nat_payload.magic_num = htonl(g_nat_format_info.magic_num);
nat_payload.version = htons((unsigned short)g_nat_format_info.version);
nat_payload.fw_ip = a_udp->addr.tuple4_v4->saddr; // 防火墙ip为源ip本身为二进制格式 nat_payload.fw_ip = a_udp->addr.tuple4_v4->saddr; // 防火墙ip为源ip本身为二进制格式
// 根据数据来源的端口采取不同的处理策略 // 根据数据来源的端口采取不同的处理策略
// 华为syslog格式防火墙日志生成时间需要转换为时间戳、动作字符串需要转换为序号、点分十进制格式ip需要转换为二进制 // 华为syslog格式防火墙日志生成时间需要转换为时间戳、动作字符串需要转换为序号、点分十进制格式ip需要转换为二进制
if (udp_port == g_nat_format_info.hw_syslog_port) { if (udp_port == g_nat_format_info.hw_syslog_port) {
// <190>2024-01-25 01:41:37 JXNC_LTGC_Eudemon_A %%01SECLOG/6/SESSION_TEARDOWN(l):IPVer=4,Protocol=udp,SourceIP=10.119.25.34,DestinationIP=220.248.192.13,SourcePort=35040,DestinationPort=53,SourceNatIP=118.212.209.248,SourceNatPort=6438,BeginTime=1706147236,EndTime=1706147236,SourceVpnID=0,DestinationVpnID=0,SourceZone=pscenet,DestinationZone=untrust,PolicyName=---,CloseReason=aged-out.
// sscanf(udp_data, "%*[^>]>%20[0-9: -]%*[^/]/%*[0-9]/%19[A-Z_]%*[^:]:IPVer=%*[^,],Protocol=%*[^,],SourceIP=%19[^,],DestinationIP=%19[^,],SourcePort=%hu,DestinationPort=%hu,SourceNatIP=%19[^,],SourceNatPort=%hu,BeginTime=%u,EndTime=%u", fw_log_time, action_str, src_intra_ip, dst_ip, &nat_payload.src_intra_port, &nat_payload.dst_port, src_extra_ip, &nat_payload.src_extra_port, &nat_payload.stream_start_timestamp, &nat_payload.stream_end_timestamp);
// 字段前的部分:防火墙日志生成时间、动作
char fw_log_time[21]; char fw_log_time[21];
char action_str[20]; char action_str[20];
char src_intra_ip[20]; if (sscanf(udp_data, "%*[^>]>%20[0-9: -]%*[^/]/%*[0-9]/%19[A-Z_]", fw_log_time, action_str) != 2) {
char dst_ip[20]; MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_INFO, "nat_format Huawei syslog", "NAT extraction fw_log_time or action_str failed");
char src_extra_ip[20]; return APP_STATE_GIVEME;
int suc_num = sscanf(udp_data, "%*[^>]>%20[0-9: -]%*[^/]/%*[0-9]/%19[A-Z_]%*[^:]:SourceIP=%19[^,],DestinationIP=%19[^,],SourcePort=%hu,DestinationPort=%hu,SourceNatIP=%19[^,],SourceNatPort=%hu,BeginTime=%u,EndTime=%u",
fw_log_time, action_str, src_intra_ip, dst_ip, &nat_payload.src_intra_port, &nat_payload.dst_port, src_extra_ip, &nat_payload.src_extra_port, &nat_payload.stream_start_timestamp, &nat_payload.stream_end_timestamp);
if (suc_num != 10) {
MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_FATAL, "nat_format Huawei syslog", "NAT extraction failed: %d/10", suc_num);
return APP_STATE_DROPME;
} }
struct tm fw_time; struct tm fw_time;
if (strptime(fw_log_time, "%Y-%m-%d %H:%M:%S ", &fw_time) == NULL) { if (strptime(fw_log_time, "%Y-%m-%d %H:%M:%S ", &fw_time) == NULL) {
MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_FATAL, "nat_format Huawei syslog", "firewall log generation time extraction failed: %s", fw_log_time); MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_INFO, "nat_format Huawei syslog", "firewall log generation time extraction failed: %s", fw_log_time);
return APP_STATE_GIVEME; return APP_STATE_GIVEME;
} }
nat_payload.fw_log_timestamp = (unsigned int)mktime(&fw_time); nat_payload.fw_log_timestamp = (unsigned int)mktime(&fw_time);
inet_pton(AF_INET, src_intra_ip, &nat_payload.src_intra_ip);
inet_pton(AF_INET, dst_ip, &nat_payload.dst_ip);
inet_pton(AF_INET, src_extra_ip, &nat_payload.src_extra_ip);
if (strcmp(action_str, HW_EVENT_ADD) == 0) { if (strcmp(action_str, HW_EVENT_ADD) == 0) {
nat_payload.action = FORMAT_LOG_ACTION_ADD; nat_payload.action = FORMAT_LOG_ACTION_ADD;
} else if (strcmp(action_str, HW_EVENT_DEL) == 0) { } else if (strcmp(action_str, HW_EVENT_DEL) == 0) {
nat_payload.action = FORMAT_LOG_ACTION_DEL; nat_payload.action = FORMAT_LOG_ACTION_DEL;
} else { } else {
MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_FATAL, "nat_format Huawei syslog", "Event field is an undefined value: %s", action_str); MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_INFO, "nat_format Huawei syslog", "Event field is an undefined value: %s", action_str);
return APP_STATE_GIVEME; return APP_STATE_GIVEME;
} }
// 字段部分按顺序排列SourceIP、DestinationIP、SourcePort、DestinationPort、SourceNatIP、SourceNatPort、BeginTime、EndTime
// 依次对应nat_payload的src_intra_ip, dst_ip, src_intra_port, &dst_port, src_extra_ip, src_extra_port, stream_start_timestamp, stream_end_timestamp
if (extract_ip(udp_data, udp_data_len, "SourceIP", &nat_payload.src_intra_ip) < 0) {
MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_INFO, "nat_format Huawei syslog", "SourceIP Not Found");
return APP_STATE_GIVEME;
}
if (extract_ip(udp_data, udp_data_len, "DestinationIP", &nat_payload.dst_ip) < 0) {
MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_INFO, "nat_format Huawei syslog", "DestinationIP Not Found");
return APP_STATE_GIVEME;
}
if (extract_port(udp_data, udp_data_len, "SourcePort", &nat_payload.src_intra_port) < 0) {
MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_INFO, "nat_format Huawei syslog", "SourcePort Not Found");
return APP_STATE_GIVEME;
}
if (extract_port(udp_data, udp_data_len, "DestinationPort", &nat_payload.dst_port) < 0) {
MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_INFO, "nat_format Huawei syslog", "DestinationPort Not Found");
return APP_STATE_GIVEME;
}
if (extract_ip(udp_data, udp_data_len, "SourceNatIP", &nat_payload.src_extra_ip) < 0) {
MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_INFO, "nat_format Huawei syslog", "SourceNatIP Not Found");
return APP_STATE_GIVEME;
}
if (extract_port(udp_data, udp_data_len, "SourceNatPort", &nat_payload.src_extra_port) < 0) {
MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_INFO, "nat_format Huawei syslog", "SourceNatPort Not Found");
return APP_STATE_GIVEME;
}
if (extract_time(udp_data, udp_data_len, "BeginTime", &nat_payload.stream_start_timestamp) < 0) {
MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_INFO, "nat_format Huawei syslog", "BeginTime Not Found");
return APP_STATE_GIVEME;
}
if (extract_time(udp_data, udp_data_len, "EndTime", &nat_payload.stream_end_timestamp) < 0) {
MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_INFO, "nat_format Huawei syslog", "EndTime Not Found");
return APP_STATE_GIVEME;
}
if (extract_protocol(udp_data, udp_data_len, "Protocol", &nat_payload.protocol) < 0) {
MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_INFO, "nat_format Huawei syslog", "Protocol Not Found");
return APP_STATE_GIVEME;
}
} else if (udp_port == g_nat_format_info.hw_binary_port) { } else if (udp_port == g_nat_format_info.hw_binary_port) {
return APP_STATE_GIVEME; return APP_STATE_GIVEME;
} else if (udp_port == g_nat_format_info.h3_syslog_port) { } else if (udp_port == g_nat_format_info.h3_syslog_port) {
@@ -162,8 +278,8 @@ char nat_format_entry(struct streaminfo *a_udp, void **pme, int thread_seq, void
// 攒够20个进行发送 // 攒够20个进行发送
if (cur_pkt == 20) { if (cur_pkt == 20) {
if (sendto(udp_socket, multicast_payload, strlen(multicast_payload), 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr)) < 0) { if (sendto(udp_socket, multicast_payload, PAYLOAD_LEN*g_nat_format_info.batch_size, 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr)) < 0) {
MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_FATAL, "nat_format Huawei syslog", "Send multicast failed: %s", strerror(errno)); MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_INFO, "nat_format Huawei syslog", "Send multicast failed: %s", strerror(errno));
} }
cur_pkt = 0; cur_pkt = 0;
} }

View File

@@ -5,15 +5,11 @@
#include <MESA/MESA_handle_logger.h> #include <MESA/MESA_handle_logger.h>
#include <MESA/MESA_prof_load.h> #include <MESA/MESA_prof_load.h>
#define FORMAT_LOG_MAGIC_NUMBER 0x004e4154
#define FORMAT_LOG_VERSION 0x0200
#define FORMAT_LOG_PROTOCOL_ICMP 0x01
#define FORMAT_LOG_PROTOCOL_TCP 0x06
#define FORMAT_LOG_PROTOCOL_UDP 0x17 // 目前均采用UDP传输
// 全局配置信息 // 全局配置信息
struct nat_format_global_info { struct nat_format_global_info {
u_int32_t magic_num;
u_int32_t version;
u_int32_t batch_size; u_int32_t batch_size;
char host_ip[64]; char host_ip[64];
int32_t host_port; int32_t host_port;
@@ -34,8 +30,8 @@ struct nat_format_global_info {
// 格式化NAT报文载荷 // 格式化NAT报文载荷
struct nat_payload { struct nat_payload {
unsigned int magic_num = FORMAT_LOG_MAGIC_NUMBER; unsigned int magic_num;
unsigned short version = FORMAT_LOG_VERSION; unsigned short version;
unsigned int fw_log_timestamp; unsigned int fw_log_timestamp;
unsigned int fw_ip; unsigned int fw_ip;
char action; char action;
@@ -47,7 +43,7 @@ struct nat_payload {
unsigned short src_extra_port; unsigned short src_extra_port;
unsigned int dst_ip; unsigned int dst_ip;
unsigned short dst_port; unsigned short dst_port;
char protocol = FORMAT_LOG_PROTOCOL_UDP; char protocol;
}; };
extern "C" int nat_format_init(void); extern "C" int nat_format_init(void);