#include #include #include #include #include #include #include #include #include #include #include "nat_format.h" #define 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(NAT_FORMAT_CONFIG_FILE, "NAT_FORMAT_LOG", "run_log_path", g_nat_format_info.log_path, sizeof(g_nat_format_info.log_path), "./log/nat_format.log"); MESA_load_profile_uint_def(NAT_FORMAT_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_nat_format_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; nat_payload.fw_ip = a_udp->addr.tuple4_v4->saddr; // 防火墙ip为源ip,本身为二进制格式 // 根据数据来源的端口采取不同的处理策略 // 华为syslog格式:防火墙日志生成时间需要转换为时间戳、动作字符串需要转换为序号、点分十进制格式ip需要转换为二进制 if (udp_port == 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; } } else if (udp_port == g_nat_format_info.hw_binary_port) { return APP_STATE_GIVEME; } else if (udp_port == g_nat_format_info.h3_syslog_port) { return APP_STATE_GIVEME; } else if (udp_port == g_nat_format_info.h3_binary_port) { return APP_STATE_GIVEME; } else if (udp_port == g_nat_format_info.dp_syslog_port) { return APP_STATE_GIVEME; } else if (udp_port == g_nat_format_info.dp_binary_port) { return APP_STATE_GIVEME; } // 将提取出来的信息写进组播载荷 memcpy(multicast_payload + cur_pkt*PAYLOAD_LEN, &nat_payload, PAYLOAD_LEN); 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) { MESA_handle_runtime_log(g_nat_format_info.log, RLOG_LV_FATAL, "nat_format Huawei syslog", "Send multicast failed: %s", strerror(errno)); } cur_pkt = 0; } return APP_STATE_GIVEME; }