全自动科学上网方案分享
Updated:
在开始方案介绍之前,请确保自己有一个国外的服务器,比较常用的有以下几个:
- Digital Ocean:最低价格是 $5/月,每月 1000G 流量。现在注册有 $10 优惠券,GitHub 学生认证以后可以免费领取 $50 优惠券
- Vultr:最低每月 $2.5,500G 流量也足够用,目前没有优惠
- 搬瓦工:年付 $19,500G 流量,硬盘只有 10G,基本上只能用来科学上网,网上有各种优惠码,大约可以优惠 5% 左右。
如果读者还没有自己的 VPS,可以根据自己的消费能力和使用场景(单纯科学上网还是部署服务)来选购,从上面的链接购买,我也会有奖励。
Shadowsocks 的配置非常简单,参考这个脚本,只要一行命令,指定端口和密码即可。
常见痛点 & 需求:
最优秀的配置就是在使用时感觉不到配置的存在,然而复杂的应用场景决定了我们需要多种代理配置。虽然最终的目的是摆脱繁琐的配置切换,但在此之前,我们有必要梳理一下日常使用中常见的痛点。
Mac
- 模拟器需要连代理,因此电脑必须设置 HTTP/HTTPS 代理
- 终端无法使用 SS 代理,即使设置了全局代理也不行
- 某些应用,比如 Telegram,需要科学上网
Mobile
- 在公司联调时需要手动输入 Mac 的 IP 地址,过程繁琐
- 如果想科学上网,需要连接 VPN,这与 HTTP 代理冲突
- 某些网站或应用会对客户端证书做校验, 比如 iTunes、微信支付、公司内网服务等对安全要求较高的场景,导致挂着代理无法访问
Common
- 访问墙外网站需要连 VPS,墙内网站不需要连接,代理会让国内网站访问速度降低
本质
复杂的需求导致了代理场景的多样化,一般来说有三种:
- Charles 的 HTTP(s) 代理
- VPS 的 socks5 代理或 PAC
- 直接连接
上述问题的本质都来源于这三种代理是互斥的,而且切换起来比较麻烦。在 Mac 上有脚本可以切换,但有时依然无法人工区分改用哪种代理,在 iOS 上,就连设置代理都会非常耗时。
目标与解决思路
明确了问题与问题背后的复杂度以后,我们需要确定一个目标,以目标为导向,来指导自己的行动。
目标其实非常简单:
经过有限次的配置,彻底避免切换代理
换句话说,就是希望代理的切换时自动进行的,全程不再需要人工干预。
这似乎有悖于目前的工作模式,不过没关系,既然系统代理不方便,我们就需要一个全局代理,起到 路由 作用,根据一定的规则把请求转发到合适的代理上去。这样就把代理的切换简化成了规则的配置,切换永远存在,但配置只要不断维护完善就行。
Mac 配置
Mac 上用到四个工具:
- Proxifier: 全局控制工具,负责应用层面的请求转发
- Charles:一种代理,负责处理那些需要被抓包的请求
- GoAgentX:一种代理,负责处理那些需要走 Shadowsocks 协议的请求
- SwitchyOmega:Chrome 拓展工具,负责对 Chrome 中的网页进行智能代理选择
GoAgentX
这个软件的作用是帮助我们在本地的某个端口(比如 1234)上运行 Shadowsocks 服务,如果某个应用需要科学上网,只要把流量用 socks5 协议代理到 1234 这个端口上即可。
有三个比较常用的模式:
- 全局代理模式:会把系统的 SOCKS 代理设置为 127.0.0.1:1234,这样系统的所有流量都会走 socks 代理
- 自动代理配置模式(PAC):这种模式会自动分析 URL,根据 URL 的特点来决定走哪种代理,也就是达到了按需翻墙的目的
- 独立模式:这种模式下仅仅会在本地的 1234 端口上运行 Shadowsocks 服务,不会更改系统的代理方式,也就是说单独使用无法进行翻墙,需要配合其它的软件来使用,这里我们选择第三种模式。
Proxifier
Proxifer 是一个控制 app 代理方式的软件,有了它,我们就可以控制某个 app,比如 Telegram 使用哪种代理。
首先在 Proxifier 中建立一个 Shadowsocks 代理:
依次选择 Proxies、Add 并填写本机的端口。
接下来就可以把某些特定应用的流量转到代理上了:
依次选择 Rules、Add、➕,然后选择需要修改的软件以及使用哪种代理。比如这里可以选择强制 Telegram 使用 Shadowsocs 代理,就可以翻墙了。
隐藏图标
对于 Proxifier 这类应用来说,他们具有以下特点:
- 需要开机启动
- 开机后不会关闭,可以后台运行,并且基本上不再需要人工干预
一般在应用设置(Command + 逗号)中可以设置开机启动,以及隐藏 Menu Bar 中的图标,如果无法设置开机启动,我们可以手动添加:
除了隐藏 Menu Bar 中的图标外,我们还希望把它在 Dock 中的图标也隐藏掉,这需要设置 Application is agent
项,以 Proxifier 为例,需要修改 /Applications/Proxifier.app/Contents
和该路径下 /Applications/Proxifier.app/Contents/Info.plist
这个文件的权限:
1
2
|
chmod 777 /Applications/Proxifier.app/Contents
chmod 777 /Applications/Proxifier.app/Contents/Info.plist
|
然后编辑 plist 文件,新增一个布尔类型的选项 Application is agent (UIElement),值为 YES:
这样 Proxifier 就不会在 Dock 中显示,基本上做到了全局无感知。
终端科学上网
有些时候,安装一些软件包会非常慢,这是因为数据源存在国外的服务器上,但终端默认不会走代理,即使设置了全局代理也无效。
为终端设置Shadowsocks代理 这篇文章介绍了一个工具来解决上述问题:
1
2
3
|
brew install polipo
ln -sfv /usr/local/opt/polipo/*.plist ~/Library/LaunchAgents
vim /usr/local/opt/polipo/homebrew.mxcl.polipo.plist
|
添加一行 socksParentProxy=localhost:1234,记得把 1234 改成自己的 Shadowsocks 端口号:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
<plist version="1.0">
<dict>
<key>Labelkey>
<string>homebrew.mxcl.polipostring>
<key>RunAtLoadkey>
<true/>
<key>KeepAlivekey>
<true/>
<key>ProgramArgumentskey>
<array>
<string>/usr/local/opt/polipo/bin/polipostring>
<string>socksParentProxy=localhost:1234string>
array>
<key>SoftResourceLimitskey>
<dict>
<key>NumberOfFileskey>
<integer>20480integer>
dict>
dict>
plist>
|
接下来向 .zshrc 中加入一个函数:
1
2
3
4
5
6
|
function pt() {
launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.polipo.plist
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.polipo.plist
export http_proxy=http://localhost:8123
export https_proxy=http://localhost:8123
}
|
至此,所有的配置就结束了。如果某个终端窗口需要科学上网,只要先执行 pt
函数就行。如果你希望自己的终端永远使用 Shadowsocks 代理,只要将 pt
函数中的内容提出来,直接写进 .zshrc
文件中即可。
为了测试是否成功的使用了代理,我们可以尝试访问下 Google 或者检测自己的 IP 地址:
Charles
Charles 作为一个大名鼎鼎的抓包工具,具体使用方法就不用我细说了,可以参考巧哥的这篇文章:iOS开发工具-网络封包分析工具Charles。
虽然 Charles 的抓包功能足够强大,但美中不足的是,它的数据处理能力极为孱弱。虽然有 Map Local/Remote 和 Rewrite 功能,但终究不是图灵完备的语言, 灵活性和可拓展性还不够强大,比如如果数据是使用 protobuf 的形式传输,Charles 就无能为力了。
通常情况下,为了搭建一个多端统一、长期可维护的测试环境,我们需要一个中间人服务器,经过一段时间的尝试和技术选型,最终我们选择了 MITM,详细内容可以参考我的这篇博客:HTTP 代理服务器技术选型之旅。
有了 MITM 工具以后,iOS 模拟器的调试问题就迎刃而解了。注意,此时不要直接修改系统的代理,因为来回切换代理比较麻烦,Charles 提供了一个非常好用的功能,叫 External Proxy。顾名思义,Charles 可以把自己视为一个中转站,把经过自己的数据发送到下一个代理服务器上去。
因此,日常工作中,我采用的方案是系统代理长期设置为 Charles,且 Charles 长期将外部代理设置为 MITM,两者要么同时生效,要么同时失效,经过 Charles 数据一定会经过 MITM 。
快速切换系统代理
上述配置虽然大部分时候都能 work,但万一出现 Proxifier 不能指定代理,而且这个网络流量又不能走代理服务器时,我们还需要一个终极方案——快速把系统代理还原为默认。虽然我至今只在某次更新 App Store 时遇到过上述问题,但做好技术储备还是没有坏处的。
使用 networksetup
配合各种参数即可实现上述需求,我写了一个可以自动切换 Charles 和 GoAgentX 代理的脚本,在这里 可以下载并根据自己的需求自行修改。
效果如图所示:
SwitchyOmega
最后一个要用到的工具是 Chrome 的一个插件:,它可以给不同的 URL 配置不同的访问策略。
首先我们新建一个情景,用来处理需要科学上网的网站。
如果是前端开发,那些需要抓包调试的网站可以代理到 Charles 上,过程类似就不赘述了。
然后需要配置下 auto switch 场景,在绝大多数时候,我们都将使用这个场景:
第一个区域内是一些自己制定的规则,如果自动配置中某些网站的访问方式不符合我们的要求,可以单独列在这里。第二个区域表示如果命中规则列表,则使用 socks 代理,否则就直接连接。第三个区域则使用了一个开源的网址列表,列出了那些需要科学上网的网站。
有了这样的配置,我们就可以实现 百度、淘宝、京东等网站直接连接,YouTube、Google、草榴等网站科学上网了。
Mac 配置小结
Mac 上需要用到的软件较多,但每个软件的使用都不太复杂,回忆一下之前的几个痛点:
- 模拟器需要连代理,因此电脑必须设置 HTTP/HTTPS 代理。这一点我们确实是通过长期设置代理为 Charles -> MITM 实现的,并且利用脚本来快速切换代理。
- 终端无法使用 SS 代理,即使是全局代理也不行。这个问题通过
polipo
工具解决,并且编写了脚本。 - 某些应用,比如 Telegram,需要科学上网。这个问题通过 Proxifier 来设置某个 app 使用的代理方式。
- 按需代理,只有需要科学上网的网站才用代理。这个需求通过 Chrome 的插件 SwitchyOmega 完成。
iOS 配置
对于预算并不充裕的同学来说,小火箭 Shadowrocket 无疑是最佳工具了。这类应用已经在国内的 App Store 下架,需要使用美国账号购买,如果团队内的其它小伙伴也需要,可以把 ipa 用开发者证书或者企业证书重签名下,来实现团队内部分享的目的。
打开 shadowrocket 以后,在首页点击右上角的加号,可以新建一个节点,也就是我们的代理服务器:
这里强烈建议给节点添加备注,原因稍后会讲。
自动选择代理
接下来,我们需要选择路由模式,一共有四种。直连的意思很好理解,就是不走任何代理,相当于没用上 shadowrocket,可以理解为一种回滚方案。全局则表示 app 所有网络流量都走代理服务器,相当于使用了系统的 VPN。这两者功能都太单一,基本上不会使用。
配置模式和上文说过的 auto switch 差不多,都是实现了黑名单 + 广告屏蔽的功能:
- 广告屏蔽:对于某些特定的、专门用于投放广告的域名,直接屏蔽掉网络请求,从而起到去除广告的效果。
- 黑名单:列出需要科学上网的网址,走代理服务器。
- 其它:默认是直接连接。
它的主体结构可以分为三部分:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// 屏蔽广告
// 爱奇艺
DOMAIN-SUFFIX,ad.m.iqiyi.com,REJECT
DOMAIN-SUFFIX,afp.iqiyi.com,REJECT
DOMAIN-SUFFIX,api.cupid.iqiyi.com,REJECT
.......
// 优酷
......
// 科学上网
// 以 gmail.com 结尾的网址要求走代理,并且要求代理服务器做 DNS 解析
DOMAIN-SUFFIX,gmail.com,PROXY,force-remote-dns
// 直连
// BAT 等首页直连
DOMAIN-SUFFIX,baidu.com,DIRECT
DOMAIN-SUFFIX,qq.com,DIRECT
DOMAIN-SUFFIX,alipay.com,DIRECT
|
这套配置绝大多数情况下足够使用了,奈何客户端开发者经常需要对 APP 抓包,以前是通过修改系统代理实现的,现在直接修改配置文件就行了。
自定义配置
现在我们的需求变成了:
- 检查是否是广告,如果是广告则拒绝连接
- 检查是否需要科学上网,如果需要的话,走代理服务器
- 检查是否需要抓包,如果需要的话,走 Mac 的 Charles 代理代理代理
- 剩下的请求默认直连
其中第三四步的逻辑可以颠倒,也就是说可以默认走抓包模式,只有那些不能抓包的连接才直连。然而这种模式问题比较多,因为很多对安全性比较高的 app 或者网页,比如支付模块等等,都会检查客户端证书, 这种情况下通过 Charles 代理就无法访问了。访问了。
这种需求是无法使用默认的配置模式实现的, 因为它只能选择代理 or 直连,而我们的需求实际上是有两种代理,即 Shadowsocks 代理和 Charles 代理,这需要我们对配置文件做一些手动编辑。
注意到之前的每一条配置都是三段式:
规则类型》 > 规则类型》 > 规则类型》 > 规则类型,规则特征,连接方式
其中连接方式可以是 DIRECT(直连)、PROXY(代理)和 REJECT(拒绝),实际上这里还可以填写前文所说的节点标签。比如我把 VPS 的标签设置为 DigitalOcean,这里就可以改成 DigitalOcean,效果,效果,效果,效果和 PROXY 一致。
有了这个大前提,我们可以新建一个 HTTP 代理,,,,标记为 Mac,然后把需要抓包的连接的代理方式设置为 Mac 即可:
配置文件更新为:
1
2
3
4
5
6
7
8
9
10
11
|
// 需要抓包的地址走 Charles 代理
DOMAIN-SUFFIX,api.example.com,MAC PRO
// 屏蔽广告
DOMAIN-SUFFIX,ad.m.iqiyi.com,REJECT
// 以 gmail.com 结尾的网址要求走代理,并且要求代理服务器做 DNS 解析
DOMAIN-SUFFIX,gmail.com,PROXY,force-remote-dns
// BAT 等首页直连
DOMAIN-SUFFIX,baidu.com,DIRECT
|
场景模式 与 Widget
真正让我下定决心使用 shadowrocket 而不是其它应用的原因是它的场景模式。有时候,在 WiFi 模式和 4G 模式,甚至是不同的 WiFi 下,我们使用的配置文件并不相同。比如我在家的 WiFi 和外出 4G 模式下,并不需要抓包。一个场景就是一种数据接入方式和配置文件的集合,最神奇的是,场景可以自动切换。
比如我创建了三个场景,分别表示 4G、家庭 WiFi 和公司 WiFi,每个场景有自己的配置文件,通过 WiFi 名称来区分:
这样当我回家以后,shadowrocket 切换场景,自然也就会切换配置文件,从而避免了手动切换。
iOS 配置总结
在 iOS 平台上,我们也遵循了不用系统代理,利用全局代理软件来控制代理的原则,通过 shadowrocket 提供的配置文件和规则实现了需求。同时 Widget、场景模式、iCloud 备份与二维码导出提高了软件的使用效率。另一个好用的工具就是 Widget,除了全局开关以外,可以快速在场景、代理、直连、配置四种路由方式中快速选择,这个相当于之前我们编写的切换系统代理的脚本。虽然用到的场景不多,但作为一种备用方案,还是不可或缺的。
除此以外,shadowrocket 导入导出配置也很容易,默认使用 iCloud 同步数据,自己的节点和配置还可以用二维码的方式分享给别人,别人在使用时只要扫码即可导入。
总结
在 iOS 平台上,我们也遵循了不用系统代理,利用全局代理软件来控制代理的原则,通过 shadowrocket 提供的配置文件和规则实现了需求。同时 Widget、场景模式、iCloud 备份与二维码导出提高了软件的使用效率。
有了这些配置以后,各个软件的存在感反而不强了,因为几乎都会保持打开状态,交给配置文件去决定代理方式,大大提升了工作效率。
由于我没有使用安卓手机,所以暂时没有安卓平台的教程,读者可以自行搜索类似的代理软件并进行配置。
VPS 配置
可以利用这个脚本快速配置 VPS 环境
给 VPS 开启 BBR 加速后,可以显著加快网络连接速度,我测试的效果是提高了 6 倍
如果使用 Digital Ocean,请参考这个教程,其它厂商也类似
BBR 是谷歌研发的新的 TCP 拥塞控制算法,能够在有一定丢包率的网络链路上充分利用带宽,感兴趣的同学可以学习这篇文章: