本文主要介绍在路由器上部署 shadowsocks 的方法与流程。通过在路由器上部署 shadowsocks 服务,可以为整个局域网内设备提供透明代理,而无需在每台设备上做相应设置,也可以让一些不方便设置代理的设备能够通过代理访问网站。

此处的路由器指安装了 padavan, OpenWrt, dd-wrt, Tomato 等固件,或者其他提供了 shell 接入、并可安装 .ipk 格式的软件包的路由器。

本文主要以安装了 padavan 固件(该固件支持华硕 RT-N11P / N14U / N56U / N65U / AC51U / AC54U / AC1200 / AC1200HP)的路由器为例。

安装 shadowsocks

首先通过包管理工具来安装 shadowsocks。

  • 如果路由器使用 Entware 进行软件分发,则使用 opkg 命令;

    # 更新软件列表
    opkg update
    # 安装 shadowsocks
    opkg install shadowsocks-libev-ss-redir
    

    注:shadowsocks 过去曾用包名 shadowsocks-libev,现则分为多个包如 shadowsocks-libev-ss-local, shadowsocks-libev-ss-server, shadowsocks-libev-ss-redir 等。

    如曾安装过 shadowsocks-libev,则在安装 shadowsocks-libev-ss-redir 前需先将其卸载:opkg remove shadowsocks-libev

    安装 shadowsocks-libev-ss-redir

    padavan 固件路由器配置使用 Entware 可以参考 HowToConfigureEntware

  • 如果路由器使用 Optware 进行软件分发,则使用 ipkg 命令,由于 Optware 包仓库中并没有 shadowsocks 的软件包,需自行网上下载,或动手编译,才能安装;

    # 更新软件列表
    ipkg update
    # 安装 shadowsocks
    ipkg install <文件名>
    
  • 如果路由器不使用任何包管理工具,需自行从网上下载可执行文件以及相应依赖,并放至路由器相应目录。

安装完成后,将会有 ss-redir 命令可用,运行 ss-redir --help 来验证安装正确完成并确认所安装的版本。

错误解决

  • opkg update 报错

    在配置完成 shadowsocks 代理前,路由器可能还无法直接访问到软件仓库,导致出现如下图所示错误:

    opkg update 错误

    此时,可以先在电脑端等能访问下载地址的机器上下载完软件包后,再上传至路由器安装。大部分路由器是基于 mips 平台的,可以使用如下地址下载 shadowsocks 所需的两个包。

    1. http://pkg.entware.net/binaries/mipsel/shadowsocks-libev-config_3.0.6-2_mipselsf.ipk
    2. http://pkg.entware.net/binaries/mipsel/shadowsocks-libev-ss-redir_3.0.6-2_mipselsf.ipk

    由于在电脑端直接下载的 shadowsocks 包可能与路由器上所包含的元信息不一致,安装时可能需要指定 --force-checksum 选项。

    手动安装 shadowsocks 包前,我们需要使用 cd 命令切换至存放安装包的目录。

    cd "安装包所在目录"
    opkg install --force-checksum shadowsocks-libev-*_mipselsf.ipk
    
  • 运行 ss-redir 等报 libsodium 相关错

    由于 shadowsocks 依赖 libsodium 库,因此如果该库未安装或者安装版本与所需版本不一致就会报错。解决办法则是安装所需版本的库。可以运行以下命令来安装:

    opkg install libsodium
    

    如果无法在路由器直接下载安装,则可以在以下地址下载后上传至路由器后安装。

    http://pkg.entware.net/binaries/mipsel/libsodium_1.0.8-1_mipselsf.ipk

    安装所用命令:

    opkg install --force-checksum <文件名>
    

    类似地,shadowsocks 还依赖 libc, libssp, libopenssl, libev, libsodium, libpthread, libpcre, zlib,如果相关依赖没有被正确安装,可以手动安装相关依赖。

配置 shadowsocks 流量转发服务

