Tomato 固件上配置 Shadowsocks + GFWList

Netgear 上刷 Tomato 固件的最主要目的就是配置 Shadowsocks 以方便在家里上网。可能是因为我将用户软件包都安装到了外接 U 盘上,中间走了很多弯路。这里的记录实际上跟参考的那几篇文章没多大区别。

因为使用的是 Linux 系统,很方便直接从 Konsole 登录到路由器,

me@mylaptop:~> ssh root@10.1.1.1 -p 2222

这里我将路由器的 IP 地址设成 10.1.1.1(在「Basic Settings 基本设置」里的「Network 网络」页面中的「LAN 局域网」部分修改 br0 的 IP 地址)而不是默认的 192.168.1.1 了,因为光猫的 IP 是 192.168.1.1。端口也没有使用默认的 22 而是改成了 2222。

安装

下面开始安装和配置 Shadowsocks,主要参考 https://zzz.buzz/zh/gfw/2016/02/16/deploy-shadowsocks-on-routers/,其中有非常详细的解释。这里不再摘录说明而只是记录操作步骤。

之前看到很多教程里面都是安装 shadowsocks-libev,但是现在这个包被拆分成了多个包,比如 shadowsocks-libev-ss-local, shadowsocks-libev-ss-server, shadowsocks-libev-ss-redir 等。(如果曾经安装过 shadowsocks-libev,则在安装 shadowsocks-libev-ss-redir 前需先卸载旧的包 opkg remove shadowsocks-libev。)所以这样安装,

# opkg install shadowsocks-libev-ss-redir

很多依赖包都会自动安装。运行 ss-redir --help 可以验证安装是否正确完成并确认所安装的版本。

配置 ss-redir

然后配置 shadowsocks。假设服务器已经配置好了,直接修改本地配置文件以使用 SS 服务器。修改配置文件 /opt/etc/shadowsocks.json。默认内容为,

{
"server":"127.0.0.1",
"server_port":8388,
"local_port":1080,
"password":"barfoo!",
"timeout":60,
"method":"chacha20-ietf-poly1305"
}

修改默认配置文件 /opt/etc/shadowsocks.json 或新建一个配置文件,对应修改为需要的参数即可,格式如下:

{
"server": "服务器地址",
"server_port": 服务器端口,
"local_address": "0.0.0.0",
"local_port": 本地端口,
"password": "密码",
"method": "加密方式",
"mode": "tcp_and_udp"
}

样例在上头,注意按实际配置情况替换其中的服务器地址、端口、密码、加密方式、协议等信息:

  • “server”: 必须,服务器 IP 地址或域名。对应命令行 -s 参数。
  • “server_port”: 必须,shadowsocks 服务器所监听的端口。对应命令行 -p 参数。
  • “local_address”: 必须,默认 “127.0.0.1”,由于我们需要在路由器上为网络中的各设备提供透明代理,此处应填入 “0.0.0.0”。对应命令行 -b 参数。
    • 要想使局域网内机器能够访问到部署在路由器上的 shadowsocks 服务,需要将该地址指定为路由器的IP地址(如 10.1.1.1,具体值取决于所配置的路由器的 IP 地址);
    • 要想使路由器自身的流量能够经过 shadowsocks 服务,需要将该地址指定为 127.0.0.1;
    • 若想使路由器自身和局域网内的机器都能够使用到 shadowsocks 服务,则需将该地址指定为 0.0.0.0。
  • “local_port”: 必须,shadowsocks 客户端要监听的端口,该端口号还会在后面的的 iptables 规则配置中用到。对应命令行 -l 参数。
  • “password”: 必须,shadowsocks 服务端所设置的密码。对应命令行 -k 参数。
  • “method”: 可选,默认 “chacha20-ietf-poly1305″。应填入 shadowsocks 服务端所设置的加密方法。对应命令行 -m 参数。
  • “mode”: 可选,默认 “tcp_only”。如服务端及客户端环境支持 UDP,可填入 “tcp_and_udp” 以同时启用 TCP 和 UDP。对应命令行默认(”tcp_only”)以及 -u (“tcp_and_udp”) 和 -U (“udp_only”) 参数。

配置文件所支持的其他参数可参见其源代码。

通过命令行启动以测试是否正常运行该指令和配置,

# ss-redir -u -c /opt/etc/shadowsocks.json -f /var/run/ss-redir.pid -b 0.0.0.0

如果没问题,修改系统自启动文件 /opt/etc/init.d/S22shadowsocks,将其中的 ss-local 改为 ss-redir,同时修改 ARGS 参数部分。具体参照下面修改后的文件内容,

root@R8000:/opt/etc/init.d# cat S22shadowsocks
#!/bin/sh

ENABLED=yes
PROCS=ss-redir
ARGS="-c /opt/etc/shadowsocks.json -f /var/run/ss-redir.pid -b 0.0.0.0"
PREARGS=""
DESC=$PROCS
PATH=/opt/sbin:/opt/bin:/opt/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

