本篇文章参考《Linux Observability with BPF》中第7章的例子,主要功能是借助于ip命令作为前端,对其他主机访问tcp的8000端口进行限制,这里需要使用较新版本的iproute2软件工具包.
1. 下载编译iproute2 工具包,使用最新的ip命令,支持配置xdp
git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
在编译iproute2时,需要开启支持libbpf的选项信息,在iproute2目录下配置使用下面的配置选项信息
./configure --libbpf_force=on --LIBBPF_DIR=/usr/local/lib64
执行上面的命令,可能出现下面的错误信息,
确定libbpf的pk-config配置文件位置,/usr/local/lib64/pkgconfig/libbpf.pc 使用
export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig/ 导入libbpf的配置文件,
使用pkg-config --list-all | grep libbpf 查看是否配置libbpf
2. 编写bpf程序
本bpf程序对于访问本机的tcp的协议的8000端口进行限制,
点击(此处)折叠或打开
-
#include <linux/bpf.h>
-
-
#include <linux/if_ether.h>
-
-
#include <linux/in.h>
-
-
#include <linux/ip.h>
-
-
#include <linux/if_packet.h>
-
-
#include <bpf/bpf_helpers.h>
-
-
#include <linux/if_vlan.h>
-
-
#include <linux/types.h>
-
-
#include <linux/tcp.h>
-
-
#include <linux/udp.h>
-
-
#include <bpf/bpf_helpers.h>
-
-
#include <bpf/bpf_endian.h>
-
-
-
-
static __always_inline int get_dport(void *trans_data, void *data_end, int protocol)
-
-
{
-
-
struct tcphdr *th;
-
-
struct udphdr *uh;
-
-
-
switch (protocol) {
-
-
case IPPROTO_TCP:
-
-
th = (struct tcphdr *)trans_data;
-
-
if ((void*)(th + 1) > data_end)
-
-
return -1;
-
-
return th->dest;
-
-
case IPPROTO_UDP:
-
-
uh = (struct udphdr *)trans_data;
-
-
if ((void *)(uh + 1) > data_end)
-
-
return -1;
-
-
return uh->dest;
-
-
default:
-
-
return 0;
-
-
}
-
-
-
}
-
-
-
SEC("mysection")
-
-
int myprogram(struct xdp_md *ctx) {
-
-
void *data = (void *)(long)ctx->data;
-
-
void *data_end = (void *)(long)ctx->data_end;
-
-
char fmt[] = "source = %d \n";
-
-
struct iphdr *ip;
-
-
int dport;
-
-
int hdport;
-
-
struct ethhdr *eth = data;
-
-
struct iphdr *iph = data + sizeof(struct ethhdr);
-
-
-
if ((void *)(iph + 1) > data_end) {
-
-
return XDP_DROP;
-
-
}
-
-
-
dport = get_dport(iph + 1, data_end,iph->protocol);
-
-
-
if (dport == -1 || dport == bpf_htons(8000)) {
-
-
bpf_trace_printk(fmt,sizeof(fmt),bpf_ntohs(dport));
-
-
return XDP_DROP;
-
-
}
-
-
-
return XDP_PASS;
-
-
}
-
- char _license [] SEC ("license") = "GPL";
使用下面的命令进行编译:clang -g -c -O2 -target bpf -c program.c -o program.o
编译完成后,使用下面的ip命令对某个网卡进行价值xdp文件。
ip link set dev eth0 xdp obj program.o sec mysection
通过上面的命令加载后,在接口上出现加载的xdp的类型和ID,表明加载成功。
使用python3 -m http.server在本地主机上其中http服务器,并监听8000端口。
使用另一台主机上使用nmap命令扫描对方监听的端口。nmap -sS 10.9.4.222,扫描结果如下:
ip link set dev eth0 xdp off 关闭加载的xdp程序。再次使用nmap扫描