onlyice 2015-11-1
- 你有一台刷上 Asus Merlin 固件并能支持 USB 扩展的路由器
- 你已经有一台海外 VPS,并已经运行 Shadowsocks 服务端
- 基础的 ssh 或 telnet 知识,基础的命令行知识
- 耐心
要翻墙,首先得看看墙做了什么,再看看如何应对它。
下面列举一些 GFW 最常见的干扰手段。
-
域名 / IP 屏蔽
比如你发起一个到 Google 服务的 HTTP 请求,GFW 会识别你访问的域名,并直接给你一个 Connection Reset
-
关键词屏蔽
URL 中如果有敏感词,也会被 GFW 屏蔽
-
DNS 污染
对于一些 GFW 不想让你访问的网站,使用国内的 DNS 服务器,很难解析出一个正确可用的 IP
-
丢包
对于像 Shadowsocks 的加密流量,GFW 并不能知道里面的内容是什么,于是判断到有大量与海外通讯的流量时,它就随机丢掉其中一些包
-
海外流量走 Shadowsocks,国内流量直连
-
海外域名的 DNS 请求也通过 Shadowsocks 转发到 VPS 上返回 因为你对这些海外服务的请求也是通过 Shadowsocks 发到 VPS 上来完成的,所以 DNS 也需要使用 VPS 解析出来的 IP
-
VPS 上装 net-speeder 或锐速等软件,用来优化高延迟、高丢包线路
首先你需要先让你的路由器运行上 Asus Merlin。Asus Merlin 的 wiki 上有详细的讲解。
下面的大部分内容,如果你不能顺利完成,请多参照 wiki 上的内容。
Entware 原本是设计给 OpenWRT 使用的,也被移植到 Asus Merlin 上来了。它是一个包管理器,类似 Ubuntu 上的 apt-get
,Federo
上的 yast
等。我们将用它来安装 Shadowsocks。
安装方法:
- 插上你的 USB Stick
- SSH / Telnet 到路由上,运行
entware-setup.sh
- 试试运行
opkg
命令,观察是否正常
P.S. SSH / Telnet 的用户名/密码,跟你在网页上登陆路由器是一样的
详细的安装教程看 wiki。
opkg
的仓库中已经有 Shadowsocks 了,分成两个包:shadowsocks-libev-polarssl
以及 shadowsocks-libev
。据说 shadowsocks-libev-polarssl
更节约资源,但是我的路由足够快,所以我装的是 shadowsocks-libev
。
安装方法:
$ opkg install shadowsocks-libev-polarssl
检查下你的 Entware 的 bin
目录(一般是 /opt/bin
)有无 ss-redir
, ss-tunnel
。
在你的 Entware 的 etc 目录中(一般是 /opt/etc/
)建立 shadowsocks.json
,写入 Shadowsocks 的配置。配置的格式与服务端的 Shadowsocks 一致。
在 /jffs/post-mount
(如果不存在这个文件,就创建它)中加入下面内容,表示路由启动并装载上 USB 后,运行 Shadowsocks:
nohup /tmp/opt/bin/ss-redir -c /tmp/opt/etc/shadowsocks.json &
nohup /tmp/opt/bin/ss-tunnel -c /tmp/opt/etc/shadowsocks.json -l 7913 -L 8.8.8.8:53 -u&
其中 ss-redir
会绑定某个本地端口,发到这个端口的流量都会被转发到 VPS 去;ss-tunnel
建立了一个通道,发到这个 7913
端口的请求都会被转到 VPS,VPS 再去请求 Google DNS (8.8.8.8) 做 DNS 解析。
iptables 是 Linux 系统下用来做流量控制的工具。我们要用它来做实际的流量转发。
目的是实现:
- 到内网的流量(如 127.0.0.1, 192.168.1.*) 直连
- 到国内 ISP 的流量直连
- 到 VPS 的流量直连
- 其他流量都转到 VPS 上
TL;DR: 下载 config/iptables_command.sh
文件,跳到 “使 iptables 规则被应用” 一节。
现在先新建一个文件,我们用它来保存 iptables 的命令。并在文件头写入下面内容,表示建立一条名为 SHADOWSOCKS 的 chain。
iptables -t nat -N SHADOWSOCKS
内网的 IP 分布在固定的几个网段中,所以直接加入以下内容即可:
# Ignore LANs IP address
iptables -t nat -A SHADOWSOCKS -d 0.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 10.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 169.254.0.0/16 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 172.16.0.0/12 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 192.168.0.0/16 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 224.0.0.0/4 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 240.0.0.0/4 -j RETURN
bestroutetb 是个 Node.js 程序,用来获取国内 ISP 的网段并生成一些转发的规则。安装好后运行:
$ bestroutetb -p custom --rule-format="iptables -t nat -A SHADOWSOCKS -d %prefix/%mask -j %gw"$'\n' --gateway.net="RETURN" -o ./iptables
$ grep RETURN ./iptables > ./iptables.china
然后把 iptables.china
文件的内容复制到前面我们创建的文件中。
加入:iptables -t nat -A SHADOWSOCKS -d 167.160.165.237 -j RETURN
加入:
iptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports 1080
iptables -t nat -I PREROUTING -p tcp -j SHADOWSOCKS
最后,把生成好的这个文件保存为 /jffs/iptables_command.sh
。
现在我们需要让这个文件在合适的时机被执行。我观察到 Asus Merlin 会在使用 PPPoE 跟运营商认证通过后(也就是平时说到的拨号上网过程),将 iptables 刷新。因此这个文件的运行时机应该是路由拨号过程完毕。
观察到深圳电信每一天会使你的 PPP 会话中断,即路由每一天会重新做一次拨号。而拨完号后有似乎有一些路由内置的功能会刷新 iptables,导致你自己注入的 iptables 被清除。看了下 Asus Merlin 的 Custom config files,似乎只有 ddns-start
事件适合这个场景。DDNS 即 Dynamic DNS,如果你使用了 Asus Merlin 提供的 DDNS 服务,路由器每次从运营商拿到新 IP 时,它会将这个新 IP 注册到 DDNS 服务器上,注册完后运行 ddns-start
脚本。因此,新建 /jffs/scripts/ddns-start
文件,写入:
#!/bin/sh
sh /jffs/iptables_command.sh
Update: 如果你开启了 QOS 功能,Asus Merlin 会把 iptable 中某些表清除掉。可以把 ddns-start
文件换成 qos-start
来解决。
这个时候,我们区分国内外流量的事情就做完了。你应该重启下路由,然后试着在你的电脑上访问一个被墙的 IP 的网站服务,比如 Google 的 http://74.125.239.144
,观察能否正常连上。
国内的 DNS 服务器在解析国外网站时,返回的 IP 基本上是不能正常访问的。同时我们想要国外的流量走 VPS,因此对于国外网站的 DNS 解析,也需要转发到 VPS 上去做。
Asus Merlin
中内置了 dnsmasq,可以用来指定特定的域名走特定的 DNS 服务器进行解析。所以剩下的问题是如何区分国内和国外的域名。
TL;DR: 下载 config/dnsmasq-conf
中的两个文件,然后跳到这一节最后部分。
我使用的 dnsmasq-china-list 提供的中国网站列表。
dnsmasq-china-list 项目提供了三个 dnsmasq
的配置文件:
-
accelerated-domains.china.conf
这个文件里面存放了绝大部分中国网站的域名,并使 dnsmasq 对这些域名使用 114.114.114.114 公共 DNS 进行解析。
-
bogus-nxdomain.china.conf
这个文件存放了一些 IP,表示当远程 DNS 服务器返回这些 IP 时,dnsmasq 将其当作解析失败来处理。原因是一些运营商对一些不存在的域名做解析时,没有正常地返回域名不存在的错误,而是返回了自己的一些广告网站的 IP。
-
google.china.conf
加速 Google 服务,我不太关心这个,没细看。
我这边的运营商并没有做上面第 2 点提到的 DNS 污染,所以我没有使用 bogus-nxdomain.china.conf
文件,只使用了 accelerated-domains.china.conf
文件。
对于 accelerated-domains.china.conf
文件,它使用了 114 公共 DNS 做解析。我觉得对于国内的域名,走运营商自己提供的 DNS 服务器会更好,于是执行了下面的命令,把这个文件中的 DNS 服务器换成默认的:
sed -i "s|^\(server.*\)/[^/]*$|\1/#|" ./accelerated-domains.china.conf
然后,生成一个文件告诉 dnsmasq 除了国内的域名,其他的走之前 ss-tunnel 绑定的端口,转发到 VPS 上走 Google 的 8.8.8.8 DNS 服务器。
echo server=/#/127.0.0.1#7913 > foreign-domains.conf
然后我们要把这个配置文件让 dnsmasq 感知到。这里使用 Asus Merlin 提供的 Custom config files 能力,将一条配置加入 dnsmasq.conf
中:
mkdir /jffs/dnsmasq-conf
cp ./accelerated-domains.china.conf /jffs/dnsmasq-conf
cp ./foreign-domains.conf /jffs/dnsmasq-conf
echo conf-dir=/jffs/dnsmasq-conf > /jffs/configs/dnsmasq.conf.add
重启路由,把你的电脑/手机的 DNS 缓存消除,试试能不能访问境外网站。
如果失败了:
- 看看路由器上
/tmp/syslog.log
中的 log - 看看
ss-redir
及ss-tunnel
有没有正常运行 - 查阅 Asus Merlin 的 wiki 等,确认你的各个步骤正确
- 多使用
dig
或nslookup
命令做验证
Enjoy the free Internet.