ebpf-blocker 1.0.0
XDP-based packet blocker using eBPF
Loading...
Searching...
No Matches
blocker_kern.c
Go to the documentation of this file.
1/// \file blocker_kern.c
2/// \brief XDP BPF-программа фильтрации пакетов по whitelist/blacklist.
3///
4/// Компилируется clang -target bpf и встраивается в userspace-бинарник
5/// в виде C-массива байткода (через xxd).
6///
7/// Обработка пакета:
8/// 1. Парсинг Ethernet + IPv4 заголовков.
9/// 2. Поиск source IP в whitelist_map (LPM trie) -> XDP_PASS если найден.
10/// 3. Поиск source IP в blacklist_map (LPM trie) -> XDP_DROP если найден,
11/// атомарный инкремент drop_counter для source IP.
12/// 4. Иначе -> XDP_PASS.
13
14#include <linux/types.h>
15#include <bpf/bpf_endian.h>
16#include <bpf/bpf_helpers.h>
17#include <linux/bpf.h>
18#include <linux/if_ether.h>
19#include <linux/ip.h>
20
21/// Ключ для LPM trie-карт: длина префикса + IP в network byte order.
22struct lpm_key {
23 __u32 prefixlen; ///< Количество значащих битов (0-32).
24 __u32 ip; ///< IP-адрес в network byte order (с маской).
25};
26
27/// LPM trie белого списка: IP-адреса источников, пропускаемые без проверки
28/// чёрного списка.
29struct {
30 __uint(type, BPF_MAP_TYPE_LPM_TRIE);
31 __uint(max_entries, 65536);
32 __type(key, struct lpm_key);
33 __type(value, __u32);
34 __uint(map_flags, BPF_F_NO_PREALLOC);
35} whitelist_map SEC(".maps");
36
37/// LPM trie чёрного списка: IP-адреса источников для немедленного сброса.
38struct {
39 __uint(type, BPF_MAP_TYPE_LPM_TRIE);
40 __uint(max_entries, 65536);
41 __type(key, struct lpm_key);
42 __type(value, __u32);
43 __uint(map_flags, BPF_F_NO_PREALLOC);
44} blacklist_map SEC(".maps");
45
46/// Хэш-карта счётчиков дропов: количество отброшенных пакетов по source IP.
47struct {
48 __uint(type, BPF_MAP_TYPE_HASH);
49 __uint(max_entries, 65536);
50 __type(key, __u32);
51 __type(value, __u64);
52 __uint(map_flags, BPF_F_NO_PREALLOC);
53} drop_counter SEC(".maps");
54
55/// Точка входа XDP: фильтрует пакеты по картам whitelist и blacklist.
56/// @param[in] ctx Метаданные XDP (указатели на данные пакета).
57/// @return XDP_PASS или XDP_DROP.
58SEC("xdp")
59int xdp_blocker_func(struct xdp_md *ctx) {
60 void *data_end = (void *)(unsigned long long)ctx->data_end;
61 void *data = (void *)(unsigned long long)ctx->data;
62
63 struct ethhdr *eth = data;
64 if ((void *)(eth + 1) > data_end)
65 return XDP_PASS;
66
67 if (bpf_ntohs(eth->h_proto) != ETH_P_IP)
68 return XDP_PASS;
69
70 struct iphdr *ip = (struct iphdr *)(eth + 1);
71 if ((void *)(ip + 1) > data_end)
72 return XDP_PASS;
73
74 struct lpm_key key = {};
75 key.prefixlen = 32;
76 key.ip = ip->saddr;
77
78 if (bpf_map_lookup_elem(&whitelist_map, &key))
79 return XDP_PASS;
80
81 if (bpf_map_lookup_elem(&blacklist_map, &key)) {
82 __u64 *count = bpf_map_lookup_elem(&drop_counter, &ip->saddr);
83 if (count)
84 __sync_fetch_and_add(count, 1);
85 else {
86 __u64 one = 1;
87 bpf_map_update_elem(&drop_counter, &ip->saddr, &one, BPF_NOEXIST);
88 }
89 return XDP_DROP;
90 }
91
92 return XDP_PASS;
93}
94
95/// Лицензия BPF-программы (требуется верификатором ядра).
96char _license[] SEC("license") = "GPL";
struct @0 SEC(".maps")
LPM trie чёрного списка: IP-адреса источников для немедленного сброса.
__uint(type, BPF_MAP_TYPE_LPM_TRIE)
__type(key, struct lpm_key)
int xdp_blocker_func(struct xdp_md *ctx)
Ключ для LPM trie-карт: длина префикса + IP в network byte order.
__u32 prefixlen
Количество значащих битов (0-32).
__u32 ip
IP-адрес в network byte order (с маской).