[ -z "$(which $PROCS)" ] && exit 0

. /opt/etc/init.d/rc.func

配置 ss-tunnel

配置 ss-tunnel 是为了转发局域网的 DNS 查询到 SS 服务器上。所以还需要安装 ss-tunnel,

# opkg install shadowsocks-libev-ss-tunnel

ss-tunnel 没有自动生成类似上面的 ss-redir 的自启动文件 /opt/etc/init.d/S22shadowsocks。我们可以修改上面的文件增加需要的内容,也可以创建一个新的自启动文件 /opt/etc/init.d/S23shadowsocks_tunnel。我是复制之前的文件为 S23shadowsocks_tunnel,

root@R8000:/opt/etc/init.d# cp /opt/etc/init.d/S22shadowsocks /opt/etc/init.d/S23shadowsocks_tunnel

然后修改内容如下,

#!/bin/sh

ENABLED=yes
PROCS=ss-tunnel
ARGS="-c /opt/etc/shadowsocks.json -b 0.0.0.0 -u -l 5353 -L 8.8.8.8:53"
PREARGS=""
DESC=$PROCS
PATH=/opt/sbin:/opt/bin:/opt/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

[ -z "$(which $PROCS)" ] && exit 0

. /opt/etc/init.d/rc.func

其中 8.8.8.8:53 是告诉 SS 服务器去 Google 的公共 DNS 服务器的 53 端口进行 DNS 查询。也就是将本地 127.0.0.1:5353 的 DNS 查询转发到 8.8.8.8:53。而本地配置的 127.0.0.1:5353 是由后面要配置的 dnsmasq 和 GFWList 来设定的。

路由器上的 IPTABLES

配置路由器 iptables 以利用创建的 dnsmasq 规则来调用 ss-redir 和 ss-tunnel。

因为 https://zzz.buzz/zh/gfw/2016/02/16/deploy-shadowsocks-on-routers/ 是将所有国外流量都走 SS,而我希望只是被墙的部分才走 SS,所以下面参考 https://cokebar.info/archives/962 的配置。采用参考链接中的方案二使用 ss-tunnel 转发 UDP 的 DNS 查询请求给 SS 服务器。这个是需要告诉路由器操作系统加载需要的模块并将相应的联网请求转发给运行在路由器中的 SS 客户端。

# Load ipset netfilter kernel modules and kernel modules
insmod ip_set
insmod ip_set_bitmap_ip
insmod ip_set_bitmap_ipmac
insmod ip_set_bitmap_port
insmod ip_set_hash_ip
insmod ip_set_hash_ipport
insmod ip_set_hash_ipportip
insmod ip_set_hash_ipportnet
insmod ip_set_hash_net
insmod ip_set_hash_netport
insmod ip_set_list_set
insmod xt_set

# Configure firewall forwarding tactics
ipset -N gfwlist iphash
iptables -t nat -A PREROUTING -p tcp -m set --match-set gfwlist dst -j REDIRECT --to-port 1080
iptables -t nat -A OUTPUT -p tcp -m set --match-set gfwlist dst -j REDIRECT --to-port 1080

上面的指令可以先在命令行运行,以测试其正确性。没有问题的话就可以粘贴到 AdvancedTomato 的 Web 管理面板的「Administration 管理」栏目下的「Scripts 脚本」页面的「Init 初始化」标签页中并保存。

可以在命令行检查这个 iptables 是不是正确创建了,

# iptables -t nat --list | grep -i gfwlist
REDIRECT tcp -- anywhere anywhere match-set gfwlist dst redir ports 1080
REDIRECT tcp -- anywhere anywhere match-set gfwlist dst redir ports 1080

如果需要将 DNS 服务器(比如 8.8.8.8)的访问流量也经过 SS 服务器,则可以在上面的代码后面增加下面的一条,

ipset add gfwlist 8.8.8.8

如果有其它 IP 需要经过代理来访问,也可以参照这一句指令来写。

再然后还需要重启一下 dnsmasq 以应用新的 ipset。将下面的这句添加到上面的 ipset 之后,

/opt/etc/init.d/S56dnsmasq restart

配置 Dnsmasq

在「Advanced Settings 高级设置」里的「DHCP/DNS」中的「Dnsmasq Custom configuration 自定义设置」中粘贴下面的定义,

conf-dir=/opt/etc/dnsmasq.d

单击页面底部的「Save 保存」按钮。

通过 SSH 在路由器的 /opt/etc 目录中新建并进入目录 dnsmasq.d,下载 dnsmasq_gfwlist_ipset.conf 后放入该目录,

# mkdir /opt/etc/dnsmasq.d
# cd /opt/etc/dnsmasq.d
# wget https://cokebar.github.io/gfwlist2dnsmasq/dnsmasq_gfwlist_ipset.conf --no-check-certificate

