在华为HG255D OpenWrt上安装和配置Shadowsocks并实现智能流量转发

1 概述

Showsocks-libev是Shadowsocks的C语言版本,和Shadowsocks其他版本一样快速、稳定,并且更加轻巧、内存占用极低,在装载OpenWrt系统的路由器上都可以流畅稳定地运行。
在OpenWrt上配置好Shadowsocks等工具之后,电脑、手机等设备可以实现零配置上Facebook、Youtube等网站。

2 一些说明

ar71xx and bcm47xx平台的Shadowsocks具有可以直接安装的ipk文件,如果你的路由器是这些平台的CPU,可以到这里去下载安装包:http://buildbot.sinaapp.com
我的华为HG255D是RT3052的SOC,需要自己编译安装包,本文记录了安装和配置的过程。本文参考了[北落师门]的文章配置一台基于openWRT的路由器使用shadowsocks并智能穿墙,特此表示感谢。

  • 软硬件环境
    • 华为HG255D路由器(Ralink RT3052)
    • 路由器系统为基于OpenWrt 12.09的PandoraBox
    • SSH工具(推荐Bitvise SSH Client)
  • 涉及到的一些软件和技术

    • Shadowsocks
    • redsocks2
    • dnscrypt-proxy
    • dnsmasq
    • vi
    • iptables
  • 为了方便本文的读者进行测试,这里共享一个我自己的Shadowsocks服务器。
    已被ISP停用

    • 地理位置: Los Angeles, US
    • 服务器IP:107.181.166.106
    • 端口号:8088
    • 密码 :Shuyz_comss
    • 加密方式:aes-256-cfb
      这是一台闲置的VPS主机,在04/19/2015之前Shadowsocks服务将一直可用,之后将不再续费。
      使用约定:服务器仅供测试,请不要用来下载、视频、SPAM等,感谢你的合理使用。

3 安装和配置Shadowsocks

3.1 安装Shadowsocks

Shadowsocks官方没有为RT3052平台的路由器编译安装包,需要自己下载源代码编译。
比较令人绝望的是针对HG255D编译的Shadowsocks竟然也不能在OpenWrt上直接安装,会提示平台不兼容。既然不能自动安装,那就只好手动安装了。

3.1.1 手动安装原理

OpenWrt的ipk安装包其实是一个压缩文件,将其逐层解压两次之后可以看到有三个文件:

  • control.tar.gz 安装包描述
  • data.tar.gz 可执行文件和配置文件
  • debian-binary 版本信息

自动安装ipk安装包时,系统将data.tar.gz的可执行文件和配置文件解压到指定目录,然后对control.tar.gz的信息进行记录,这样就可以在软件包列表里看到这个软件了;
我们说的手动安装其实就是代替系统将data.tar.gz里的可执行文件和配置文件解压到指定目录,这样也可以正常运行。但是由于系统没有记录我们的安装信息,所以手动安装的软件在系统的软件列表里是看不到的,卸载也需
手动卸载

3.1.2 开始安装

这里以编译的Shadowsocks 1.4.5为例,这个版本用的是openssl库。

首先SSH登录到路由器,依次执行以下命令:

cd /tmp
#下载Shadowsocks的data.tar.gz压缩包
wget http://uploads.shuyz.com/openwrt/hg255d/shadowsocks-libev_1.4.5_ramips_24kec%20dfd/data.tar.gz
#安装(解压文件到指定目录)
gunzip data.tar.gz
tar xvf data.tar -C /
#删除临时文件
rm data.tar
#至此安装完成
#输入ss-local 命令看是否有输出,如果看到帮助信息说明安装成功

Shadowsocks安装后会有三个文件:

  • ss-local socks5 协议代理
  • ss-redir 透明代理
  • ss-tunnel 端口转发

3.1.3 卸载Shadowsocks

如果需要卸载,删除安装过程添加的文件就可以卸载了,依次输入以下命令:

