1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <time.h>
#include <unistd.h>
#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;
}
|