3. iptables与Netfilter关系:用户态工具、内核态匹配与目标、表与链映射

iptables 是 Linux 系统中最经典的防火墙配置工具,但它本身并不执行数据包过滤。真正完成过滤、修改、跟踪等工作的,是内核中的 Netfilter 框架。iptables 只是 Netfilter 的用户态配置前端,通过 setsockopt/getsockopt 系统调用与内核态 xtables 模块通信。

核心认知:iptables 是命令解析器 + 规则下发通道;Netfilter 是规则执行引擎。两者通过 struct xt_table 和 struct xt_entry 在内核中完成映射。

3.1 整体架构:用户态 ↔ 内核态

iptables 命令在用户态解析规则,通过 getsockopt / setsockopt 系统调用(协议族 AF_INET,选项 IPT_SO_SET_REPLACE / IPT_SO_GET_INFO)将规则集传递给内核。内核中的 xtables 核心层 负责将规则挂载到对应 Netfilter 钩子点。

iptables ↔ Netfilter 整体架构 iptables 命令 libiptc / libxtables setsockopt xtables 核心层 struct xt_table 注册 NF_INET_PRE_ROUTING NF_INET_LOCAL_IN NF_INET_FORWARD / OUT / POST struct xt_entry 规则链 匹配(match) + 目标(target) 用户态流程 1. iptables 解析命令行参数 2. 组装 struct ipt_replace 3. setsockopt 下发到内核

3.2 表(table)与链(chain)的映射关系

iptables 中的表对应内核中的 struct xt_table,链对应内核中挂载到特定 Netfilter 钩子点的规则列表。每个表可以注册到多个钩子点,每个钩子点可以被多个表共享。

表名 内核结构 注册的钩子点 功能
filter xt_filter_table LOCAL_IN, FORWARD, LOCAL_OUT 数据包过滤(默认表)
nat xt_nat_table PREROUTING, POSTROUTING, LOCAL_OUT 网络地址转换
mangle xt_mangle_table PREROUTING, LOCAL_IN, FORWARD, LOCAL_OUT, POSTROUTING 数据包修改(TOS、TTL 等)
raw xt_raw_table PREROUTING, LOCAL_OUT 连接跟踪豁免(NOTRACK)
security xt_security_table LOCAL_IN, FORWARD, LOCAL_OUT SELinux 安全策略标记
优先级顺序:在同一钩子点,多个表的执行顺序固定为:raw → mangle → nat (PREROUTING) → filter → security。这是由内核中 xt_table 的 priority 字段决定的。

3.3 内核态 xtables 匹配(match)与目标(target)

每条 iptables 规则由匹配条件和目标动作组成。在内核中,它们分别对应 xt_match 和 xt_target 结构体,以内核模块形式动态加载。

内核 xtables 匹配与目标结构 struct xt_entry (一条规则) ipt_entry + ip6t_entry 头部 struct xt_entry_match match->match() 回调函数 struct xt_entry_target target->target() 回调函数 xt_conntrack.ko xt_tcpudp.ko xt_DNAT.ko xt_LOG.ko

3.3.1 匹配模块(match)

匹配模块负责检查数据包是否满足特定条件。内核通过 struct xt_match 注册,关键字段包括:

  • name:匹配名称,如 "tcp"、"conntrack"、"state"
  • family:协议族(NFPROTO_IPV4 / NFPROTO_IPV6)
  • match:核心回调函数,返回 true/false 决定是否匹配
  • checkentry:规则插入时校验参数合法性
/* 内核 xt_match 结构体核心定义 (include/linux/netfilter/x_tables.h) */
struct xt_match {
    const char             *name;
    u8                      revision;
    bool                    (*match)(const struct sk_buff *skb,
                                     struct xt_action_param *par);
    int                     (*checkentry)(const struct xt_mtchk_param *par);
    void                    (*destroy)(const struct xt_mtdtor_param *par);
    struct module          *me;
    const char             *table;
    unsigned int            matchsize;
    unsigned int            hooks;
    unsigned short          proto;
    unsigned short          family;
    /* ... */
};

3.3.2 目标模块(target)

