eBPF指定网口丢弃icmp报文
ubuntu 23.10
安装eBPF依赖
# 安装编译工具
apt install -y llvm clang
# 确认内核具有BTF支持,路径存在,内核没有BTF支持,使用vmlinux.h无法通过编译
ls /sys/kernel/btf
# 生成vmlinux.h
# apt install -y linux-tools-generic
apt install -y linux-tools-6.5.0-26-generic
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
eBPF丢弃icmp报文
拷贝github.com/cilium/ebpf/examples/headers目录,里面放入vmlinux.h。
代码结构
icmp/drop-icmp.c
#include "../headers/vmlinux.h"
#include "../headers/bpf_endian.h"
#include "../headers/bpf_helpers.h"
#define TC_ACT_SHOT 2
#define TC_ACT_OK 0
#define ETH_P_IP 0x0800
char __license[] SEC("license") = "Dual MIT/GPL";
SEC("tc")
int tc_deny_icmp(struct __sk_buff *skb) {
void *data_end = (void *)(long)skb->data_end;
void *data = (void *)(long)skb->data;
struct ethhdr *eth_hdr = data;
if ((void *)eth_hdr + sizeof(*eth_hdr) > data_end || eth_hdr->h_proto != bpf_htons(ETH_P_IP)) {
return TC_ACT_OK;
}
struct iphdr *ip_hdr = (void *)eth_hdr + sizeof(*eth_hdr);
if ((void *)ip_hdr + sizeof(*ip_hdr) > data_end) {
return TC_ACT_OK;
}
if (ip_hdr->protocol == IPPROTO_ICMP) {
return TC_ACT_SHOT;
}
return TC_ACT_OK;
}
编译eBPF程序并加载
# 加-c允许没有main函数,加-target bpf生成ELF,编译优化级别-O2,加-g生成BTF
clang -c icmp/drop-icmp.c -o icmp/drop-icmp.o -target bpf -O2 -g
tc qdisc add dev ens33 clsact
tc filter add dev ens33 egress bpf da obj icmp/drop-icmp.o sec tc
tc filter add dev ens33 ingress bpf da obj icmp/drop-icmp.o sec tc
加载eBPF后无法ping通。