You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确配置环境编译基于Netfilter Hooks的BPF程序?

问题描述

我在Ubuntu 24.04(Linux内核6.8)上编写了一个BPF程序,目的是丢弃本地进出数据包,只允许转发数据包,计划用bpftool加载。程序代码如下:

#include <linux/bpf.h>
  
#include <bpf/bpf_endian.h>
#include <bpf/bpf_helpers.h>
#include <linux/netfilter.h>

SEC("netfilter") /* hint to BPF loader that this is a netfilter BPF program */
int filter(const struct bpf_nf_ctx *ctx) {
  const struct nf_hook_state *state = ctx->state;
  unsigned int routing_decision = state->hook;

  if (routing_decision == NF_INET_LOCAL_IN ||
      routing_decision == NF_INET_LOCAL_OUT)
    return NF_DROP;

  return NF_ACCEPT;
}

char LICENSE[] SEC("license") = "GPL";

第一次编译错误

执行编译命令:

clang --target=bpf -O2 -Wall -I/usr/include/x86_64-linux-gnu -c filter.c -o filter.bpf.o

得到错误输出:

filter.c:8:27: warning: declaration of 'struct bpf_nf_ctx' will not be visible outside of this function [-Wvisibility]
    8 | int filter(const struct bpf_nf_ctx *ctx) {
      |                           ^
filter.c:9:42: error: incomplete definition of type 'struct bpf_nf_ctx'
    9 |   const struct nf_hook_state *state = ctx->state;
      |                                       ~~~^
filter.c:8:27: note: forward declaration of 'struct bpf_nf_ctx'
    8 | int filter(const struct bpf_nf_ctx *ctx) {
      |                           ^
filter.c:10:29: error: incomplete definition of type 'struct bpf_nf_ctx'
   10 |   int routing_decision = ctx->state->hook;
      |                          ~~~^
filter.c:8:27: note: forward declaration of 'struct bpf_nf_ctx'
    8 | int filter(const struct bpf_nf_ctx *ctx) {
      |                           ^
1 warning and 2 errors generated.

添加头文件后的编译错误

我发现struct bpf_nf_ctx定义在nf_bpf_link.h中,于是添加了#include <net/netfilter/nf_bpf_link.h>,并调整编译命令添加内核头文件路径,但又出现错误:

clang --target=bpf -O2 -Wall -I/usr/include/x86_64-linux-gnu -I/usr/src/linux-headers-6.8.0-48/include -c filter.c -o filter.bpf.o

错误输出:

In file included from filter.c:1:
In file included from /usr/src/linux-headers-6.8.0-48/include/linux/bpf.h:8:
In file included from /usr/src/linux-headers-6.8.0-48/include/uapi/linux/filter.h:9:
/usr/src/linux-headers-6.8.0-48/include/linux/compiler.h:251:10: fatal error: 'asm/rwonce.h' file not found
  251 | #include <asm/rwonce.h>
      |          ^~~~~~~~~~~~~~
1 error generated.
make: *** [Makefile:7: all] Error 1
解决方案

针对你的问题,需要从头文件依赖和编译环境配置两方面调整:

1. 修正BPF程序的头文件与逻辑

Netfilter BPF程序不能直接访问内核内部头文件(如nf_bpf_link.h),也不能直接读取bpf_nf_ctx->state,必须使用标准BPF helper函数获取上下文。修改后的程序代码如下:

#include <linux/bpf.h>
#include <bpf/bpf_endian.h>
#include <bpf/bpf_helpers.h>
#include <linux/netfilter.h>
#include <bpf/bpf_tracing.h>  // 提供bpf_nf_ctx和bpf_get_nf_ctx的定义

SEC("netfilter")
int filter(const struct bpf_nf_ctx *ctx) {
    struct nf_hook_state state;
    // 通过标准helper函数获取Netfilter hook状态
    if (bpf_get_nf_ctx(ctx, &state, sizeof(state)) != 0)
        return NF_ACCEPT;

    unsigned int routing_decision = state.hook;

    if (routing_decision == NF_INET_LOCAL_IN ||
        routing_decision == NF_INET_LOCAL_OUT)
        return NF_DROP;

    return NF_ACCEPT;
}

char LICENSE[] SEC("license") = "GPL";

2. 正确配置编译环境

编译BPF程序无需手动引用完整内核源码头文件,使用libbpf提供的头文件即可,先安装必要依赖:

sudo apt install clang llvm libbpf-dev linux-tools-common linux-tools-$(uname -r)

然后用以下命令编译,无需额外指定内核头文件路径:

clang --target=bpf -O2 -Wall -c filter.c -o filter.bpf.o

3. 加载并验证程序

编译完成后,使用bpftool加载到Netfilter钩子:

# 加载程序到BPF文件系统
sudo bpftool prog load filter.bpf.o /sys/fs/bpf/filter

# 挂载到Netfilter各个钩子点
sudo bpftool netfilter add hook input priority 0 prog name filter
sudo bpftool netfilter add hook output priority 0 prog name filter
sudo bpftool netfilter add hook forward priority 0 prog name filter

内容的提问来源于stack exchange,提问作者Orian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 08:30:21