4. iptables与Netfilter框架

在 Envoy 透明代理场景中,流量劫持的核心底层依赖 Linux 内核的 Netfilter 框架及其用户态配置工具 iptables。理解 iptables 的“五链四表”结构、数据包在内核中的流转路径以及规则的匹配顺序,是正确配置透明代理劫持规则的前提。

4.1 Netfilter 框架与 iptables 的关系

Netfilter 是 Linux 内核内部的一组钩子(Hook)函数,允许内核模块在网络协议栈的关键路径上注册回调函数。iptables 则是用户空间用于配置这些钩子规则的工具。两者关系如下:

组件 层级 作用
Netfilter 内核空间 提供 5 个钩子点(NF_IP_PRE_ROUTING, NF_IP_LOCAL_IN, NF_IP_FORWARD, NF_IP_LOCAL_OUT, NF_IP_POST_ROUTING),拦截并处理数据包。
iptables 用户空间 通过 setsockopt/getsockopt 系统调用,将规则下发到内核的 Netfilter 规则表中。
内核模块 内核空间 如 xtables、nf_conntrack 等,提供具体的匹配和目标(如 REDIRECT、DNAT、TPROXY)。
透明代理关键点:Envoy 透明代理主要依赖 TPROXY 或 REDIRECT 目标,这两个目标均在内核 Netfilter 钩子点(通常是 PREROUTING 或 OUTPUT)上注册,实现流量拦截。

4.2 五链四表结构

iptables 的规则组织方式可以概括为“四张表”和“五条链”。表是功能的分类,链是数据包流经的检查点。

4.2.1 四张表(Tables)

表名 优先级 主要功能 常用目标
raw 1(最高) 配置连接跟踪豁免(NOTRACK),优先级最高。 NOTRACK
mangle 2 修改数据包头部字段(如 TOS、TTL、MARK)。 MARK, TPROXY, DSCP
nat 3 网络地址转换(DNAT、SNAT、REDIRECT)。 DNAT, SNAT, REDIRECT, MASQUERADE
filter 4(最低) 数据包过滤(允许/拒绝),默认表。 ACCEPT, DROP, REJECT, LOG

4.2.2 五条链(Chains)

每条链对应 Netfilter 框架中的一个钩子点,数据包在特定阶段会依次经过这些链上的规则检查。

  • PREROUTING:数据包进入网络协议栈后,路由决策前。适用于 DNAT、REDIRECT、TPROXY。
  • INPUT:路由决策后,数据包目的为本机。适用于过滤发往本机的流量。
  • FORWARD:路由决策后,数据包目的为其他主机(本机作为路由器)。适用于转发过滤。
  • OUTPUT:本机进程发出的数据包,路由决策前。适用于拦截本机发出的流量。
  • POSTROUTING:数据包即将离开本机前。适用于 SNAT、MASQUERADE。

4.3 数据包流转路径与规则匹配顺序

数据包在 iptables 中的流转路径遵循严格的顺序。理解这个路径是配置透明代理规则的基础。

核心原则:数据包按“链”的顺序依次经过,在每个链上按“表”的优先级(raw → mangle → nat → filter)依次检查规则。一旦在某条规则中匹配并执行了“最终目标”(如 ACCEPT、DROP、RETURN),则停止该链后续规则的检查。
数据包流转路径与 iptables 链/表匹配顺序 网络入口 PREROUTING 链 raw → mangle → nat 路由决策 目的为本机 INPUT 链 mangle → filter 本机进程 目的为转发 FORWARD 链 mangle → filter POSTROUTING 链 mangle → nat 网络出口 OUTPUT 链 raw → mangle → nat → filter 路由决策 到 POSTROUTING 说明: 数据包从网络入口进入,依次经过 PREROUTING → 路由决策 → (INPUT 或 FORWARD) → POSTROUTING → 网络出口。 本机发出的数据包从 OUTPUT 链开始,经过路由决策后进入 POSTROUTING 链。

4.4 规则匹配顺序详解

规则匹配顺序遵循“链内顺序匹配,链间固定顺序”的原则。理解这一点对于避免规则冲突至关重要。

4.4.1 链内匹配顺序

在一条链内部,规则按照从上到下的顺序依次匹配。一旦匹配某条规则并执行了目标(如 ACCEPT、DROP、RETURN、REDIRECT),则停止该链后续规则的检查。如果所有规则都不匹配,则执行该链的默认策略(Policy)。

4.4.2 链间匹配顺序

数据包在不同链之间的流转顺序是固定的,由内核协议栈决定。以透明代理最常见的场景——拦截发往本机的流量为例:

  1. PREROUTING 链(raw → mangle → nat):在此处使用 REDIRECT 或 TPROXY 目标,将目标端口重定向到 Envoy 监听的端口。
  2. 路由决策:内核根据修改后的目标 IP 和端口重新决策,此时数据包目的变为本机。
  3. INPUT 链(mangle → filter):数据包进入本机协议栈,Envoy 进程在此处接收流量。
透明代理配置陷阱:如果在 PREROUTING 链中使用 REDIRECT 目标,必须确保 Envoy 监听的端口与原始目标端口不同,否则会形成重定向循环。TPROXY 目标通过保留原始目标地址避免了此问题,但需要额外的路由策略配合。

4.5 透明代理场景下的典型规则链

在 Envoy 透明代理中,最常操作的链是 PREROUTING(拦截入站流量)和 OUTPUT(拦截本机发出的流量)。以下是一个典型的规则配置示例:

# 1. 在 PREROUTING 链的 nat 表中,将目标端口 80 和 443 的 TCP 流量重定向到 Envoy 的 15001 端口
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 15001
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 15001

# 2. 在 OUTPUT 链的 nat 表中,拦截本机发出的流量(排除 Envoy 自身发出的流量,避免循环)
iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 15001
iptables -t nat -A OUTPUT -p tcp --dport 443 -j REDIRECT --to-port 15001

# 3. 可选:在 mangle 表的 PREROUTING 链中,为需要 TPROXY 的流量打标记
iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 15001
透明代理场景下的 iptables 规则链 外部客户端 PREROUTING 链 nat: REDIRECT 80→15001 路由决策 INPUT 链 filter: 允许 15001 Envoy 代理 本机进程 流程: 外部客户端请求 → PREROUTING 链(REDIRECT 到 15001)→ 路由决策(目的变为本机)→ INPUT 链(允许)→ Envoy 代理接收 → 转发到本机进程

4.6 规则匹配顺序总结

场景 数据包方向 经过的链(按顺序) 关键表
入站透明代理 外部 → 本机 PREROUTING → 路由决策 → INPUT nat (PREROUTING), filter (INPUT)
出站透明代理 本机 → 外部 OUTPUT → 路由决策 → POSTROUTING nat (OUTPUT), nat (POSTROUTING)
转发透明代理 外部 → 本机 → 外部 PREROUTING → 路由决策 → FORWARD → POSTROUTING nat (PREROUTING), filter (FORWARD), nat (POSTROUTING)
最佳实践:在配置透明代理规则时,始终遵循“先匹配、后动作”的原则。使用 -I(插入到链首)或 -A(追加到链尾)时要明确规则顺序。对于 Envoy 自身发出的流量,务必在 OUTPUT 链中使用 -m owner --uid-owner <envoy_uid> 或 -j RETURN 来跳过重定向,避免循环。