同时将自动更新脚本下载过来,

# wget https://raw.githubusercontent.com/cokebar/gfwlist2dnsmasq/master/gfwlist2dnsmasq.sh --no-check-certificate

配置自动获取 GFWList 并更新 dnsmasq_gfwlist_ipset.conf

cokebar 上提供了根据 GFWList 自动更新 dnsmasq_gfwlist_ipset.conf 的脚本 gfwlist2dnsmasq.sh。实测的时候发现当前的 entware 里没有需要的 mktempmktemp 是 Linux 上用来创建临时文件(夹)的软件。所以我稍稍修改了一下 gfwlist2dnsmasq.sh 将创建临时文件夹的那一句改成一个固定的路径。将刚才下载的 gfwlist2dnsmasq.sh 脚本文件移动到 /opt 路径下并重命名为 gfwlist2dnsmasq_mod.sh,修改其中的,

TMP_DIR=`mktemp -d /tmp/gfwlist2dnsmasq.XXXXXX`

为,

#TMP_DIR=`mktemp -d /tmp/gfwlist2dnsmasq.XXXXXX`
TMP_DIR="/tmp/gfwlist2dnsmasq_tmp"

保存并修改其可执行权限,

# chmod a+x /opt/gfwlist2dnsmasq_mod.sh

测试一下结果,

# sh /opt/gfwlist2dnsmasq_mod.sh -s gfwlist -o /opt/etc/dnsmasq.d/dnsmasq_gfwlist_ipset.conf

如果没有问题就到「Administration 管理」栏目下的「Scheduler 计划任务」页面并定位到「Custom 1 自定义 1」。勾选「Enable 启用」,然后选个自动执行的时间,比如每个周日凌晨的 3:00。下面的 days 是默认勾选全部的,改成只勾选 Sun。然后将上面的指令(不要前面的 # 号)粘贴到「Command 指令」后面的文本框中,最后单击页面底部的「Save 保存」。

检查 IPSET

某些情况下系统初始化时候配置的 ipset 可能会莫名其妙丢失,从而导致无法自动路由到 Shadowsocks。仿照 https://www.nap6.com/thread-275-1-1.html 的脚本来定期检查和重置。

创建 /opt/run_load_modules.sh 脚本文件,内容为,

#!/bin/sh
# Copyright (C) 2015 OpenWrt.org

# Load ipset netfilter kernel modules and kernel modules
insmod ip_set
insmod ip_set_bitmap_ip
insmod ip_set_bitmap_ipmac
insmod ip_set_bitmap_port
insmod ip_set_hash_ip
insmod ip_set_hash_ipport
insmod ip_set_hash_ipportip
insmod ip_set_hash_ipportnet
insmod ip_set_hash_net
insmod ip_set_hash_netport
insmod ip_set_list_set
insmod xt_set

# Configure firewall forwarding tactics
ipset -N gfwlist iphash
iptables -t nat -A PREROUTING -p tcp -m set --match-set gfwlist dst -j REDIRECT --to-port 1080
iptables -t nat -A OUTPUT -p tcp -m set --match-set gfwlist dst -j REDIRECT --to-port 1080

当然这里最后三行的内容应该与前面「路由器上的 IPTABLES」那里一致。

再创建一个新的脚本文件 /opt/run_check_chain.sh,内容为,

#!/bin/sh
# a VPN check script

CHAIN=`iptables -t nat --list | grep -i gfwlist`

if [ -z "$CHAIN" ]
then
    sh /opt/run_load_modules.sh
fi

将这两个文件都设置为可执行,

# chmod a+x /opt/run_check_chain.sh
# chmod a+x /opt/run_load_modules.sh

参照上面自动更新 dnsmasq_gfwlist_ipset.conf 的计划任务,将 sh /opt/run_check_chain.sh 放到「Administration 管理」栏目下的「Scheduler 计划任务」页面并定位到「Custom 2 自定义 2」的「Command 指令」后面的文本框中。并设置检查频率等,比如每天,每隔几分钟检查一次。最后单击页面底部的「Save 保存」。

暂时似乎不需要检查到被阻断网站的连通性。

下载保存路由器的配置然后重启看看效果。遇到路由器无法连接了可以通过复位(reset,顶住电源按钮旁边的小孔里的复位器几秒钟)然后路由器重启后就可以无线连接其默认的 Tomato* 无线热点(无密码)。©

本文发表于水景一页。永久链接:<https://cnzhx.net/blog/ss-and-gfwlist-in-tomatousb/>。转载请保留此信息及相应链接。

雁过留声,人过留名

电子邮件地址不会被公开。 必填项已用*标注

特别提示:与当前文章主题无关的讨论相关但需要较多讨论求助信息请发布到水景一页讨论区的相应版块,谢谢您的理解与合作!请参考本站互助指南
您可以在评论中使用如下的 HTML 标记来辅助表达: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.