summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunzy <[email protected]>2024-08-23 17:53:01 +0800
committerJunzy <[email protected]>2024-08-23 17:53:01 +0800
commit37d3039dd12dd588b6038cf6e2e836d332043214 (patch)
treed7af806edb3934a6b7ab39bd0b7498c128112b70
parent59effb65ea296f658c6c57917ee6152304878230 (diff)
first commit
-rw-r--r--CMakeLists.txt15
-rw-r--r--bin/conf/nat_format.conf18
-rw-r--r--bin/conf/nat_format.inf9
-rw-r--r--src/nat_format.cpp175
-rw-r--r--src/nat_format.h53
5 files changed, 270 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..b9ed544
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,15 @@
+set (PLUG_NAT_FORMAT_SRC nat_format.cpp)
+add_definitions(-fPIC -Wall -g)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__FILENAME__='\"$(subst ${CMAKE_CURRENT_SOURCE_DIR}/,,$(abspath $<))\"'")
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
+include_directories(/opt/MESA/include/)
+
+set(PLUG_NAT_FORMAT_DEPEND_DYN_LIB MESA_handle_logger MESA_prof_load MESA_field_stat2 avro libevent libevent-openssl libevent-pthreads curl)
+
+add_library(nat_format SHARED ${PLUG_NAT_FORMAT_SRC})
+target_link_libraries(nat_format ${PLUG_NAT_FORMAT_DEPEND_DYN_LIB})
+set_target_properties(nat_format PROPERTIES PREFIX "")
+
+install(TARGETS nat_format DESTINATION ${CMAKE_INSTALL_PREFIX}/plug/business/nat_format)
+install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/bin/conf/nat_format.conf DESTINATION ${CMAKE_INSTALL_PREFIX}/conf)
diff --git a/bin/conf/nat_format.conf b/bin/conf/nat_format.conf
new file mode 100644
index 0000000..d86921e
--- /dev/null
+++ b/bin/conf/nat_format.conf
@@ -0,0 +1,18 @@
+[NAT_FORMAT_SEND]
+batch_size=20
+host_ip=127.0.0.1
+host_port=5678
+multicast_ip=224.88.88.88
+multicast_port=0
+
+[NAT_FORMAT_RECEIVE_PORT]
+hw_syslog=514
+hw_binary=515
+h3_syslog=516
+h3_binary=517
+dp_syslog=518
+dp_binary=519
+
+[NAT_FORMAT_LOG]
+run_log_path=./log/nat_format.log
+run_log_level=10
diff --git a/bin/conf/nat_format.inf b/bin/conf/nat_format.inf
new file mode 100644
index 0000000..fb02ba5
--- /dev/null
+++ b/bin/conf/nat_format.inf
@@ -0,0 +1,9 @@
+[PLUGINFO]
+PLUGNAME=nat_format
+SO_PATH=./plug/business/nat_format/nat_format.so
+INIT_FUNC=nat_format_init
+DESTROY_FUNC=nat_format_destroy
+
+[UDP]
+FUNC_FLAG=ALL
+FUNC_NAME=nat_format_entry \ No newline at end of file
diff --git a/src/nat_format.cpp b/src/nat_format.cpp
new file mode 100644
index 0000000..20a8465
--- /dev/null
+++ b/src/nat_format.cpp
@@ -0,0 +1,175 @@
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "nat_format.h"
+
+#define NAT_FORMAT_NAT_FORMAT_CONFIG_FILE "./conf/nat_format.conf"
+#define PAYLOAD_LEN 46
+
+#define FORMAT_LOG_ACTION_ADD 0x00
+#define FORMAT_LOG_ACTION_DEL 0x01
+
+#define HW_EVENT_ADD "SESSION_BUILT"
+#define HW_EVENT_DEL "SESSION_TEARDOWN"
+
+struct nat_format_global_info g_nat_format_info;
+
+char *multicast_payload;
+int cur_pkt = 0;
+
+int udp_socket;
+struct sockaddr_in dst_addr;
+
+// 初始化函数
+int nat_format_init(void) {
+ // 读取配置文件
+ 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_int_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_SEND", "host_port", &g_nat_format_info.host_port, 5678);
+ MESA_load_profile_string_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_SEND", "multicast_ip", g_nat_format_info.multicast_ip, 16, "224.88.88.88");
+ MESA_load_profile_int_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_SEND", "multicast_port", &g_nat_format_info.multicast_port, 0);
+
+ MESA_load_profile_int_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_RECEIVE_PORT", "hw_syslog", &g_nat_format_info.hw_syslog_port, 514);
+ MESA_load_profile_int_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_RECEIVE_PORT", "hw_binary", &g_nat_format_info.hw_binary_port, 515);
+ MESA_load_profile_int_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_RECEIVE_PORT", "h3_syslog", &g_nat_format_info.h3_syslog_port, 516);
+ MESA_load_profile_int_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_RECEIVE_PORT", "h3_binary", &g_nat_format_info.h3_binary_port, 517);
+ MESA_load_profile_int_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_RECEIVE_PORT", "dp_syslog", &g_nat_format_info.dp_syslog_port, 518);
+ MESA_load_profile_int_def(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_RECEIVE_PORT", "dp_binary", &g_nat_format_info.dp_binary_port, 519);
+
+ MESA_load_profile_string_def(config_file, "NAT_FORMAT_LOG", "run_log_path", g_nat_format_info.log_path, sizeof(g_nat_format_info.root_log_path), "./log/nat_format.log");
+ MESA_load_profile_uint_def(config_file, "NAT_FORMAT_LOG", "run_log_level", &g_nat_format_info.log_level, 10);
+ g_nat_format_info.log = MESA_create_runtime_log_handle(g_nat_format_info.log_path, g_nat_format_info.log_level);
+ if (g_tf_dns_info.log == NULL) {
+ printf("MESA_create_runtime_log_handle %s failed: %s\n", g_nat_format_info.log_path, strerror(errno));
+ return -1;
+ }
+
+ // 分配并初始化组播报文存储空间,长度为 batch_size*46Bytes
+ multicast_payload = (char *)malloc(PAYLOAD_LEN * g_nat_format_info.batch_size);
+ memset(multicast_payload, 0, PAYLOAD_LEN * g_nat_format_info.batch_size);
+
+ // 创建socket用于发包,绑定组播地址和发包端口
+ udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
+ if (udp_socket == -1) {
+ printf("UDP multicast socket creation failed:%d, %s\n", errno, strerror(errno));
+ return -1;
+ }
+ dst_addr.sin_family = AF_INET;
+ 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);
+ struct sockaddr_in src_addr;
+ src_addr.sin_family = AF_INET;
+ src_addr.sin_port = htons(g_nat_format_info.host_port);
+ src_addr.sin_addr.s_addr = inet_addr(g_nat_format_info.host_ip);
+ if (bind(udp_socket, (struct sockaddr*)&src_addr, sizeof(src_addr)) < 0) {
+ printf("socket bind failed\n");
+ close(udp_socket);
+ return -1;
+ }
+
+ return 0;
+}
+
+// 卸载函数
+void nat_format_destroy(void) {
+ free(nat_payload);
+}
+
+// 入口函数
+/*
+ 输入参数:
+ a_udp: UDP流信息,详见stream.h;
+ pme: UDP链接上下文信息;
+ thread_seq: 线程号
+ a_packet: 原始IP数据包
+ 返回值:
+ PROT_STATE_GIVEME: 业务插件继续需要给会话后续包;
+ PROT_STATE_DROPME: 业务插件不再需要该会话后续包;
+ PROT_STATE_KILLME: 业务插件对此流做FD动作,此流不再给其他插件。
+*/
+char nat_format_entry(struct streaminfo *a_udp, void **pme, int thread_seq, void *a_packet) {
+ // 不处理空数据包
+ if (a_packet == NULL) {
+ return APP_STATE_GIVEME;
+ }
+
+ // 提取udp流信息
+ char *udp_data = (char *)a_udp->pudpdetail->pdata;
+ int32_t upd_data_len = a_udp->pudpdetail->datalen;
+ unsigned short udp_port = a_udp->addr.tuple4_v4->source;
+
+ // 提取nat信息
+ struct nat_payload nat_payload;
+ inet_pton(AF_INET, a_udp->addr.tuple4_v4->s_addr, nat_payload.fw_ip); // 防火墙ip为源ip,需要进行点分十进制转换
+ // 根据数据来源的端口采取不同的处理策略
+ switch (udp_port) {
+ // 华为syslog格式:防火墙日志生成时间需要转换为时间戳、动作字符串需要转换为序号、点分十进制格式ip需要转换为二进制
+ case g_nat_format_info.hw_syslog_port:
+ char fw_log_time[21];
+ char action_str[20];
+ char src_intra_ip[20];
+ char dst_ip[20];
+ char src_extra_ip[20];
+ 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;
+ 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);
+ return APP_STATE_GIVEME;
+ }
+ 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) {
+ nat_payload.action = FORMAT_LOG_ACTION_ADD;
+ } else if (strcmp(action_str, HW_EVENT_DEL) == 0) {
+ nat_payload.action = FORMAT_LOG_ACTION_DEL;
+ } 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);
+ return APP_STATE_GIVEME;
+ }
+
+ break;
+ case g_nat_format_info.hw_binary_port:
+ break;
+ case g_nat_format_info.h3_syslog_port:
+ break;
+ case g_nat_format_info.h3_binary_port:
+ break;
+ case g_nat_format_info.dp_syslog_port:
+ break;
+ case g_nat_format_info.dp_binary_port:
+ break;
+ default:
+ break;
+ }
+
+ // 将提取出来的信息写进组播载荷
+ memcpy(multicast_payload + cur_pkt*PAYLOAD_LEN, &nat_payload, PAYLOAD_LEN);
+ cur_pkt++;
+
+ // 攒够20个进行发送
+ if (cur_pkt == 20) {
+ if (sendto(udp_socket, buf, strlen(buf), 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", "Event field is an undefined value: %s", action_str);
+ }
+ cur_pkt = 0;
+ }
+
+ return APP_STATE_GIVEME;
+}
diff --git a/src/nat_format.h b/src/nat_format.h
new file mode 100644
index 0000000..33c773c
--- /dev/null
+++ b/src/nat_format.h
@@ -0,0 +1,53 @@
+#ifndef NAT_FORMAT_H_
+#define NAT_FORMAT_H_
+
+#include <MESA/stream.h>
+#include <MESA/MESA_handle_logger.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 {
+ int32_t batch_size;
+ char host_ip[64];
+ u_int32_t host_port;
+ char multicast_ip[64];
+ u_int32_t multicast_port;
+
+ int32_t hw_syslog_port;
+ int32_t hw_binary_port;
+ int32_t h3_syslog_port;
+ int32_t h3_binary_port;
+ int32_t dp_syslog_port;
+ int32_t dp_binary_port;
+
+ char root_log_path[256];
+ u_int32_t log_level;
+ void *log;
+};
+
+// 格式化NAT报文载荷
+struct nat_payload {
+ unsigned int magic_num = FORMAT_LOG_MAGIC_NUMBER;
+ unsigned short magic_num = FORMAT_LOG_VERSION;
+ unsigned int fw_log_timestamp;
+ unsigned int fw_ip;
+ char action;
+ unsigned int stream_start_timestamp;
+ unsigned int stream_end_timestamp;
+ unsigned int src_intra_ip;
+ unsigned short src_intra_port;
+ unsigned int src_extra_ip;
+ unsigned short src_extra_port;
+ unsigned int dst_ip;
+ unsigned short dst_port;
+ char protocol = FORMAT_LOG_PROTOCOL_UDP;
+};
+
+#endif // NAT_FORMAT_H_