配置服务端可以有两种方式:

  • 修改默认配置文件 /opt/etc/shadowsocks.json 或新建一个配置文件,格式如下:

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

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

    {
        "server": "ss.zzz.buzz",
        "server_port": 10443,
        "local_address": "0.0.0.0",
        "local_port": 1080,
        "password": "zzz.buzz",
        "method": "chacha20-ietf-poly1305",
        "mode": "tcp_and_udp"
    }
    
    • "server": 必填,填入服务器 IP 地址或域名。对应命令行 -s 参数。

    • server_port: 必填,填入 shadowsocks 服务器所监听的端口。对应命令行 -p 参数。

    • "local_address": 选填,默认 "127.0.0.1",由于我们需要在路由器上为网络中的各设备提供透明代理,此处应填入 "0.0.0.0"对应命令行 -b 参数。

      • 要想使局域网内机器能够访问到部署在路由器上的 shadowsocks 服务,需要将该地址指定为路由器的IP地址(如 192.168.1.1,具体值取决于所配置的路由器的IP地址);
      • 要想使路由器自身的流量能够经过 shadowsocks 服务,需要将该地址指定为 127.0.0.1
      • 若想使路由器自身和局域网内的机器都能够使用到 shadowsocks 服务,则需将该地址指定为 0.0.0.0
    • local_port: 必填,填入 shadowsocks 客户端要监听的端口,该端口号还会在后文的 iptables 规则配置中用到。对应命令行 -l 参数。

    • "password": 必填,填入 shadowsocks 服务端所设置的密码。对应命令行 -k 参数。

    • "method": 选填,默认 "rc4-md5"。应填入 shadowsocks 服务端所设置的加密方法。对应命令行 -m 参数。

    • "mode": 选填,默认 "tcp_only"。如服务端及客户端环境支持 UDP,可填入 "tcp_and_udp" 以同时启用 TCP 和 UDP。对应命令行默认("tcp_only")以及 -u ("tcp_and_udp") 和 -U ("udp_only") 参数。

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

    随后,在启动 shadowsocks 时,使用 -c 选项指定配置文件的位置。例如如下所示:

    ss-redir -c /opt/etc/shadowsocks.json
    
  • 命令行参数

    此外,也可以在命令行上直接指定所需的相关参数,命令行参数与配置文件的对应关系见上文说明,例如:

    ss-redir -s "服务器地址" -p 服务器端口 -b 0.0.0.0 -l 本地端口 -k "密码" -m "加密方式" -u
    

    也可以加载配置文件,并额外提供一些命令行参数来覆盖配置文件中的设置,例如:

    ss-redir -c /opt/etc/shadowsocks.json -l 本地端口
    

配置服务文件

通过服务启动 shadowsocks 时,shadowsocks 所用的参数来自于服务文件,需要在服务文件中进行配置。

安装 shadowsocks 后,会在系统中安装一个 shadowsocks 的服务文件,取决于系统与具体所安装的版本,服务文件可能位于以下位置中:

  • /opt/etc/init.d/S22shadowsocks
  • /opt/etc/init.d/shadowsocks
  • /etc/init.d/S22shadowsocks
  • /etc/init.d/shadowsocks

Shadowsocks 服务文件示例:

#!/bin/sh

ENABLED=yes
PROCS=ss-redir
ARGS="-c /opt/etc/shadowsocks.json"
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

其中:

  • ENABLED 行表明了是否在开机时自动启动服务;

  • PROCS 行指定了所运行的主程序;

  • ARGS 行指定了 shadowsocks 启动时的参数。

    -c 后跟的是配置文件的位置,需将填写好的配置文件保存至该位置。

    该配置文件具体位置取决于所安装版本和服务配置,一般为 /opt/etc/shadowsocks.json/etc/shadowsocks.json,也可自行指定为其他位置。

    如果没有使用配置文件,而想直接使用命令行参数,那么这些参数同样需要在 ARGS 行中指定。

注意事项

  • 安装 shadowsocks 时附带的服务文件中的 PROCS 行默认写的是 ss-local,此处根据我们转发流量的需求应当改为 ss-redirss-redirss-local 以及其他 ss 命令使用的命令行参数都是相同的。

  • 配置 shadowsocks 时,可以同时使用配置文件和命令行参数。其中,在命令行上提供的参数将覆盖配置文件中的设置。如:

    PROCS=ss-redir
    ARGS="-c /opt/etc/shadowsocks.json -b 0.0.0.0"
    

启动 shadowsocks 流量转发服务

通过命令行启动

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

其中,

  • -u 选项启用UDP转发(需要TPROXY模块支持),该选项也可在配置文件中进行配置;
  • -c 选项指定配置文件;
  • -f 选项指定pid文件的位置,同时让进程进入后台运行;
  • -b 选项指定 shadowsocks 服务绑定的本地地址,默认绑定在 127.0.0.1。此处应填 0.0.0.0,该选项也可在配置文件中进行配置,详见上文说明

通过服务文件启动

使用命令 /opt/etc/init.d/S22shadowsocks start 启动服务;

注意上面命令中的 /opt/etc/init.d/S22shadowsocks 需换为上文中提到的 shadowsocks 服务文件在系统中的实际位置。

配置自动转发流量至 shadowsocks 服务器

配置自动流量转发主要通过 iptables 相关命令完成, iptables 相关的命令执行后立即生效。如果配置错误导致无法上网,可以重启路由器,原先输入的命令会被自动撤销;如果配置完成后,并没有起到效果,可能是配置有问题,也有可能配置正确,但所访问的网站不但需要通过代理访问,对其域名进行的 DNS 解析也应通过代理完成,详见后文转发 DNS 请求

转发局域网内 TCP 流量

