TPROXY 透明代理原理
什么是 TPROXY
TPROXY(Transparent Proxy)是 Linux 内核原生的透明代理技术,属于 netfilter 框架的一部分。相比传统的 REDIRECT,TPROXY 在设计上更"干净",也是对应用层最透明的方案。
核心思路
TPROXY 不是「改目标地址」,而是给内核发一条指令:
这个包别路由出去,直接交给本机的 7893 端口处理,同时保留所有原始信息。
跟 REDIRECT 的对比
REDIRECT(你之前用的方式)
客户端 → 路由器(PREROUTING)
│
▼
iptables -j REDIRECT --to-ports 7892
│
│ 把目标IP:端口改了
│ (例如: youtube.com:443 → 127.0.0.1:7892)
▼
mihomo 收到连接
│
│ 需要用 SO_ORIGINAL_DST 从内核拿回真实目标
│ (但拿回的是 IP,不知道原始域名)
▼
DNS 污染时:拿到错误 IP → 连错服务器 → 失败
本质:内核把包"篡改"了,mihomo 得费力去猜原始目标是什么。
TPROXY(现在用的方式)
客户端 → 路由器(PREROUTING)
│
▼
iptables -j TPROXY --on-port 7893 --tproxy-mark 1
│
│ 不打改包,只是打个标记(fwmark=1)
│ 原始目标 IP:端口 原封不动
▼
策略路由:标记 1 的包 → 路由表 100
│
▼
route add local 0.0.0.0/0 dev lo
(所有标记包都交给本机回环接口处理)
│
▼
mihomo 收到连接,直接看到原始目标 IP:端口
配合 sniffer 读取 TLS SNI → 拿到 www.youtube.com
即使 IP 被污染,也能从域名识别出正确目标
本质:内核不篡改包,只是"拦截并本地投递",mihomo 看到的和客户端发送的完全一致。
三要素
TPROXY 需要三个东西同时配合才能工作:
1. iptables mangle 表规则
iptables -t mangle -A PREROUTING -p tcp -j TPROXY --on-port 7893 --tproxy-mark 1
-t mangle:mangle 表在 PREROUTING 链处理,时机比 nat 表更早--on-port 7893:把匹配的包交给本机 7893 端口--tproxy-mark 1:给包打上标记 1,路由系统根据这个标记做策略路由
2. 策略路由
ip rule add fwmark 1 table 100
ip route add local 0.0.0.0/0 dev lo table 100
这两条的意思是:凡是打了标记 1 的包,查路由表 100。路由表 100 说:所有地址都是本机地址(local),走回环接口(lo)处理。
没有策略路由的话,内核收到一个目标为 8.8.8.8:443 的包,会试图从 WAN 口发出去,而不是交给本地进程。
3. mihomo 监听 tproxy 端口
tproxy-port: 7893
mihomo 需要用 IP_TRANSPARENT socket 选项来绑定,这要求:
- mihomo 以 root 运行(或者有 CAP_NET_ADMIN 权限)
- 这样才能接收目标不是本机的包
关键区别:为什么 TPROXY 不怕 DNS 污染
REDIRECT 场景
客户端 DNS → 阿里 DoH → 69.171.235.22(Facebook) ← DNS 被污染
客户端 TCP → 69.171.235.22:443
REDIRECT → 改目标为 127.0.0.1:7892
mihomo 拿到 127.0.0.1:7892,用 SO_ORIGINAL_DST 问内核
内核返回 69.171.235.22:443
mihomo 连 69.171.235.22:443 → Facebook 不认识 youtube SNI → 断
TPROXY 场景
客户端 DNS → 阿里 DoH → 69.171.235.22(Facebook) ← 同样污染
客户端 TCP → 69.171.235.22:443
TPROXY → 不打改包,打标记 1 → 策略路由 → 本机 7893
mihomo 直接看到 69.171.235.22:443(原始目标保留着)
mihomo sniffer 嗅探 TLS 握手 → SNI: www.youtube.com
mihomo 用域名规则 → DOMAIN-SUFFIX,youtube.com,🚀 节点选择 → 走代理
mihomo 自己重新解析 youtube.com(通过 Google DNS)→ 正确 IP
代理连到正确的 YouTube 服务器 → 成功
即使 IP 被 DNS 污染,TPROXY 保留了完整包信息,sniffer 能从 TLS 层拿到真实域名。
支持 UDP(REDIRECT 做不到的)
REDIRECT 只能劫持 TCP,因为 UDP 没有连接概念,改了目标地址就没法还原了。
TPROXY 可以劫持 UDP:
tproxy-port: 7893
iptables 加一条 UDP 规则:
iptables -t mangle -A PREROUTING -p udp -j TPROXY --on-port 7893 --tproxy-mark 1
mihomo 收到 UDP 包后,可以根据原始目标 IP 做 DNS 防污染、QUIC 代理等。
数据流完整路径
┌─────────────────────────────────────────────────────────────────┐
│ 客户端 (192.168.1.215) │
│ 浏览器 → youtube.com:443 │
└──────────────────────────┬──────────────────────────────────────┘
│ 包: src=192.168.1.215:54321
│ dst=69.171.235.22:443
▼
┌─────────────────────────────────────────────────────────────────┐
│ 路由器 (i br-lan 进入) │
│ │
│ ① PREROUTING (mangle, 最先处理) │
│ └─ MIHEMO 链: 来源 IP=215, TCP → TPROXY --on-port 7893 │
│ 包没改,但打上了 fwmark=1 │
│ │
│ ② 路由决策 │
│ └─ fwmark=1 → 查路由表 100 │
│ 路由表 100: local 0.0.0.0/0 dev lo │
│ → "这是本机地址,从 lo 送本地进程" │
│ │
│ ③ mihomo (监听 0.0.0.0:7893, IP_TRANSPARENT) │
│ 收到包,看到原始目标 69.171.235.22:443 │
│ └─ sniffer 嗅探 TLS ClientHello → SNI: www.youtube.com │
│ └─ match DOMAIN-SUFFIX,youtube.com → 🚀 节点选择 │
│ └─ 连接 35.78.84.79:10541 (VLESS Reality) 走代理 │
│ │
│ ④ 出口 (FORWARD → POSTROUTING → pppoe-wan) │
│ 代理流量正常路由 │
└─────────────────────────────────────────────────────────────────┘
总结
| 特性 | REDIRECT | TPROXY | TUN |
|---|---|---|---|
| 原理 | 改目标地址 | 标记 + 策略路由 | 虚拟网卡 |
| TCP | ✓ | ✓ | ✓ |
| UDP | ✗ | ✓ | ✓ |
| 原始地址 | 需额外获取 | 自动保留 | 自动保留 |
| 性能 | 好 | 好 | 略低(用户态) |
| 配置复杂度 | 低 | 中 | 低 |
| 适合场景 | 简单 TCP 代理 | 全面透明代理 | 全流量接管 |
评论
评论功能即将上线,敬请期待。