#如果启用了服务需要先禁用
/etc/init.d/shadowsocks disable
#删除文件
rm /etc/init.d/shadowsocks
rm /etc/shadowsocks.json
rm /usr/bin/ss-local
rm /usr/bin/ss-redir
rm /usr/bin/ss-tunnel

3.1.4 配置Shadowsocks

输入命令vi /etc/shadowsocks.json编辑shadowsocks配置文件。
如果你不太了解vi编辑器也不用担心,只需要了解几条简单的命令就可以了:

  • i 进入编辑模式
  • ESC 进入命令模式
  • :wq 保存并退出

http://uploads.shuyz.com/2014/06/676964637.png

不要忘记method配置项里加密方式要加引号,否则会提示ERROR: 7:14: Unexpected a when seeking value错误

3.1.5 测试Shadowsocks

输入下面的命令启动shadowsocks客户端:

ss-local -c /etc/shadowsocks.json

http://uploads.shuyz.com/2014/06/3423971636.png

这时候已经在路由器上启动shadowsocks代理了,我们只要在代理软件上填写路由器的ip和shadowsocks的端口就可以浏览国外的网站了。这里以Chrome浏览器的SwitchySharp插件为例(我的路由器ip是10.1.1.1):

http://uploads.shuyz.com/2014/06/4124111228.png

启用SwitchySharp后,试试是否能打开Google(Facebook等网站可能被DNS污染不能打开),如果顺利打开说明Shadowsocks已经起作用了,如果打不开注意查看SSH窗口的输出信息进行调试。

3.1.6 开机启动shadowsocks服务

如果测试无误的话可以将shadowsocks设为开机启动,这样路由器即使重启也不需要再次启动Shadowsocks了,输入下面的命令设置开机启动服务:

/etc/init.d/shadowsocks enable

小结:到这里我们已经可以通过Shadowsocks上国外的网站了,但是操作还是不太优雅,因为客户端需要安装和配置代理软件,因为这会让我们意识到的存在。当然,如果你不介意的话可以到此为止了。

我们的想法就是没有任何客户端,即使不懂技术的爸爸妈妈拿起手机也可以直接上Facebook。要实现这个功能,我们需要使用对流量进行转发,即能直接连接的网站直接连接,不能直接连接的网站使用shadowsocks连接。这一切都是在路由器端实现的,手机、电脑等设备根本不知道这个细节。

4 配置redsocks2智能转发

4.1 安装和配置

redsocks2是改版的redsocks,相比于redsocks,redsocks2能够智能判断是否需要使用socks5代理,如果网站可以直接连接则直接连接,如果不能连接则使用socks5代理(这里特指shadowsocks)进行连接,比gfwlist还智能。

这里使用恩山的test0x01朋友编译的redsocks2可执行文件,我加上了libevent库和配置文件,打包成一个安装包,通过以下命令安装:

cd /tmp
# 下载
wget http://robots.shuyz.com/openwrt/hg255d/redsocks2/redsocks2.tar.gz
# 解压安装
gunzip redsocks2.tar.gz
tar xvf redsocks2.tar -C /
#删除临时文件
rm redsocks2.tar
#至此安装完成

打开/etc/redsocks.conf文件,将ip地址改成你的路由器ip地址:

    ...
    # 把下面这两个10.2.2.1改成路由器ip
    local_ip = 10.2.2.1;
    local_port = 1081;
    ip = 10.2.2.1;
    port = 1080;
    ...

4.2 卸载

删除redsocks2安装包释放的文件即可:

#shadowsocks自启动文件因为修改了,也会被删除
rm /etc/init.d/shadowsocks
rm /etc/redsocks.conf
rm /lib/libevent-2.0.so.5
rm /lib/libevent-2.0.so.5.1.9
rm /opt/bin/redsocks2

4.3 测试

我修改了shadowsocks的自启动文件/etc/init.d/shadowsocks,将 shadowsocks、redsocks2和iptable规则全部写在里面了, 所以开机启动shadowsocks时就已经启动智能上网方案了,文件内容如下:

#!/bin/sh /etc/rc.common
# Copyright (C) 2006-2011 OpenWrt.org

START=95

SERVICE_USE_PID=1
SERVICE_WRITE_PID=1
SERVICE_DAEMONIZE=1

start() {
    echo starting ss-local...
        service_start /usr/bin/ss-local -c /etc/shadowsocks.json

    echo starting redsocks2...
    /opt/bin/redsocks2 -c /etc/redsocks2.conf

    echo loading redsocks2 firewall rules...
        load_firewall

    echo done.
}

stop() {
    echo stopping ss-local...
        service_stop /usr/bin/ss-local

    echo stopping redsocks2...
    killall -9 redsocks2

    echo flushing redsocks2 firewall rules...
        flush_firewall

    echo done.
}

load_firewall() {
    # create a new chain named REDSOCKS
    iptables -t nat -N REDSOCKS

    # Ignore LANs IP address
    iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
    iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
    iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
    iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
    iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
    iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
    iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
    iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN

    # Anything else should be redirected to redsocks's local port
    iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-ports 1081

    # Apply the rules
    iptables -t nat -I zone_lan_prerouting -j REDSOCKS
}

flush_firewall() {
    iptables -t nat -F REDSOCKS
    sleep 1
    iptables -t nat -D zone_lan_prerouting -j REDSOCKS
    iptables -t nat -X REDSOCKS
}

执行/etc/init.d/shadowsocks restart命令或重启路由器即可启动智能转发方案。

使用电脑或手机等打开Google(Facebook等被DNS污染的网站可能打不开)等网站测试一下,注意电脑上不需要任何代理软件,如果能打开说明配置成功了。如果出现问题,可以开启redsocks2的debug开关进行调试。

http://uploads.shuyz.com/2014/06/4074683339.png

到这里我们已经意识不到的存在了,客户端零配置就可以自由上网,比如用Kindle Paperwhite上Twitter。

http://uploads.shuyz.com/2014/06/2907656957.jpg

5 防止DNS劫持

经过上面的配置之后,有可能Facebook等网站仍然打不开,原因是这些站点的域名的DNS被污染了,被解析到一个不存在的地方(下图中第一次使用114DNS解析错误,第二次是使用路由器的DNS解析正确):

http://uploads.shuyz.com/2014/06/6272847.png

国内DNS污染的说明和解决方法这里有一篇非常详细的文章:openwrt 上通过 pdnsd 和 dnsmasq 解决 dns 污染。由于pdnsd内存占用太高(在openwrt上运行大约需要9M的内存),这里我们使用dnscrypt-proxy来解决dns污染。

dnscrypt-proxy provides local service which can be used directly as your local resolver or as a DNS forwarder, encrypting and authenticating requests using the DNSCrypt protocol and passing them to an upstream server.

5.1 安装dnscrypt-proxy

这里提供一个恩山的ivyswen朋友编译的dnscrypt-proxy,可以在hg255d上直接安装。

# 安装
opkg install http://robots.shuyz.com/openwrt/hg255d/dnscrypt-proxy_1.2.0-1_ramips.ipk
# 启动
/etc/init.d/dnscrypt-proxy start
# 设置开机启动
/etc/init.d/dnscrypt-proxy enable

注意:如果dnscrypt-proxy开机启动失败的话可以尝试编辑/etc/init.d/dnscrypt-proxy文件,将启动顺序设为START=98.

5.2 配置dnscrypt-proxy

修改/etc/config/dhcp,将dnsmasq配置段后面的内容改成如下:

#   option resolvfile           '/tmp/resolv.conf.auto'
    option noresolv             1
    list server                 '127.0.0.1#2053'
    list server                 '/pool.ntp.org/208.67.222.222'

修改完成之后重启一下dnsmasq服务: /etc/init.d/dnsmasq restart.

5.3 测试dnscrypt-proxy

