Awesome
Unblock CHN
Unblock CHN 是一个帮助配置 Shadowsocks 回国解锁代理分流的命令行小工具,实现通过路由器或 Surge 自动分流,将国内一些网站的访问通过 Shadowsocks 代理回国,用以解除这些网站的海外访问限制,其它流量则会正常直连不走回国代理。
当然前提是你需要有一台位于国内的 Shadowsocks 服务器,在国内的路由器上部署 Shadowsocks 服务器端也是可行的。
分流规则提取自 Unblock Youku,Unblock Youku 的规则中一般只包含站点用于检测的地址 ,不包含实际音视频流的地址,因此大部分情况下音视频流可以直连不用走代理,这样可以避免音视频变慢,也可以有效节约代理服务器的流量。
Unblock CHN 的功能分为两部分:
路由器
目前仅支持华硕梅林固件(Asuswrt-Merlin),其它支持 ss-redir + iptables + ipset + dnsmasq 的路由器固件或许也可以使用,但可能需要修改部分配置或代码。
原理
-
从 Unblock Youku 的 urls.js 中提取分流规则。
-
根据分流规则生成 dnsmasq 和 ipset 规则,将需要回国代理的 IP 地址加入 chn ipset。
-
添加 iptables 规则,将属于 chn ipset 的请求转发到 Shadowsocks 透明代理工具 ss-redir 的端口,通过 Shadowsocks 代理回国。
Unblock CHN 自动化以上过程,提供了一键配置路由器的命令和一些管理命令。
安装
-
在路由器上插入一个 U 盘,用来安装 Unblock CHN 和相关程序。
-
安装依赖程序:
# Python3
$ opkg install python3
# pip3
$ opkg install python3-pip
# Git
$ opkg install git-http
# Shadowsocks 透明代理工具 ss-redir
$ opkg install shadowsocks-libev-ss-redir
- 安装 Unblock CHN:
# 进入 U 盘目录(例如 /tmp/mnt/sda1)
$ cd /tmp/mnt/sda1
# 安装 Unblock CHN
$ git clone https://github.com/gxfxyz/unblockchn.git
# 进入 Unblock CHN 目录
$ cd unblockchn
# 安装 Unblock CHN 依赖
$ pip3 install -r requirements.txt
使用
$ python3 unblockchn.py router --help
usage: python3 unblockchn.py router [-h] {status,on,off,servers,switch,check,renew,setup,restore,create}
Unblock CHN 路由器命令:
status 查看代理状态
on 开启代理
off 关闭代理
servers [--json] 列出代理服务器 [--json: 输出 json 格式]
switch [name] [--auto] 切换代理服务器 [--auto: 自动选择延迟最低的代理服务器]
check <URL/IP/域名> 检查 <URL/IP/域名> 是否走代理
renew 更新规则
setup [--no-ss] 一键配置路由器 [--no-ss: 跳过配置 ss-redir]
restore [--no-ss] 还原路由器为未配置状态 [--no-ss: 跳过还原 ss-redir]
create 仅生成 ipset 和 dnsmasq 规则配置文件
positional arguments:
{status,on,off,servers,switch,check,renew,setup,restore,create}
optional arguments:
-h, --help show this help message and exit
一键配置路由器
$ python3 unblockchn.py router setup
Shadowsocks 服务器地址:180.160.0.1
Shadowsocks 服务器端口:1111
Shadowsocks 密码:xxxxxxxxxx
Shadowsocks 加密方法:rc4-md5
命名此代理服务器为:Shanghai
✔ 保存 ss-redir 配置文件:/tmp/mnt/sda1/unblockchn/shadowsocks/Shanghai.json
是否添加更多代理服务器?[y/N]:y
Shadowsocks 服务器地址:beijing.asuscomm.com
Shadowsocks 服务器端口:2222
Shadowsocks 密码:xxxxxxxxxx
Shadowsocks 加密方法:aes-128-cfb
命名此代理服务器为:Beijing
✔ 保存 ss-redir 配置文件:/tmp/mnt/sda1/unblockchn/shadowsocks/Beijing.json
是否添加更多代理服务器?[y/N]:n
0) 自动选择延迟最低的代理服务器
1) Shanghai [180.160.0.1:1111]
2) Beijing [beijing.asuscomm.com:2222]
请选择要使用的代理服务器 [0-2]:1
使用 Shanghai 代理服务器
✔ 启动 ss-redir(Shanghai 代理服务器):/opt/bin/ss-redir -c /tmp/mnt/sda1/unblockchn/shadowsocks/Shanghai.json -f /tmp/mnt/sda1/unblockchn/shadowsocks/ss-redir.pid
✔ 保存 ss-redir 启动命令到路由器的 services-start 启动脚本中:/jffs/scripts/services-start
✔ 生成 ipset 配置文件(configs 目录):ipset.rules & ipset.headless.rules
✔ 生成 dnsmasq 配置文件(configs 目录):dnsmasq.conf.add
✔ 复制:/tmp/mnt/sda1/unblockchn/configs/ipset.rules -> /jffs/configs/ipset.rules
✔ 复制:/tmp/mnt/sda1/unblockchn/configs/dnsmasq.conf.add -> /jffs/configs/dnsmasq.conf.add
✔ 加载 xt_set 模块:modprobe xt_set
✔ 保存 xt_set 模块加载命令到路由器的 services-start 启动脚本中:/jffs/scripts/services-start
✔ 载入 ipset 规则:ipset restore < /jffs/configs/ipset.rules
✔ 保存 ipset 载入命令到路由器的 nat-start 启动脚本中:/jffs/scripts/nat-start
✔ 添加 iptables 规则:iptables -t nat -A PREROUTING -p tcp -m set --match-set chn dst -j REDIRECT --to-port 1080
✔ 保存 iptables 规则添加命令到路由器的 nat-start 启动脚本中:/jffs/scripts/nat-start
✔ 重启 dnsmasq:service restart_dnsmasq
✔ 定时每日 3 点更新规则:cru a unblockchn_renew "0 3 * * * /opt/bin/python3 /tmp/mnt/sda1/unblockchn/unblockchn.py router renew"
✔ 保存定时更新规则命令到路由器的 services-start 启动脚本中:/jffs/scripts/services-start
配置成功
如果想要跳过配置 ss-redir,那么就加上 --no-ss
参数:
$ python3 unblockchn.py router setup --no-ss
至此,回国代理和自动分流就配置并开启好了。
可以访问下列地址以验证回国代理是否成功,如果显示 true
,就说明回国代理已生效:
查看代理状态
$ python3 unblockchn.py router status
已开启 (Shanghai)
关闭代理
$ python3 unblockchn.py router off
关闭成功
开启代理
$ python3 unblockchn.py router on
开启成功 (Shanghai)
列出代理服务器
$ python3 unblockchn.py router servers
共有 2 个代理服务器:
1) Beijing
Shadowsocks 服务器地址:beijing.asuscomm.com
Shadowsocks 服务器端口:2222
Shadowsocks 密码:xxxxxxxxxx
Shadowsocks 加密方法:aes-128-cfb
2) Shanghai
Shadowsocks 服务器地址:180.160.0.1
Shadowsocks 服务器端口:1111
Shadowsocks 密码:xxxxxxxxxx
Shadowsocks 加密方法:rc4-md5
-
目前使用的代理服务器为:Shanghai
如果加上 --json
参数,则会输出 json 格式:
$ python3 unblockchn.py router servers --json
{
"Beijing": {
"server": "beijing.asuscomm.com",
"server_port": 2222,
"local_address": "0.0.0.0",
"local_port": 1080,
"password": "xxxxxxxxxx",
"timeout": 300,
"method": "aes-128-cfb",
"fast_open": false,
"mode": "tcp_and_udp"
},
"Shanghai": {
"server": "180.160.0.1",
"server_port": 1111,
"local_address": "0.0.0.0",
"local_port": 1080,
"password": "xxxxxxxxxx",
"timeout": 300,
"method": "rc4-md5",
"fast_open": false,
"mode": "tcp_and_udp",
"selected": true
}
}
ss-redir 代理服务器配置文件保存在 shadowsocks
子目录下,你可以手动删改。
切换代理服务器
$ python3 unblockchn.py router switch
0) 自动选择延迟最低的代理服务器
1) Beijing [beijing.asuscomm.com:2222]
2) Shanghai [180.160.0.1:1111]
请选择要使用的代理服务器 [0-2]:1
✔ 停止 ss-redir:kill 21810
✔ 启动 ss-redir(Beijing 代理服务器):/opt/bin/ss-redir -c /tmp/mnt/sda1/unblockchn/shadowsocks/Beijing.json -f /tmp/mnt/sda1/unblockchn/shadowsocks/ss-redir.pid
切换到了 Beijing 代理服务器
或者直接输入代理服务器名来切换:
$ python3 unblockchn.py router switch Shanghai
✔ 停止 ss-redir:kill 21987
✔ 启动 ss-redir(Shanghai 代理服务器):/opt/bin/ss-redir -c /tmp/mnt/sda1/unblockchn/shadowsocks/Shanghai.json -f /tmp/mnt/sda1/unblockchn/shadowsocks/ss-redir.pid
切换到了 Shanghai 代理服务器
你可以使用 --auto
参数,让 Unblock CHN 自动选择延迟最低的代理服务器:
$ python3 unblockchn.py router switch --auto
1) Beijing [beijing.asuscomm.com:2222]: 237 ms
2) Shanghai [180.160.0.1:1111]: 523 ms
✔ 停止 ss-redir:kill 22584
✔ 启动 ss-redir(Beijing 代理服务器):/opt/bin/ss-redir -c /tmp/mnt/sda1/unblockchn/shadowsocks/Beijing.json -f /tmp/mnt/sda1/unblockchn/shadowsocks/ss-redir.pid
切换到了 Beijing 代理服务器(237 ms)
检查 <URL/IP/域名> 是否走代理
$ python3 unblockchn.py router check http://ipservice.163.com/isFromMainland
59.111.19.7 走代理
$ python3 unblockchn.py router check https://google.com
216.58.193.78 不走代理
$ python3 unblockchn.py router check www.bilibili.com
148.153.45.166 走代理
$ python3 unblockchn.py router check 192.168.2.1
192.168.2.1 不走代理
更新规则
$ python3 unblockchn.py router renew
✔ 生成 ipset 配置文件(configs 目录):ipset.rules & ipset.headless.rules
✔ 生成 dnsmasq 配置文件(configs 目录):dnsmasq.conf.add
✔ 复制:/tmp/mnt/sda1/unblockchn/configs/ipset.rules -> /jffs/configs/ipset.rules
✔ 复制:/tmp/mnt/sda1/unblockchn/configs/dnsmasq.conf.add -> /jffs/configs/dnsmasq.conf.add
✔ 清空 ipset 的 chn 表:ipset flush chn
✔ 载入 ipset 规则:ipset restore < /tmp/mnt/sda1/unblockchn/configs/ipset.headless.rules
✔ 重启 dnsmasq:service restart_dnsmasq
更新成功
Unblock CHN 在路由器上默认定时每日 03:00 自动更新分流规则,及时跟进 Unblock Youku 规则的变化。
还原路由器为未配置状态
$ python3 unblockchn.py router restore
✔ 停止 ss-redir:kill 24427
✔ 从启动脚本里移除 ss-redir 启动命令:/jffs/scripts/services-start
✔ 删除:/jffs/configs/ipset.rules
✔ 从启动脚本里移除 ipset 载入命令:/jffs/scripts/nat-start
✔ 删除:/jffs/configs/dnsmasq.conf.add
✔ 删除 iptables 规则:iptables -t nat -D PREROUTING -p tcp -m set --match-set chn dst -j REDIRECT --to-port 1080
✔ 从启动脚本里移除 iptables 规则添加命令:/jffs/scripts/nat-start
✔ 删除 ipset 的 chn 表:ipset destroy chn
✔ 删除每日更新规则的 cron 定时任务:cru d unblockchn_renew
✔ 从启动脚本里移除定时命令:/jffs/scripts/services-start
✔ 从启动脚本里移除 xt_set 模块加载命令:/jffs/scripts/services-start
✔ 重启 dnsmasq:service restart_dnsmasq
还原成功
如果想要跳过还原 ss-redir,那么就加上 --no-ss
参数:
$ python3 unblockchn.py router restore --no-ss
仅生成 ipset 和 dnsmasq 规则配置文件
$ python3 unblockchn.py router create
✔ 生成 ipset 默认配置模板文件(configs 目录):ipset.rules.tpl
✔ 生成 ipset 配置文件(configs 目录):ipset.rules & ipset.headless.rules
✔ 生成 dnsmasq 默认配置模板文件(configs 目录):dnsmasq.conf.add.tpl
✔ 生成 dnsmasq 配置文件(configs 目录):dnsmasq.conf.add
生成配置文件成功
此命令让 Unblock CHN 跳过配置路由器,仅提取 Unblock Youku 的规则,在 configs
子目录下生成相应的 ipset 和 dnsmasq 规则配置文件。
修改规则模板
除了 Unblock CHN 自动生成的规则以外,如果你需要自定义一些 dnsmasq 或 ipset 规则,可以通过修改 configs
子目录下的规则模板文件 dnsmasq.conf.add.tpl
和 ipset.rules.tpl
来实现。
保留模板文件中的 {rules}
一行,其在生成规则时会被 Unblock CHN 规则替换,然后在模板文件中添加你需要的规则,例如:
dnsmasq.conf.add.tpl
# NAS
address=/nas.xxxx.com/192.168.1.100
# CCTV
address=/cctv.xxxx.com/192.168.1.200
{rules}
ipset.rules.tpl
{rules}
create blacklist hash:ip family inet hashsize 1024 maxelem 65536
add blacklist 103.31.6.5
add blacklist 208.73.51.100
运行更新规则命令来使自定义的规则生效:
$ python3 unblockchn.py router renew
远程控制工具
iOS 捷径(Shortcut)
在 iOS 的通知中心里远程(局域网内)控制路由器上的 Unblock CHN 代理。
Alfred Workflow
在 macOS 上用 Alfred 来远程(局域网内)控制路由器上的 Unblock CHN 代理。
关键词:
unblockchn
设置:
使用前需要先设置路由器 SSH 免密码登录:
- 生成密钥:
$ ssh-keygen -t rsa
- 查看密钥:
$ cat ~/.ssh/id_rsa.pub
- 复制密钥到路由器管理页面:
系统管理 - 系统设置 - 服务 - 授权密钥
除此之外,在 Workflow 设置里点 [x] 按钮可以设置一些参数:
- router_ip: 路由器 IP 地址(默认
192.168.1.1
) - router_user: 路由器用户名(默认
admin
) - unblockchn_py_path: unblockchn.py 在路由器上的路径(默认
/tmp/mnt/sda1/unblockchn/unblockchn.py
)
Surge
Unblock CHN 从 Unblock Youku 提取分流规则,生成相应的 Surge 规则配置文件,供 Surge 或 Shadowrocket 使用,实现在 iOS 或 macOS 上解除国内网站的海外访问限制。
现成配置
懒得亲自运行 Unblock CHN?你可以直接使用下列 Unblock CHN 已经生成好的 Surge 配置文件或 ruleset 文件。
如果 Unblock CHN 的规则有变化,下列文件会定时自动更新。
配置文件
下载后修改代理服务器信息就可使用。
若使用的是 Shadowrocket,可以分开设置代理节点,然后通过 URL 单独更新配置内的规则。
RULESET 文件
RULESET 是 Surge 3 新加入的功能(Shadowrocket 不支持)。
RULESET 让 Surge 配置文件可以通过路径或 URL 来引用外部规则文件,例如你可以这样引用 Unblock CHN 的 ruleset:
RULE-SET,https://git.io/fxjWu,PROXY
而完整配置文件就可以简化成这样:
这样若 Unblock CHN 的规则有更新,你可以通过重载配置文件来更新 RULESET 引用的规则,而无需更新整个配置文件。
安装
- 安装 Unblock CHN:
$ git clone https://github.com/gxfxyz/unblockchn.git
- 进入 Unblock CHN 目录:
$ cd unblockchn
- 安装 Unblock CHN 依赖:
- 通过 pipenv(推荐)
# 安装依赖并创建虚拟环境
$ pipenv install
# 激活 pipenv 虚拟环境
$ pipenv shell
- 通过 pip
$ pip3 install -r requirements.txt
使用
$ python3 unblockchn.py surge --help
usage: python3 unblockchn.py surge [-h] [-d DST]
Unblock CHN
生成 Surge 配置文件
optional arguments:
-h, --help show this help message and exit
-u, --url 生成基于 URL 正则表达式的规则(默认基于域名)
-r, --ruleset 生成 Surge ruleset 文件
-d DST, --dst DST 保存生成的文件到此目录
准备模板
Unblock CHN 生成配置时,会在 surge
子目录下查找 .conf.tpl
后缀的 Surge 配置模板文件,因此你需要先准备至少一个模板文件。
复制样例模板文件 sample_surge.conf.tpl
,重命名为例如 surge.conf.tpl
。
用文件编辑器打开 surge.conf.tpl
,修改 Shadowrocket 服务器的地址、端口、加密方式、密码等信息。
你也可以加入其它 Surge 规则,但要保留 {rules}
一行,其在生成配置时会被 Unblock CHN 规则替换。
生成配置文件
$ python3 unblockchn.py surge
✔ 生成 Surge 配置文件(surge 目录):surge.conf
Unblock CHN 就会在 surge
子目录下生成模板文件 surge.conf.tpl
对应的 Surge 配置文件 surge.conf
。
Surge 或 Shadowrocket 载入配置文件后,可以访问下列地址以验证回国代理是否成功,如果显示 true
,就说明回国代理已生效:
指定目录
你可以添加 -d
参数,让 Unblock CHN 在生成配置文件后,将其复制到另外一个文件夹,例如 iCloud Drive 或其它网盘文件夹,这样可以方便在手机上更新配置文件:
$ python3 unblockchn.py surge -d ~/Library/Mobile\ Documents/iCloud~com~nssurge~inc/Documents
✔ 生成 Surge 配置文件(surge 目录):surge.conf
✔ 保存 Surge 配置文件到:/Users/User/Library/Mobile Documents/iCloud~com~nssurge~inc/Documents/surge.conf
生成基于 URL 正则表达式的规则
你可以使用 --url
参数:
$ python3 unblockchn.py surge --url
让 Unblock CHN 生成基于 URL 正则表达式的 Surge 规则,例如:
URL-REGEX,^http://bangumi\.bilibili\.com/api/.*,PROXY
而 Unblock CHN 默认生成的是基于域名的 Surge 规则,例如:
DOMAIN,bangumi.bilibili.com,PROXY
域名规则会让整个域名下的所有 URL 都走回国代理,而 URL 规则只会让匹配正则表达式的 URL 走回国代理。
URL 规则的好处是匹配更准确,站点一般只通过几个特定 URL 来检测用户地区,因此只需要代理这些 URL 就好了,其它网站页面和资源可以直连。但是站点用来检测的 URL 很可能经常会变化,而 Unblock Youku 的 URL 规则往往是滞后的、不完善的,因此容易导致解锁失败。而且 URL 规则只对 HTTP 请求有效,HTTPS 请求因为加密了 URL,无法用 URL 规则来匹配,所以仍需要通过域名规则来代理,现在大部分网站也默认采用 HTTPS,因此 URL 规则实用性不是很好。
相比之下,域名规则虽然会让整个域名下的页面和资源都走回国代理,但是覆盖面广,规则不容易失效。而且站点的音视频流一般通过 CDN 来分发,会使用不同的域名,因此即使使用域名规则,大部分情况下音视频流还是会直连不走回国代理。
所以 Unblock CHN 默认且推荐使用基于域名的规则。
生成 RULESET
你可以使用 --ruleset
参数,让 Unblock CHN 生成回国规则的 ruleset 文件 unblockchn.surge.ruleset
:
$ python3 unblockchn.py surge --ruleset
✔ 生成 Surge ruleset 文件(surge 目录):unblockchn.surge.ruleset
一些说明
-
Unblock Youku 的规则可能会失效,如果你遇到某个站点无法解锁,可以向 Unblock Youku 反馈。
-
因为 Unblock Youku 的规则主要是针对浏览器 Web 端,而一些手机端 App 有可能会采用不同的检测,所以可能需要手动添加一些额外规则才能解锁这些手机端 App。
-
国内一些网站在海外可能会使用同一个 CDN 服务商,导致不同网站的域名会被解析为相同的 IP,由于 Unblock CHN 在路由器上实质是基于 IP 来分流的,因此可能会造成不需要代理回国的域名被误代理。目前,我发现微博图片的
ws1.sinaimg.cn
等域名和 B 站的data.bilibili.com
域名有时会出现这种被解析到相同 IP 的情况,导致微博图片被误代理回国。临时解决办法是用renew
命令来重置下 ipset,微博图片应该就能恢复直连,直到下一次访问 B 站。 -
更新 Unblock CHN:
-
更新前还原路由器为未配置状态:
python3 unblockchn.py router restore
-
更新:
git pull
-
更新后重新配置路由器:
python3 unblockchn.py router setup
-
-
default_config.py
里有一些配置项,你可以将其复制为config.py
后进行修改,config.py
内的配置会覆盖default_config.py
内的配置。 -
目录下的
unblockchn.log
为日志文件,记录了运行过的命令和结果。 -
本项目衍生自 Unblock Youku,如果你觉得本项目或 Unblock Youku 有用,请考虑向 Unblock Youku 捐款 ❤️。