转发局域网内 TCP 流量的 iptables 规则参照了 shadowsocks-libev 的官方文档

# 创建 iptables 链
iptables -t nat -N SHADOWSOCKS

# 忽略自己服务器的 IP 地址
# !!重要!! 忽略此步将无法代理流量至 shadowsocks 服务器
iptables -t nat -A SHADOWSOCKS -d "服务器IP地址" -j RETURN

# 忽略局域网中的 IP 和其他想忽略的 IP 地址
# 可参照 ashi009/bestroutetb 来生成忽略所有中国地址的列表
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

# 其他所有未被忽略的 TCP 流量将被转发至 shadowsocks 的本地端口(即之前配置配置文件中配置的本地端口)
# !注意! 该命令必须放在忽略规则之后执行。若将忽略规则放在此之后则不会生效。
iptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports "本地端口"

# 应用 shadowsocks 规则
iptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS

转发路由器自身 TCP 流量

要让路由器自身的流量也能够经过 shadowsocks 代理服务器的话,还需要运行如下 iptables 规则:

iptables -t nat -A OUTPUT -p tcp -j SHADOWSOCKS

使用 bestroutetb 生成忽略列表

按照上文的配置可以将所有通向外网的流量转发至 shadowsocks 服务器,但实际上,更多时候我们只想将通向国外的流量转发至 shadowsocks 服务器,而国内的流量则依然直接连接。那么我们可以使用 bestroutetb 来智能地生成 iptables 规则,注意使用该工具时需要管理员或 root 权限,具体详见该项目主页。

如不想自行执行命令生成规则列表,也可以使用生成好的规则列表:下载规则脚本 (72 KB,更新于 2017年7月27日)

脚本中的命令类似如下所示:

# 忽略中国IP,不经过shadowsocks代理
iptables -t nat -A SHADOWSOCKS -d 0.0.0.0/7 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 10.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 14.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 14.0.0.0/21 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 14.0.12.0/22 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 14.1.0.0/22 -j RETURN
...

转发 DNS 请求

配置完 TCP 流量转发后,还需要配置 DNS 请求的转发,以避免 DNS 污染造成的无法访问。

转发 DNS 请求可以配置 ChinaDNS(推荐),只将国外域名的 DNS 请求转发,也可以通过添加 iptables 规则来转发所有 DNS 请求至 shadowsocks 服务器。两者选其一即可。

配置 ChinaDNS 转发国外域名的 DNS 请求

参考:ChinaDNS

安装

# 更新软件列表
opkg update
# 安装 ChinaDNS
opkg install chinadns

启动 ChinaDNS

# 启动 ChinaDNS
/opt/etc/init.d/S56chinadns start

ChinaDNS 默认监听 5353 端口,因此在之后的配置中使用 5353 端口。

配置 /etc/storage/dnsmasq/dnsmasq.conf

添加或修改相应行:

no-resolv
server=127.0.0.1#5353

修改完成后,执行以下命令以重启 dnsmasq 服务:

kill `pidof dnsmasq`; dnsmasq

使用 iptables 规则转发所有 DNS 请求

DNS 请求默认走的是 UDP 协议,因此转发 DNS 我们需要 shadowsocks 服务端开启 UDP 支持,以及路由器上运行的客户端 ss-redir 同样配置使用 UDP。如服务端或客户端无法启用 UDP 支持,则可以选择配置 ChinaDNS

另外 iptables 转发 UDP 请求需要 TPROXY 模块支持。因此,如果以下命令执行出现错误,说明相关模块没有在路由器上安装,可以考虑手动安装,或者选择配置 ChinaDNS

# 创建 iptables 链
iptables -t mangle -N SHADOWSOCKS

# 添加 UDP 规则
ip rule add fwmark 0x01/0x01 table 100
ip route add local 0.0.0.0/0 dev lo table 100
iptables -t mangle -A SHADOWSOCKS -p udp --dport 53 -j TPROXY --on-port "本地端口" --tproxy-mark 0x01/0x01

# 应用 shadowsocks 规则
iptables -t mangle -A PREROUTING -j SHADOWSOCKS

自启动 shadowsocks 及 ChinaDNS

安装在 /opt/etc/init.d/ 目录下的服务文件默认会在开机时被位于 /usr/bin/opt-start.sh 的脚本启动。

如需禁止自动启动,需编辑 /opt/etc/init.d/ 下相应的服务文件,将其中的 ENABLED=yes 改为 ENABLED=no

  • shadowsocks 的服务文件一般为 /opt/etc/init.d/S22shadowsocks
  • ChinaDNS 的服务文件一般为 /opt/etc/init.d/S56chinadns

另外,除了启动服务外,还需要在开机启动时再次自动执行之前配置的 iptables 命令。配置开机启动的命令一般在路由器的网页管理界面中都有配置,也可在命令行下配置,不再详述。