-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathudp-tcpfivem_xdp.c
308 lines (266 loc) · 11 KB
/
udp-tcpfivem_xdp.c
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/tcp.h>
#include <linux/in.h>
#include <bpf/bpf_helpers.h>
#define FIVEM_SERVER_IP 0x7F000001 // 127.0.0.1 in hexadecimal (loopback)
#define FIVEM_SERVER_PORT 30120 // FiveM server port
#define MAX_PACKET_RATE 13000 // Max packets per second for rate-limiting
#define BLOCKED_IP_LIST_MAX 128 // Max number of IPs in blocklist
// Per-CPU map for rate limiting per CPU core
struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__type(key, __u32);
__type(value, __u64);
__uint(max_entries, 1);
} rate_limit_map SEC(".maps");
// Blocklist map (dynamic, can be updated by user-space)
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, __u32); // IP address
__type(value, __u8); // Block flag (1 = blocked)
__uint(max_entries, BLOCKED_IP_LIST_MAX);
} blocklist_map SEC(".maps");
// Allowlist map for trusted IP addresses
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, __u32); // IP address
__type(value, __u8); // Allow flag (1 = allowed)
__uint(max_entries, BLOCKED_IP_LIST_MAX);
} allowlist_map SEC(".maps");
// Connection tracking map (to track stateful UDP/TCP connections)
struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, __u64); // Flow key (combination of src/dst IP, ports)
__type(value, __u64); // Last seen timestamp
__uint(max_entries, 4096); // Max number of tracked connections
} conntrack_map SEC(".maps");
// Deep packet inspection map for known attack patterns
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, __u32); // Pattern hash
__type(value, __u8); // Attack flag (1 = attack)
__uint(max_entries, 256);
} dpi_map SEC(".maps");
// Anomaly detection map for statistical traffic patterns
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, __u64); // Flow key
__type(value, __u64); // Anomaly score
__uint(max_entries, 4096);
} anomaly_map SEC(".maps");
// Machine learning-based threat detection map
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, __u64); // Flow key
__type(value, __u8); // Threat flag (1 = threat)
__uint(max_entries, 4096);
} ml_threat_map SEC(".maps");
// Helper function for parsing UDP
static __always_inline struct udphdr *parse_udp(void *data, void *data_end, struct ethhdr *eth, struct iphdr *ip) {
struct udphdr *udp = (struct udphdr *)((__u8 *)ip + sizeof(struct iphdr));
if ((void *)(udp + 1) > data_end) {
return NULL; // Bounds check failed
}
return udp;
}
// Helper function for parsing TCP
static __always_inline struct tcphdr *parse_tcp(void *data, void *data_end, struct ethhdr *eth, struct iphdr *ip) {
struct tcphdr *tcp = (struct tcphdr *)((__u8 *)ip + sizeof(struct iphdr));
if ((void *)(tcp + 1) > data_end) {
return NULL; // Bounds check failed
}
return tcp;
}
// Hash function for connection tracking (combining multiple fields for more randomness)
static __always_inline __u64 generate_flow_key(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport) {
return ((__u64)saddr << 32) | ((__u64)daddr ^ ((__u64)sport << 16) ^ dport ^ (saddr >> 8));
}
// Advanced deep packet inspection with pattern matching for multiple known attack signatures
static __always_inline int deep_packet_inspection(void *data, void *data_end) {
// Advanced example: check for multiple known malicious patterns in the payload
__u32 patterns[] = {0xdeadbeef, 0xbaadf00d, 0xfeedface}; // Example malicious payload patterns
for (int i = 0; i < sizeof(patterns) / sizeof(patterns[0]); i++) {
if (data + sizeof(__u32) > data_end) {
return 0; // Bounds check failed
}
if (*(__u32 *)data == patterns[i]) {
return 1; // Pattern matched
}
}
return 0;
}
// More sophisticated anomaly detection using multiple thresholds and pattern analysis
static __always_inline int detect_anomaly(__u64 flow_key) {
// Advanced example: check if the anomaly score exceeds multiple thresholds
__u64 *anomaly_score = bpf_map_lookup_elem(&anomaly_map, &flow_key);
if (anomaly_score) {
if (*anomaly_score > 500) { // Higher threshold for high sensitivity
return 1; // Severe anomaly detected
}
if (*anomaly_score > 200) { // Lower threshold for moderate sensitivity
return 1; // Moderate anomaly detected
}
}
return 0;
}
// Advanced machine learning-based threat detection integrating multiple features
static __always_inline int ml_threat_detection(__u64 flow_key) {
// Advanced example: multiple conditions based on threat level
__u8 *threat_flag = bpf_map_lookup_elem(&ml_threat_map, &flow_key);
if (threat_flag) {
if (*threat_flag == 2) { // More severe threat detected
return 1; // Drop severe threats
}
if (*threat_flag == 1) { // Minor threat detected
return 1; // Drop minor threats
}
}
return 0;
}
// Helper function for SYN cookie generation with stronger randomness
static __always_inline __u32 generate_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport, __u32 isn) {
// Advanced example: XOR of IPs, ports, initial sequence number, and a random factor
__u32 rand_factor = bpf_get_prandom_u32();
return saddr ^ daddr ^ sport ^ dport ^ isn ^ rand_factor;
}
// Helper function for TCP bypass detection with enhanced checking
static __always_inline int detect_tcp_bypass(struct tcphdr *tcp) {
// Advanced example: check for unusual TCP flags or sequence numbers with stricter rules
if (tcp->fin || tcp->rst || tcp->psh || tcp->urg || (tcp->seq & 0x1FFF) == 0) {
return 1; // TCP bypass attempt detected
}
return 0;
}
static __always_inline int handle_tcp_syn_flood(struct iphdr *ip, struct tcphdr *tcp) {
//(SYN = 1, ACK = 0)
if (tcp->syn && !tcp->ack) {
// Generate a SYN cookie based on the source and destination IP/ports
__u32 syn_cookie = generate_syn_cookie(ip->saddr, ip->daddr, tcp->source, tcp->dest, tcp->seq);
if (tcp->seq != syn_cookie) {
return XDP_DROP; // Invalid SYN cookie, likely part of a SYN flood attack
}
}
return XDP_PASS;
}
SEC("xdp_program")
int fivem_xdp(struct xdp_md *ctx) {
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
// Parse Ethernet header
struct ethhdr *eth = data;
if ((void *)(eth + 1) > data_end) {
return XDP_ABORTED;
}
// Only process IP packets
if (eth->h_proto != htons(ETH_P_IP)) {
return XDP_PASS;
}
// Parse IP header
struct iphdr *ip = (struct iphdr *)((__u8 *)eth + sizeof(struct ethhdr));
if ((void *)(ip + 1) > data_end) {
return XDP_ABORTED;
}
// Check if the source IP is blocked
__u8 *blocked = bpf_map_lookup_elem(&blocklist_map, &ip->saddr);
if (blocked && *blocked == 1) {
return XDP_DROP; // Drop packet from blocked IP
}
// Check if the source IP is allowed (bypass filtering)
__u8 *allowed = bpf_map_lookup_elem(&allowlist_map, &ip->saddr);
if (allowed && *allowed == 1) {
return XDP_PASS; // Allow packet from trusted IP
}
// UDP or TCP handling
__u64 now = bpf_ktime_get_ns();
__u64 *last_seen;
__u64 flow_key;
if (ip->protocol == IPPROTO_UDP) {
// Parse UDP header with bounds checking
struct udphdr *udp = parse_udp(data, data_end, eth, ip);
if (!udp) {
return XDP_ABORTED;
}
// Check if the packet is destined for the FiveM server
if (ip->daddr != htonl(FIVEM_SERVER_IP) || udp->dest != htons(FIVEM_SERVER_PORT)) {
return XDP_PASS; // Let other packets through
}
// Handle SYN flood mitigation
if (handle_tcp_syn_flood(ip, tcp) == XDP_DROP) {
return XDP_DROP;
}
// Generate a flow key based on source and destination IP/ports
flow_key = generate_flow_key(ip->saddr, ip->daddr, udp->source, udp->dest);
// Perform connection tracking
last_seen = bpf_map_lookup_elem(&conntrack_map, &flow_key);
if (last_seen) {
// Update the last seen time for the connection
*last_seen = now;
} else {
// Insert a new entry into the connection tracking map
bpf_map_update_elem(&conntrack_map, &flow_key, &now, BPF_ANY);
}
// Perform deep packet inspection (DPI) for known malicious patterns
if (deep_packet_inspection(data, data_end)) {
return XDP_DROP; // Drop packet if malicious pattern detected
}
// Check for anomaly detection
if (detect_anomaly(flow_key)) {
return XDP_DROP; // Drop packet if an anomaly is detected
}
// Check for machine learning-based threat detection
if (ml_threat_detection(flow_key)) {
return XDP_DROP; // Drop packet if a threat is detected
}
} else if (ip->protocol == IPPROTO_TCP) {
struct tcphdr *tcp = parse_tcp(data, data_end, eth, ip);
if (!tcp) {
return XDP_ABORTED;
}
// Check if the packet is destined for the FiveM server
if (ip->daddr != htonl(FIVEM_SERVER_IP) || tcp->dest != htons(FIVEM_SERVER_PORT)) {
return XDP_PASS;
}
// Generate a flow key for the TCP connection
flow_key = generate_flow_key(ip->saddr, ip->daddr, tcp->source, tcp->dest);
// Perform connection tracking for TCP as well
last_seen = bpf_map_lookup_elem(&conntrack_map, &flow_key);
if (last_seen) {
// Update the last seen time for the TCP connection
*last_seen = now;
} else {
// Insert a new entry into the connection tracking map
bpf_map_update_elem(&conntrack_map, &flow_key, &now, BPF_ANY);
}
// Detect TCP bypass attempts based on unusual flag or sequence number
if (detect_tcp_bypass(tcp)) {
return XDP_DROP; // Drop packet if TCP bypass attempt detected
}
// Perform deep packet inspection (DPI) for TCP
if (deep_packet_inspection(data, data_end)) {
return XDP_DROP; // Drop packet if malicious pattern detected
}
// Check for anomaly detection
if (detect_anomaly(flow_key)) {
return XDP_DROP; // Drop packet if an anomaly is detected
}
// Check for machine learning-based threat detection
if (ml_threat_detection(flow_key)) {
return XDP_DROP; // Drop packet if a threat is detected
}
}
// Rate limiting logic
__u32 key = 0;
__u64 *rate = bpf_map_lookup_elem(&rate_limit_map, &key);
if (rate) {
__u64 last_packet_time = *rate;
if (now - last_packet_time < (1000000000 / MAX_PACKET_RATE)) {
return XDP_DROP; // Drop packets that exceed the rate limit
}
*rate = now; // Update the last packet time
}
return XDP_PASS; // Allow the packet if all checks passed
}
char _license[] SEC("license") = "MIT";