trans_proxy一款 macOS 和 Linux 透明代理工具,通过 pf/nftables 拦截 TCP 流量并转发至上游 HTTP CONNECT 或 SOCKS5 代理。
使用 /dev/pf 上的 DIOCNATLOOK ioctl 从 pf 的 NAT 状态表中恢复原始目标地址 — 与 mitmproxy 使用的技术相同。
使用 SO_ORIGINAL_DST getsockopt 从 nftables 重定向规则中恢复原始目标地址。
通过 socks5://host:port 使用 SOCKS5 代理作为上游,支持可选的用户名/密码认证(RFC 1928/1929)。
窥探 TLS ClientHello 以提取主机名,发送正确的 CONNECT host:port 而非原始 IP。无需 TLS 终止或证书生成。
直接在网关接口(端口 53)上监听局域网客户端的 DNS 查询。构建 IP→域名查找表。支持 DoH 和 UDP 上游。
使用基于锚点的 pf 规则(macOS)或独立的 nftables 表(Linux),不会触碰现有防火墙配置。
支持作为后台进程运行,带有 PID 文件和日志文件支持。使用 -d 启动,使用 kill 停止。
安装为系统服务(macOS 使用 launchd,Linux 使用 systemd),开机自动启动。Linux 上自动管理 nftables NAT 规则。使用 --install 和 --uninstall。
基于 tokio 构建,为每个连接生成独立任务。通过双向中继高效处理大量并发连接。
完整的端到端测试套件在 Linux 和 macOS 上运行真实的 nftables/pf + 代理流水线,覆盖 SOCKS5、HTTP CONNECT、DNS 转发和端口选择性重定向。
DIOCNATLOOK ioctl)# 克隆仓库 git clone https://github.com/madeye/trans_proxy.git cd trans_proxy # 构建发布版二进制文件 cargo build --release # 验证 cargo test ./target/release/trans_proxy --help
本示例假设您的上游 HTTP 代理运行在 127.0.0.1:1082,局域网接口为 en0。
在网关接口上启用 DNS 运行(默认使用 Cloudflare DoH):
# 前台运行(自动检测 en0 IP,监听端口 53) sudo ./target/release/trans_proxy \ --upstream-proxy 127.0.0.1:1082 \ --dns # 或作为守护进程运行 sudo ./target/release/trans_proxy \ --upstream-proxy 127.0.0.1:1082 \ --dns -d
在另一个终端中安装 pf 规则(仅 HTTP/HTTPS — DNS 由程序直接处理):
sudo scripts/pf_setup.sh en0 8443
脚本会输出您的网关 IP 和设置摘要。
在每个客户端设备上将 Mac 的 IP 设置为默认网关(和 DNS 服务器)。
sudo scripts/pf_teardown.sh # 如果以守护进程运行 sudo kill $(cat /var/run/trans_proxy.pid)
| 参数 | 默认值 | 说明 |
|---|---|---|
--listen-addr |
0.0.0.0:8443 | 代理监听的地址和端口 |
--upstream-proxy |
必填 | 上游代理:host:port 为 HTTP CONNECT,socks5://host:port 为 SOCKS5 |
--log-level |
info | 日志详细级别:trace、debug、info、warn、error |
--dns |
off | 在网关接口上启用 DNS 转发器(端口 53) |
--interface |
en0 | 用于 DNS 自动检测的网络接口 |
--dns-listen |
自动 | 覆盖 DNS 监听地址(例如 192.168.1.42:53) |
--dns-upstream |
https://cloudflare-dns.com/dns-query | 上游 DNS:UDP 使用 host:port,DoH 使用 https:// URL |
-d / --daemon |
off | 作为后台守护进程运行 |
--pid-file |
/var/run/trans_proxy.pid | PID 文件路径(与 --daemon 一起使用) |
--log-file |
/var/log/trans_proxy.log(守护进程) | 日志文件路径(前台运行时默认输出到 stderr) |
--install |
off | 安装为系统服务(macOS 使用 launchd,Linux 使用 systemd) |
--uninstall |
off | 卸载系统服务 |
# 设置:pf_setup.sh <interface> [proxy_port] # DNS 不再需要 pf 重定向 — 直接监听端口 53 sudo scripts/pf_setup.sh en0 8443 # 清理:刷新锚点规则,禁用 IP 转发 sudo scripts/pf_teardown.sh
example.com:443(解析为 93.184.216.34)127.0.0.1:8443(macOS 使用 pf,Linux 使用 nftables)93.184.216.34:443)example.com)CONNECT example.com:443从 TLS ClientHello 中提取。适用于 HTTPS(端口 443)。无需 TLS 终止。
来自 DNS 响应(通过 DoH 或 UDP)的 IP→域名映射。适用于 HTTP 和 HTTPS。需要 --dns。
如果无法确定主机名,则回退到 IP 地址。始终可用。
NAT 重定向规则会在套接字层看到之前就重写目标地址。
trans_proxy 使用平台特定机制恢复原始目标地址:
macOS 上使用 DIOCNATLOOK(查询 pf 的 NAT 状态表,与 mitmproxy 相同),
Linux 上使用 SO_ORIGINAL_DST(从内核的连接跟踪中恢复重定向前的目标地址)。
在每个需要通过代理路由的设备上,将网关机器的 IP 设置为默认网关和 DNS 服务器。
设置 → Wi-Fi → (i) → 配置 IP → 手动 → 路由器和 DNS:网关 IP
设置 → 网络 → Wi-Fi → 属性 → 编辑 IP → 手动 → 网关和 DNS:网关 IP
sudo ip route replace default via <ip> 并更新 /etc/resolv.conf
Wi-Fi → 长按 → 修改 → 高级 → 静态 IP → 网关和 DNS:网关 IP
sudo 运行。代理需要 root 权限才能访问 /dev/pf。pfctl 的无害警告。macOS 不包含 ALTQ。pf 重定向在没有它的情况下也能正常工作。sudo pfctl -a trans_proxy -s rulessudo pfctl -s info | head -1--log-level debug 获取详细的逐连接日志。sysctl net.inet.ip.forwarding(应为 1)。
--dns 且 DNS 转发器正在运行。DNS forwarder listening on <ip>:53。dig @<gateway_ip> example.com