← 返回

使用 trans_proxy 搭建透明代理网关

什么是透明代理

传统代理需要在每台设备上手动配置代理地址,而透明代理工作在网关层面——局域网内的设备只需将默认网关和 DNS 指向代理机器,所有 TCP 流量就会被自动拦截并转发到上游代理,设备本身无需任何代理配置。

这对于不方便设置代理的设备(智能电视、IoT 设备、游戏主机等)尤其有用。

trans_proxy 的工作原理

trans_proxy 是一个用 Rust 编写的透明代理工具,支持 macOS 和 Linux,基于 tokio 异步运行时构建。下图展示了它的整体架构:

trans_proxy 架构示意图

原始目的地址恢复

透明代理面临的第一个问题是:流量被 NAT 重定向到 trans_proxy 的监听端口后,如何知道客户端原本要访问的目标地址?

trans_proxy 针对不同平台采用了不同的方案:

  • macOS (pf):通过 DIOCNATLOOK ioctl 查询 pf 的 NAT 状态表,从中获取连接被重定向前的原始目的地址
  • Linux (nftables):通过 SO_ORIGINAL_DST getsockopt 从 accepted socket 上读取原始目的地址

主机名解析

拿到原始 IP 和端口后,trans_proxy 还需要将 IP 解析为域名,因为上游 HTTP CONNECT 代理需要的是 CONNECT hostname:port 格式的请求。trans_proxy 按以下优先级确定主机名:

  1. SNI 提取:对于 TLS 连接(端口 443),解析 ClientHello 消息中的 SNI 扩展字段,直接获取客户端要访问的域名,无需解密 TLS 流量
  2. DNS 表查询:如果启用了内置 DNS 转发器,trans_proxy 会记录 DNS 查询结果,从中反查 IP 对应的域名
  3. IP 回退:如果以上两种方式都无法获取域名,则直接使用 IP 地址

内置 DNS 转发器

trans_proxy 内置了一个 DNS 转发器,监听在网关接口的 53 端口,具备以下能力:

  • DNS-over-HTTPS (DoH):支持将 DNS 查询通过 HTTPS 发送到上游 DNS 服务器(默认 Cloudflare),防止 DNS 污染
  • HTTP/2 连接池:复用 HTTP/2 连接,降低 DoH 查询延迟
  • TTL 缓存:根据 DNS 记录的 TTL 值缓存查询结果
  • 查询合并:对同一域名的并发查询进行合并,避免重复请求

这个 DNS 转发器不仅提供 DNS 服务,还为上面提到的主机名解析提供 IP 到域名的反查记录。

防火墙集成

trans_proxy 通过脚本管理防火墙规则:

  • macOS:使用 pf 的 anchor 机制,将 NAT 重定向规则挂载到独立的 anchor 下,不影响系统已有的 pf 规则
  • Linux:创建独立的 nftables table,同样不会干扰现有的防火墙配置

安装与编译

Bash
# 克隆仓库
git clone https://github.com/madeye/trans_proxy.git
cd trans_proxy

# 编译(需要 Rust 1.70+)
cargo build --release

# 编译产物在 target/release/trans_proxy

使用方法

macOS

假设网关机器的网络接口为 en0,上游 HTTP CONNECT 代理运行在本地 127.0.0.1:1082

Bash
# 启动 trans_proxy(启用 DNS 转发器)
sudo ./trans_proxy --upstream-proxy 127.0.0.1:1082 --dns

# 设置 pf NAT 重定向规则
sudo scripts/pf_setup.sh en0 8443

Linux

假设网关接口为 eth0,上游代理在 127.0.0.1:7890

Bash
# 启动 trans_proxy
sudo ./trans_proxy --upstream-proxy 127.0.0.1:7890 --dns --interface eth0

# 设置 nftables 规则
sudo scripts/nftables_setup.sh eth0 8443

主要参数

参数默认值说明
--listen-addr0.0.0.0:8443trans_proxy 监听地址
--upstream-proxy(必填)上游 HTTP CONNECT 代理地址
--dns关闭启用内置 DNS 转发器
--interfaceen0 / eth0网关网络接口
--dns-upstreamCloudflare DoH上游 DNS 服务器(支持 UDP 或 DoH)
--log-levelinfo日志级别(trace/debug/info/warn/error)
-d / --daemon关闭以守护进程方式运行

客户端配置

局域网内的设备只需两步:

  1. 默认网关设为运行 trans_proxy 的机器 IP
  2. DNS 服务器设为同一 IP(如果启用了 --dns

支持 macOS、iOS、Windows、Linux、Android 等所有主流平台,设备端无需安装任何软件。

安装为系统服务

trans_proxy 支持一键安装为系统服务:

Bash
sudo ./trans_proxy --upstream-proxy 127.0.0.1:1082 --dns --install
  • macOS:创建 LaunchDaemon,开机自启
  • Linux:创建 systemd unit,并通过 ExecStartPre / ExecStopPost 自动管理 nftables 规则的加载和清除

卸载服务:

Bash
sudo ./trans_proxy --uninstall

排查问题

遇到问题时,先提高日志级别观察:

Bash
sudo ./trans_proxy --upstream-proxy 127.0.0.1:1082 --dns --log-level debug

常见问题:

  • /dev/pf 权限错误(macOS):确保以 root 权限运行
  • NAT 查询失败:检查防火墙规则是否正确加载(macOS 用 pfctl -sa,Linux 用 nft list ruleset
  • 连接超时:确认上游代理运行正常,检查网关机器是否开启了 IP 转发(Linux 需要 sysctl net.ipv4.ip_forward=1
  • DNS 解析失败:确认 53 端口没有被其他进程占用(lsof -i :53

与 Caddy 正向代理配合

trans_proxy 需要一个上游 HTTP CONNECT 代理。如果你还没有现成的,可以参考之前的文章用 Caddy 搭建一个。一个典型的组合方式:

TEXT
局域网设备 → trans_proxy(网关) → Caddy HTTPS 正向代理(远程服务器) → 目标网站

这样局域网内的设备无需任何配置,所有流量自动通过加密隧道转发。

小结

trans_proxy 解决的核心问题是:如何让局域网内所有设备无感知地通过代理访问网络。它的优势在于:

  1. 零配置客户端:设备只需改网关和 DNS,无需安装软件或配置代理
  2. 跨平台:同时支持 macOS (pf) 和 Linux (nftables) 作为网关
  3. DNS 防污染:内置 DoH 转发器,从源头解决 DNS 污染问题
  4. 无侵入式防火墙管理:anchor / 独立 table 机制不干扰现有规则
  5. 异步高性能:基于 tokio,每个连接独立调度,适合网关场景的高并发需求