Skip to content

Netfilter 核心框架

1. 模块架构

1.1 功能概述

Netfilter 是 Linux 内核的包过滤框架,提供了在网络协议栈的关键位置拦截和处理数据包的能力。

1.2 关键源文件

文件作用
net/netfilter/core.cNetfilter 核心
net/netfilter/nf_hook.c钩子实现
include/linux/netfilter.hNetfilter 定义
include/linux/netfilter_ipv4.hIPv4 特定定义

2. 钩子点

2.1 IPv4 钩子点

c
// include/linux/netfilter_ipv4.h
enum nf_inet_hooks {
    NF_INET_PRE_ROUTING,   // 路由前 - 接收包
    NF_INET_LOCAL_IN,     // 本地输入 - 目的为本地
    NF_INET_FORWARD,      // 转发 - 目的为其他主机
    NF_INET_LOCAL_OUT,    // 本地输出 - 本地生成
    NF_INET_POST_ROUTING, // 路由后 - 发送包
    NF_INET_NUMHOOKS
};

2.2 IPv6 钩子点

c
// include/linux/netfilter_ipv6.h
enum nf_inet_hooks {
    NF_INET_PRE_ROUTING,
    NF_INET_LOCAL_IN,
    NF_INET_FORWARD,
    NF_INET_LOCAL_OUT,
    NF_INET_POST_ROUTING,
    NF_INET_NUMHOOKS
};

3. 钩子结构

3.1 struct nf_hook_ops

c
// include/linux/netfilter.h:62
struct nf_hook_ops {
    struct list_head list;    // 链表

    // 钩子回调
    nf_hookfn *hook;          // 回调函数
    struct net_device *dev;    // 设备 (NULL 表示全部)
    void *priv;               // 私有数据

    u_int8_t pf;             // 协议族 (NFPROTO_*)
    unsigned int hooknum;     // 钩子编号
    int priority;             // 优先级 (越小越先)
};

3.2 回调函数

c
// include/linux/netfilter.h:46
typedef unsigned int nf_hookfn(void *priv,
                               struct sk_buff *skb,
                               const struct nf_hook_state *state);

struct nf_hook_state {
    unsigned int hook;
    u_int8_t pf;
    struct net_device *in;
    struct net_device *out;
    struct sock *sk;
    struct net *net;
};

4. 钩子注册

4.1 nf_register_net_hook()

c
// net/netfilter/core.c:258
int nf_register_net_hook(struct net *net, const struct nf_hook_ops *ops)
{
    // 1. 分配 nf_hook_entries
    // 2. 添加到钩子链表
    // 3. 返回
}

4.2 nf_unregister_net_hook()

c
// net/netfilter/core.c:276
void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *ops)
{
    // 从链表移除
    // 同步等待
}

5. 钩子调用

5.1 nf_hook_slow()

c
// net/netfilter/nf_hook.c:96
int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
{
    struct nf_hook_entries *entries;
    unsigned int verdict;
    int i;

    // 获取钩子条目
    entries = rcu_dereference(state->net->nf.hooks_entries[state->pf][state->hook]);

    // 遍历所有钩子
    for (i = 0; i < entries->num_hook_entries; i++) {
        verdict = entries->hooks[i].hook(entries->hooks[i].priv, skb, state);

        if (verdict != NF_ACCEPT) {
            if (verdict != NF_REPEAT)
                return verdict;
            i--;
        }
    }

    return NF_ACCEPT;
}

6. x_tables 框架

6.1 表结构

c
// net/netfilter/x_tables.c
struct xt_table {
    struct list_head list;          // 表链表
    unsigned int valid_hooks;       // 有效钩子掩码
    struct xt_table_info *private;  // 表信息
    const struct xt_table_ops *ops;
    u_int8_t af;                   // 地址族 (AF_INET/AF_INET6)
    struct module *me;
};

6.2 规则结构

c
// include/uapi/linux/netfilter/x_tables.h
struct xt_entry_match {
    __u16 match_size;           // 匹配大小
    char name[XT_FUNCTION_MAXNAMELEN];  // 匹配名称
    __u8 revision;              // 修订版
    __u8 private[0];            // 匹配数据
};

struct xt_entry_target {
    __u16 target_size;         // 目标大小
    char name[XT_FUNCTION_MAXNAMELEN];  // 目标名称
    __u8 revision;              // 修订版
    __u8 private[0];            // 目标数据
};

7. iptables 命令

7.1 iptables 链

钩子点用途
PREROUTINGNF_INET_PRE_ROUTING路由前处理
INPUTNF_INET_LOCAL_IN本地输入
FORWARDNF_INET_FORWARD转发
OUTPUTNF_INET_LOCAL_OUT本地输出
POSTROUTINGNF_INET_POST_ROUTING路由后处理

7.2 内建目标

c
// net/netfilter
NF_DROP       // 丢弃包
NF_ACCEPT     // 接受包
NF_STOLEN     // 接管包,不继续处理
NF_QUEUE      // 排队到用户空间
NF_REPEAT     // 重复当前钩子
NF_CONTINUE   // 继续下一个钩子

8. 连接跟踪

8.1 连接跟踪结构

c
// net/netfilter/nf_conntrack.h
struct nf_conn {
    struct nf_conntrack_tuple_hash __rcu *tuplehash[IP_CT_DIR_MAX];
    atomic_t use;                      // 引用计数
    void *sfe_entry;                  // 状态
    unsigned long status;              // 状态
    struct sk_buff *sfe_skb;         // 相关 skb
    struct nf_conn *master;          // 主连接
    struct timer_list timeout;        // 超时定时器
    ...
};

8.2 连接状态

c
// include/uapi/linux/netfilter/nf_conntrack_common.h
enum ip_conntrack_status {
    IPS_EXPECTED,        // 预期连接
    IPS_SEEN_REPLY,     // 已见回复
    IPS_ASSURED,        // 确认连接
    IPS_CONFIRMED,      // 已确认
    IPS_SRC_NAT,        // 源 NAT
    IPS_DST_NAT,        // 目的 NAT
    IPS_SEQ_ADJUST,     // 序列号调整
    IPS_SRC_NAT_DONE,   // 源 NAT 完成
    IPS_DST_NAT_DONE,   // 目的 NAT 完成
    IPS_DYING,          // 正在消失
    IPS_FIXED_TIMEOUT,  // 固定超时
};

9. NAT

9.1 NAT 钩子

c
// net/ipv4/netfilter/nf_nat_rule.c
static unsigned int
nf_nat_rule_local_out(unsigned int hooknum, struct sk_buff *skb,
                     const struct net_device *out, ...)
{
    return nf_nat_rule_hook(skb, hooknum, out, NULL, AF_INET);
}

9.2 NAT 转换

c
// net/netfilter/nf_nat_core.c
static int nf_nat_packet(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
                        unsigned int hooknum, struct sk_buff *skb)
{
    enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);

    // 获取源/目的地址和端口
    // 应用 NAT 转换
    // 更新校验和
}

10. 快速路径

10.1 nf_hookfn 快速路径

c
// net/netfilter/nf_hook.c
static int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
{
    // 遍历所有注册的钩子
    // 返回最终裁决
}

10.2 批量处理

c
// net/netfilter/nfnetlink_hook.c
static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
    // 处理来自用户空间的 netlink 消息
    // 添加/删除钩子
}

基于 VitePress 构建