验证丢弃任何包
先上代码
//#include <linux/bpf.h>
#include <uapi/linux/bpf.h>
#define SEC(NAME) __attribute__((section(NAME), used))
SEC("xdp")
int xdp_drop_the_world(struct xdp_md *ctx) {
return XDP_DROP;
}
char _license[] SEC("license") = "GPL";
用如下编译命令编译
clang -O2 -Wall -target bpf -I /usr/include/x86_64-linux-gnu/ -c xdp-drop.c -o xdp-drop.o
在Ubuntu-16.04 有编译错误
“error: use of undeclared identifier ‘XDP_DROP’”
修改代码头文件引用,
将 “#include <linux/bpf.h>” 改成 “#include <uapi/linux/bpf.h>”
拷贝内核头文件
sudo cp -rf /usr/src/linux-headers-4.15.18-041518/include/uapi/* /usr/include/uapi/
而在Ubuntu 18.04 可以直接用 #include <linux/bpf.h>
编译命令中的 “-I /usr/include/x86_64-linux-gnu/” 是确保引用asm下的头文件
用如下编译命令测试
ip link set dev eth0 xdp obj xdp-drop.o sec xdp
报错如下
Error: either "dev" is duplicate, or "xdp" is a garbage.
怀疑跟iproute2的版本有关,默认安装的iproute2版本过低,不支持xdp。
下载最新的iproute2-5.11.0,编译后,用以下命令验证,确认断网。
sudo /home/lbbxsxlz/workspace/iproute2-5.11.0/ip/ip link set dev eth0 xdp obj xdp-drop.o sec xdp verbose
Continuing without mounted eBPF fs. Too old kernel?
Prog section 'xdp' loaded (5)!
- Type: 6
- Instructions: 2 (0 over limit)
- License: GPL
Verifier analysis:
0: (b7) r0 = 1
1: (95) exit
processed 2 insns, stack depth 0
恢复网络:
sudo /home/lbbxsxlz/workspace/iproute2-5.11.0/ip/ip link set dev eth0 xdp off
使用docker验证
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
44cce8b245a7 lbbxsxlz/ubuntu_20.04_ext4 "/bin/bash" 3 weeks ago Up 21 hours test-show
启动docker
docker start test-show
确定docker容器的网卡
ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether e4:b9:7a:f7:78:2b brd ff:ff:ff:ff:ff:ff
3: wlan0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN mode DORMANT group default qlen 1000
link/ether 9c:b6:d0:c7:90:5d brd ff:ff:ff:ff:ff:ff
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 02:42:c5:99:cb:63 brd ff:ff:ff:ff:ff:ff
6: veth8935654@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
link/ether 4a:0f:73:3c:52:6c brd ff:ff:ff:ff:ff:ff link-netnsid 0
确认docker容器的ip
docker inspect test-show --format=''
{<nil> [] [] 3c0f4a2efb769323551e2e7a8f0b611e59ff310876a1850536bfa4a0b7226546 25e07e86937b07245d4ff5f94f6e0aa2da53d226b3d096cc1db21271169361b8 172.17.0.1 172.17.0.2 16 0 02:42:ac:11:00:02 map[]}
对网卡veth8935654操作:
首先ping 172.17.0.2
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.069 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.068 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.064 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.069 ms
加载xdp
sudo /home/lbbxsxlz/workspace/iproute2-5.11.0/ip/ip link set dev veth8935654 xdp obj xdp-drop.o sec xdp verbose
From 172.17.0.1 icmp_seq=80 Destination Host Unreachable
From 172.17.0.1 icmp_seq=81 Destination Host Unreachable
From 172.17.0.1 icmp_seq=82 Destination Host Unreachable
From 172.17.0.1 icmp_seq=83 Destination Host Unreachable
卸载xdp
sudo /home/lbbxsxlz/workspace/iproute2-5.11.0/ip/ip link set dev veth8935654 xdp obj off
64 bytes from 172.17.0.2: icmp_seq=98 ttl=64 time=0.043 ms
64 bytes from 172.17.0.2: icmp_seq=99 ttl=64 time=0.018 ms
64 bytes from 172.17.0.2: icmp_seq=100 ttl=64 time=0.017 ms
64 bytes from 172.17.0.2: icmp_seq=101 ttl=64 time=0.018 ms
验证丢弃ping包
先上代码
#include <uapi/linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/in.h>
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
#define htons(x) __cpu_to_be16(x)
#define SEC(NAME) __attribute__((section(NAME), used))
static int parse_ipv4(void *data, u64 nh_off, void *data_end)
{
struct iphdr *iph = data + nh_off;
if ((void *)(iph + 1) > data_end)
return 0;
return iph->protocol;
}
SEC("xdp-icmp")
int xdp_drop_icmp(struct xdp_md *ctx) {
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data;
u16 h_proto;
u64 nh_off;
u32 ipproto;
nh_off = sizeof(*eth);
if (data + nh_off > data_end)
return XDP_DROP;
h_proto = eth->h_proto;
if (h_proto == htons(ETH_P_IP)) {
ipproto = parse_ipv4(data, nh_off, data_end);
if (IPPROTO_ICMP == ipproto || 0 == ipproto)
return XDP_DROP;
}
return XDP_PASS;
}
char _license[] SEC("license") = "GPL";
编译:
clang -O2 -Wall -target bpf -I /usr/include/x86_64-linux-gnu/ -c xdp-drop-icmp.c -o xdp-drop-icmp.o
查看测试机IP,
ifconfig eth0
eth0 Link encap:以太网 硬件地址 e4:b9:7a:f7:78:2b
inet 地址:172.31.1.102 广播:172.31.255.255 掩码:255.255.0.0
inet6 地址: fe80::e6b9:7aff:fef7:782b/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 跃点数:1
接收数据包:68394871 错误:0 丢弃:0 过载:0 帧数:0
发送数据包:87729212 错误:0 丢弃:0 过载:0 载波:0
碰撞:0 发送队列长度:1000
接收字节:8468843173 (8.4 GB) 发送字节:38610498051 (38.6 GB)
中断:19
在外部网络ping测试机,
测试机加载程序,
sudo /home/lbbxsxlz/workspace/iproute2-5.11.0/ip/ip link set dev eth0 xdp obj xdp-drop-icmp.o sec xdp-icmp verbose
Continuing without mounted eBPF fs. Too old kernel?
Prog section 'xdp-icmp' loaded (5)!
- Type: 6
- Instructions: 19 (0 over limit)
- License: GPL
Verifier analysis:
0: (b7) r0 = 1
1: (61) r2 = *(u32 *)(r1 +4)
2: (61) r1 = *(u32 *)(r1 +0)
3: (bf) r3 = r1
4: (07) r3 += 14
5: (2d) if r3 > r2 goto pc+12
R0=inv1 R1=pkt(id=0,off=0,r=14,imm=0) R2=pkt_end(id=0,off=0,imm=0) R3=pkt(id=0,off=14,r=14,imm=0) R10=fp0
6: (bf) r3 = r1
7: (07) r3 += 34
8: (2d) if r3 > r2 goto pc+8
R0=inv1 R1=pkt(id=0,off=0,r=34,imm=0) R2=pkt_end(id=0,off=0,imm=0) R3=pkt(id=0,off=34,r=34,imm=0) R10=fp0
9: (71) r2 = *(u8 *)(r1 +13)
10: (67) r2 <<= 8
11: (71) r3 = *(u8 *)(r1 +12)
12: (4f) r2 |= r3
13: (57) r2 &= 65535
14: (55) if r2 != 0x8 goto pc+2
R0=inv1 R1=pkt(id=0,off=0,r=34,imm=0) R2=inv8 R3=inv(id=0,umax_value=255,var_off=(0x0; 0xff)) R10=fp0
15: (71) r1 = *(u8 *)(r1 +23)
16: (15) if r1 == 0x1 goto pc+1
R0=inv1 R1=inv(id=0,umax_value=255,var_off=(0x0; 0xff)) R2=inv8 R3=inv(id=0,umax_value=255,var_off=(0x0; 0xff)) R10=fp0
17: (b7) r0 = 2
18: (95) exit
from 16 to 18: R0=inv1 R1=inv1 R2=inv8 R3=inv(id=0,umax_value=255,var_off=(0x0; 0xff)) R10=fp0
18: (95) exit
from 14 to 17: safe
from 8 to 17: safe
from 5 to 18: safe
processed 23 insns, stack depth 0
测试机卸载程序,
sudo /home/lbbxsxlz/workspace/iproute2-5.11.0/ip/ip link set dev eth0 xdp off
验证结果如下图所示: