跟着 TPROXY 数据包一路走到 socket
把接收 socket、包标记和本地策略路由当作一条透明代理投递链路来排查。
TPROXY 的计数器可能一直在涨,应用却什么都收不到。规则命中了,但本地投递还取决于策略路由和兼容的接收 socket。
Linux 的 TPROXY 能拦截流量而不像 DNAT 那样改写目的地址。因此,发往非本地目的地址的数据包必须能落到合适的本地 socket 上。
沿着投递链路走一遍
- 流量经预期网卡和地址族到达拦截主机。
- 拦截规则与包标记决定本地投递策略。
- 匹配的策略规则选中能把数据包投递到本地的路由。
- 代理使用受支持的透明监听器,并带上所需的 socket 选项。
内核的 IPv4 示例要求应用支持 IP_TRANSPARENT。同一端口上的普通监听器,或全局的非本地绑定设置,都不能证明具备该支持。
| 观察 | 下一步检查 |
|---|---|
| 没有相关的入站数据包 | 流量路径与入接口 |
| 数据包到达,但拦截计数不动 | 地址族、链与匹配条件 |
| 规则命中,本地投递失败 | 标记与策略路由选择 |
| socket 在监听,应用却收不到 | 透明 socket 能力与监听器归属 |
| 请求开始,后续回包失败 | 已建立 socket 的匹配与回程路由 |
每次观察都同时记录已加载的配置和网络命名空间。后面的规则可能覆盖标记或改选另一条路由。如果在主机上拦截、监听器却跑在容器里,一条有效的宿主机本地路由并不会自动投递进那个容器。
把后续数据包也算进去
内核示例包含 socket 匹配,以及一条给透明 socket 的数据包打标记的 DIVERT 路径。省掉它,即使首次拦截成功,后续流量也可能走到另一条路径上。
使用应用支持的透明模式,并按地址族查阅对应的内核文档。IPv4 的本地路由命令不会配置 IPv6,一个地址族上的支持也不能证明另一个地址族的 socket 行为。
TPROXY 本身也不产生 SOCKS 协商。透明转 SOCKS 的组件仍然必须发现目的地址并与上游协商。
从 REDIRECT 迁移
记录现有应用如何取得原始目的地址。REDIRECT 会改写目的地址,依赖相应的还原机制;TPROXY 则需要自己的透明 socket 与路由安排。按应用与源地址策略来选择。
在切换拦截模式之前,把计数器与选中的路由、socket 能力和应用日志对齐。在提供所需能力的发行版上,补上缺失的投递步骤比重新编译内核更值得先做。