MacOS 透明代理
Table of Contents
简介
透明代理:用户在访问网络时无需特别配置或知晓代理的存在,不需要一个程序一个程序的设置。代理能够自动判断哪些请求需要通过代理,哪些请求直接链接。一般是通过修改路由表的方式实现。
本文是参考 macOS上的透明代理 这篇文章
随便购买一个便宜的机场,使用 shadowsocks-rust 连接机场。使用 Packet Filter 一个状态检测型的包过滤防火墙 修改请求的路由。
安装 shadowsocks-rust
brew install shadowsocks-rust
pf 配置
scrub-anchor "com.apple/*" table <direct_cidr> persist file "/Users/a77/Downloads/tproxy/configs/direct_cidr.txt" #1 nat-anchor "com.apple/*" rdr-anchor "com.apple/*" rdr pass on lo0 proto tcp from any to any port 0:1024 -> 127.0.0.1 port 59080 #2 pass out route-to (lo0 127.0.0.1) proto tcp from any to !<direct_cidr> #3 dummynet-anchor "com.apple/*" anchor "com.apple/*" load anchor "com.apple" from "/etc/pf.anchors/com.apple"
- directcidr.txt 文件中定义了哪些 ip 地址不需要代理,这里有一些ip地址
- 将所有发往本地回环接口 (lo0) 端口为 0-1024 的 TCP 流量,重定向到了本机的 59080 端口。
- 确保所有满足条件的出站 TCP 流量在发送之前被强制路由到本机的 lo0 接口,通过 127.0.0.1 转发出去。
实际的调用逻辑是,先把需要代理的请求,发送到本地回环接口 (lo0),然后,再把 lo0 上的流量重定向到 59080 端口(ss 会监听这个端口)。不需要代理的请求,不通过 lo0 直接发往目标。
为什么需要先 route-to(强制路由)再 rdr(重定向)
如果仅仅修改数据包的目标地址和端口,让数据包发往指定的新地址。数据包仍然经过物理接口(例如 en0),并且内核的路由子系统并没有将其当作本地流量处理,这可能导致 连接状态追踪(state tracking)异常,因为数据包的源地址仍然是外部地址,目标地址被改写为 127.0.0.1,但内核网络栈不一定会将这类数据包当作本地回环流量。
因此需要将请求先 route-to(强制路由)到 lo0 接口,然后再重定向请求。但这样存在一个问题。route-to 到 lo0 的请求和自己发送给 127.0.0.1 的请求是一样的。如果把所有 lo0 的请求都 rdr 到 59080 端口,会导致无法访问到本地部署的 127.0.0.1 服务。
因此,只选择重定向 0-1024(具体的数字,根据后续的深入使用来配置)请求的端口到代理服务,其他的端口假设为本地服务端口。
SS 配置
{ "locals": [ { "local_address": "0.0.0.0", "local_port": 59080, "protocol": "redir" } ], "ss_local_port": 1080, "local_address": "127.0.0.1", "servers": [ ] }
SSH 配置
上述配置,进行 github git SSH 操作时无法联通。因此单独配置 ssh, 端口设置为 443(违背了透明原则,后续看看能否解决。)。
Host github.com Hostname ssh.github.com Port 443 AddKeysToAgent yes UseKeychain yes IdentityFile ~/.ssh/id_ed25519
tproxy 脚本
基于上述逻辑,编写一个 tproxy 脚本。