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 <bpf/bpf_endian.h>
15#include <bpf/bpf_helpers.h>
16#include <linux/bpf.h>
17#include <linux/if_ether.h>
18#include <linux/ip.h>
19
20/// Ключ для LPM trie-карт: длина префикса + IP в network byte order.
21struct lpm_key {
22 __u32 prefixlen; ///< Количество значащих битов (0-32).
23 __u32 ip; ///< IP-адрес в network byte order (с маской).
24};
25
26/// LPM trie белого списка: IP-адреса источников, пропускаемые без проверки
27/// чёрного списка.
28struct {
29 __uint(type, BPF_MAP_TYPE_LPM_TRIE);
30 __uint(max_entries, 65536);
31 __type(key, struct lpm_key);
32 __type(value, __u32);
33 __uint(map_flags, BPF_F_NO_PREALLOC);
34} whitelist_map SEC(".maps");
35
36/// LPM trie чёрного списка: IP-адреса источников для немедленного сброса.
37struct {
38 __uint(type, BPF_MAP_TYPE_LPM_TRIE);
39 __uint(max_entries, 65536);
40 __type(key, struct lpm_key);
41 __type(value, __u32);
42 __uint(map_flags, BPF_F_NO_PREALLOC);
43} blacklist_map SEC(".maps");
44
45/// Хэш-карта счётчиков дропов: количество отброшенных пакетов по source IP.
46struct {
47 __uint(type, BPF_MAP_TYPE_HASH);
48 __uint(max_entries, 65536);
49 __type(key, __u32);
50 __type(value, __u64);
51 __uint(map_flags, BPF_F_NO_PREALLOC);
52} drop_counter SEC(".maps");
53
54/// Точка входа XDP: фильтрует пакеты по картам whitelist и blacklist.
55/// @param[in] ctx Метаданные XDP (указатели на данные пакета).
56/// @return XDP_PASS или XDP_DROP.
57SEC("xdp")
58int xdp_blocker_func(struct xdp_md *ctx) {
59 void *data_end = (void *)(unsigned long long)ctx->data_end;
60 void *data = (void *)(unsigned long long)ctx->data;
61
62 struct ethhdr *eth = data;
63 if ((void *)(eth + 1) > data_end)
64 return XDP_PASS;
65
66 if (bpf_ntohs(eth->h_proto) != ETH_P_IP)
67 return XDP_PASS;
68
69 struct iphdr *ip = (struct iphdr *)(eth + 1);
70 if ((void *)(ip + 1) > data_end)
71 return XDP_PASS;
72
73 struct lpm_key key = {};
74 key.prefixlen = 32;
75 key.ip = ip->saddr;
76
77 if (bpf_map_lookup_elem(&whitelist_map, &key))
78 return XDP_PASS;
79
80 if (bpf_map_lookup_elem(&blacklist_map, &key)) {
81 __u64 *count = bpf_map_lookup_elem(&drop_counter, &ip->saddr);
82 if (count)
83 __sync_fetch_and_add(count, 1);
84 else {
85 __u64 one = 1;
86 bpf_map_update_elem(&drop_counter, &ip->saddr, &one, BPF_NOEXIST);
87 }
88 return XDP_DROP;
89 }
90
91 return XDP_PASS;
92}
93
94/// Лицензия BPF-программы (требуется верификатором ядра).
95char _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 (с маской).