目标模块定义匹配成功后执行的动作。常见目标包括 ACCEPT、DROP、LOG、DNAT、SNAT、MASQUERADE 等。

目标名称 内核模块 动作说明 返回值
ACCEPT 内置于核心 允许数据包通过,终止当前表遍历 NF_ACCEPT
DROP 内置于核心 丢弃数据包,不回复 NF_DROP
LOG xt_LOG.ko 记录日志到内核 ring buffer,继续匹配 XT_CONTINUE
DNAT xt_DNAT.ko 修改目的 IP/端口(PREROUTING 链) NF_ACCEPT
SNAT xt_SNAT.ko 修改源 IP/端口(POSTROUTING 链) NF_ACCEPT
MASQUERADE xt_MASQUERADE.ko 动态 SNAT(用于 PPPoE 等动态 IP) NF_ACCEPT
CT xt_CT.ko 手动指定连接跟踪行为 NF_ACCEPT
关键区别:ACCEPT/DROP 是判决目标,直接返回 Netfilter 判决值(NF_ACCEPT/NF_DROP);LOG/ULOG 是非判决目标,返回 XT_CONTINUE 让规则继续遍历。自定义目标模块必须明确返回语义。

3.4 表与链的内核注册机制

每个表在内核中通过 xt_register_table() 注册,指定其所属的钩子点和优先级。链是表内部的规则列表,通过 struct xt_table_info 管理。

/* 内核 filter 表注册示例 (net/ipv4/netfilter/iptable_filter.c) */
static const struct xt_table packet_filter = {
    .name       = "filter",
    .valid_hooks = FILTER_VALID_HOOKS,  /* 位图:LOCAL_IN | FORWARD | LOCAL_OUT */
    .me         = THIS_MODULE,
    .af         = NFPROTO_IPV4,
    .priority   = NF_IP_PRI_FILTER,     /* 优先级值,决定表在钩子点的执行顺序 */
};

static int __init iptable_filter_init(void)
{
    return xt_register_table(net, &packet_filter, &filter_ops);
}

3.5 规则遍历流程:从用户态到内核态

  1. 用户态解析:iptables 解析命令行,构建 struct ipt_replace 结构体,包含所有规则条目。
  2. 系统调用:通过 setsockopt(IPT_SO_SET_REPLACE) 将规则集传入内核。
  3. 内核校验:do_replace() 函数校验规则合法性,调用各匹配/目标的 checkentry。
  4. 规则挂载:将规则链挂入对应表的 xt_table_info 中,替换旧规则集。
  5. 钩子触发:数据包到达 Netfilter 钩子点时,nf_hook_slow() 遍历该钩子点上的所有表,按优先级执行规则。
  6. 规则匹配:对每条规则,依次调用所有匹配模块的 match(),全部通过后执行目标模块的 target()。
数据包在钩子点的表遍历顺序 NF_INET_PRE_ROUTING 钩子点 raw 表 (优先级 -300) mangle 表 (优先级 -150) nat 表 (优先级 -100) 返回 NF_ACCEPT 或 NF_DROP 遍历规则 • 每个表按优先级从小到大执行(数值越小优先级越高) • 同一表内按规则顺序遍历,匹配则执行目标,不匹配则继续下一条

3.6 关键数据结构映射总结

iptables 概念 内核数据结构 说明
表 (table) struct xt_table 包含表名、有效钩子点位图、优先级
链 (chain) struct xt_table_info 中的规则数组 每个钩子点对应一个规则链,链是规则数组的切片
规则 (rule) struct xt_entry / struct ipt_entry 包含匹配段和目标段,通过偏移量链接
匹配 (match) struct xt_entry_match + struct xt_match 匹配条件,可叠加多个
目标 (target) struct xt_entry_target + struct xt_target 动作定义,每条规则只有一个目标
钩子点 nf_hook_ops 表通过 xt_table 注册到钩子点
开发启示:编写自定义 Netfilter 模块时,你实际上是在注册 xt_match 或 xt_target,而不是直接操作钩子点。iptables 用户态工具会自动将你的模块与表/链关联。理解这套映射关系,是开发高效内核模块的基础。