使用ebpf禁止ICMP报文
本文介绍如何使用c语言与bpftools工具编写一个拒绝icmp协议报文的ebpf程序,本文需要你对c语言与ebpf具有一定基础
前言
ebpf入门网站,请自行阅读官网入门,本文不再赘述:
环境
IP: 192.168.31.200
内核: 6.8.0-45-generic
编写内核程序
完整代码如下:
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/icmp.h>
#include "bpf/bpf_helpers.h"
SEC("xdp")
int block_ping(struct xdp_md *ctx) {
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct ethhdr *eth = data;
struct iphdr *ip;
struct icmphdr *icmp;
// 检查以太网头部是否在包的范围内
if ((void *)(eth + 1) > data_end) {
return XDP_PASS;
}
// 检查是否为 IPv4 数据包
if (eth->h_proto != __constant_htons(ETH_P_IP)) {
return XDP_PASS;
}
// 获取 IP 头
ip = (struct iphdr *)(eth + 1);
// 检查 IP 头部是否在包的范围内
if ((void *)(ip + 1) > data_end) {
return XDP_PASS;
}
// 检查是否为 ICMP 协议 (ping 使用的协议)
if (ip->protocol != IPPROTO_ICMP) {
return XDP_PASS;
}
// 获取 ICMP 头
icmp = (struct icmphdr *)(ip + 1);
// 检查 ICMP 头部是否在包的范围内
if ((void *)(icmp + 1) > data_end) {
return XDP_PASS;
}
// 检查是否为 ICMP 回显请求 (ping)
if (icmp->type == ICMP_ECHO) {
// 打印调试信息
bpf_printk("Dropping ICMP ping packet\n");
// 丢弃 ping 数据包
return XDP_DROP;
}
return XDP_PASS;
}
char LICENSE[] SEC("license") = "GPL";
编译为ebpf字节码
为了方便使用Makefile调用clang将c源代码编译为ebpf字节码,Makefile文件内容如下
# Compiler and flags
CLANG := clang
CFLAGS := -target bpf -g -O2
# Include directory for headers
INCLUDES := -I /usr/include/x86_64-linux-gnu
# Source file and output file passed as external variables
src ?= test.c
OBJ := $(patsubst %.c,%.o,$(src))
# Default rule
all: $(OBJ)
# Rule to compile .c file to .o
%.o: %.c
$(CLANG) $(CFLAGS) $(INCLUDES) -c $< -o $@
# Clean rule to remove generated object files
clean:
rm -f $(OBJ)
.PHONY: all clean
使用如下命令开始编译
make src=test.c
编译成功后,会在当前目录发现test.o文件,这个文件就是编译过后的ebpf字节码文件
bpftools加载
使用bpftools加载ebpf程序到网卡上
# load
bpftools prog load test.o /sys/fs/bpf/test
# 查看id
bpftools prog
# 加载到网卡 假设id为66
bpftools attach net xdp dev ens33 id 66
查看日志打印
在ebpf程序中使用bpf_printk函数,会把内容输出到如下文件
/sys/kernel/debug/tracing/trace_pipe
挂载后测试ping
已经无法ping通主机
查看网卡加载情况
id为66的xdp程序已成功挂载到ens33网卡
取消挂载
同样使用bpftools程序取消挂载
bpftool net detach xdp dev ens33