打开OpenDNS的测试页面: OpenDNS welcome,如果你看到下面的页面说明你的DNS已经加密了。

http://uploads.shuyz.com/2014/08/741478506.jpg

5.4 指定局域网主机的DNS服务器

经过上面的设置之后,如果使用路由器作为DNS服务器,就可以避免被DNS污染了;但是如果局域网内的主机手动设置了DNS服务器,还是难免遭到DNS污染。

为了避免这个问题,我们可以强制局域网内的主机都使用路由器的DNS,通过设置防火墙规则,将所有DNS解析的请求"劫持"到路由器上,从未避免局域网内的主机使用自定义DNS时被污染,在/etc/firewall.user上增加两条规则即可:

iptables -t nat -A PREROUTING -s 路由器IP/24 -p udp --dport 53 -j DNAT --to 路由器IP
iptables -t nat -A PREROUTING -s 路由器IP/24 -p tcp --dport 53 -j DNAT --to 路由器IP

下面一张图是局域网主机通过自定义DNS解析Facebook的结果,被路由器"劫持"之后,即使使用了自定义DNS,解析结果也是正确的:

http://uploads.shuyz.com/2014/06/force-dns.PNG

5.5 福利:国内网站去广告

根据adblock-lazy的列表制作了一份dnsmasq解析规则,将国内网站的广告解析到127.0.0.1 ,从而达到去广告的目的,执行下面的命令:

#切换到规则目录
cd /etc/dnsmasq.d
#下载adblock-lazy列表
wget http://uploads.shuyz.com/openwrt/adblock-lazy.conf
#重启dnsmasq服务
/etc/init.d/dnsmasq restart
这时候打开优酷等视频网站,应该没有广告了。

6 后记

Shadowsocks进程监控

Shadowsocks的稳定性还是非常不错的,在路由器上连续运行了5天都没出现问题,直到有一天突然发现Google打不开了,登陆路由器发现没有ss-redir进程,原来是Shadowsocks挂掉了!所以为了保证Shadowsocks一直运行,我们可以写一个脚本,通过一个cron任务来监控ss-redir进程,如果发现挂掉则立即重启,并记录日志,这样也方便日后分析,下面是我的一段监控脚本:

*/2 * * * * isfound=$(ps | grep "ss-redir" | grep -v "grep"); if [ -z "$isfound" ]; then echo "$(date): restart ss-redir...">>/tmp/log/ss-monitor.log && /etc/init.d/shadowsocks restart; fi

7 参考资料

8 更新历史

  • 2014/06/11 关于下载的压缩包解压时提示tar: invalid tar magic的问题。
    可能是由于OpenShift服务器对tar.gz的压缩包进行了二次压缩,造成下载的数据损坏,去掉文件后缀再wget就没问题,即将data.tar.gz改为data再wget。文中的链接已修正。

  • 2014/06/17 今天自己下载Shadowsocks的data文件解压时仍然提示tar: invalid tar magic(前几天测试是正常的),但是Windows下载下来的压缩包打开正常。很奇怪的问题,建议遇到这个问题的朋友可以先下载到电脑上,然后通过WinSCP等工具传到OpenWrt上安装。

  • 2014/06/22 找到tar: invalid tar magic错误的解决办法,先gunzip解压然后再用tar解压就没问题。

  • 2014/08/11 使用dnscrypt-proxy代替pdnsd,使用redsocks2代替iptables实现智能转发。以前的方案做了一个pdf备份:点此下载

关键字:openwrt, hg255d, shadowsocks, iptables, rt3052, dnsmasq, pdnsd, redsocks2, dnscrypt-proxy

本文链接:树叶的BLOG >> 在华为HG255D OpenWrt上安装和配置Shadowsocks并实现智能流量转发

本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 Unported许可协议进行许可。

上一篇 : 使用串口修复OpenWrt路由器 下一篇 : 用Typecho Redis Cache来为Typecho提供全站超高速缓存