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),则停止该链后续规则的检查。
4.4 规则匹配顺序详解
规则匹配顺序遵循“链内顺序匹配,链间固定顺序”的原则。理解这一点对于避免规则冲突至关重要。
4.4.1 链内匹配顺序
在一条链内部,规则按照从上到下的顺序依次匹配。一旦匹配某条规则并执行了目标(如 ACCEPT、DROP、RETURN、REDIRECT),则停止该链后续规则的检查。如果所有规则都不匹配,则执行该链的默认策略(Policy)。
4.4.2 链间匹配顺序
数据包在不同链之间的流转顺序是固定的,由内核协议栈决定。以透明代理最常见的场景——拦截发往本机的流量为例:
- PREROUTING 链(raw → mangle → nat):在此处使用 REDIRECT 或 TPROXY 目标,将目标端口重定向到 Envoy 监听的端口。
- 路由决策:内核根据修改后的目标 IP 和端口重新决策,此时数据包目的变为本机。
- 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
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 来跳过重定向,避免循环。