请稍侯

树莓派搭建透明代理

21 July 2015

前面介绍了如何将树莓派打造成无线路由器,以及如何用树莓派屏蔽网页、视频广告,接着我们在树莓派上搭建透明代理服务器,实现科学上网。

一、ss-redir + chinadns + iptables

实现透明代理的方法很多,这儿介绍两种。第一种是 ss-redir + chinadns + iptables。

ss-redir 是 shadowsocks 的一部分,在 pc 上面一般用的是 ss-local。chinadns 是一个防污染 dns 服务器,和 shadowsocks 出自同一个作者之手(clowwindy)。基本原理是,先通过 chinadns 解析域名,获得真实 ip,然后通过 iptables 将指定 ip 段的请求转发给 ss-redir 监听的端口,ss-redir 将请求经过加密后转发给 shadowsocks 服务端 ss-server,由 ss-server 向目标服务器发出请求,这些过程对连接到热点的用户是透明的。

首先安装 shadowsocks,shadowsocks 有各种语言的版本,此处我们使用 libev 版本(c 版本):

sudo apt-get install shadowsocks-libev

由于 ss-redir 需要配合 ss-server 使用,因此需要有一个墙外的 vps 运行 ss-server,对于手头不充裕的同学,推荐使用 xvmlabs 或 bandwagonhost,价格极低,但还算稳定,流量也够用,我已经用了一年有余。不久前,这货提供了 shadowsocks 一键安装功能,真是方(zuo)便(si)。ss-server 的安装与配置,与 ss-local、ss-redir 差别不大。

编辑配置文件 /etc/shadowsocks-libev/config.json

{
    "server": "x.x.x.x",
    "server_port": 1081,
    "password": "123456",
    "method": "rc4-md5",
    "local_address": "192.168.42.1",
    "local_port": 1080,
    "timeout": 60
}

请将 server 和 server_port 换成你的 vps 的 ip 和端口,加密方式和 ss-server 保持一致(推荐 rc4-md5,速度较快)。

shadowsocks 的启动脚本 /etc/init.d/shadowsocks-libev 默认启动 ss-local,请改为 ss-redir。如果你想树莓派本身也能使用代理,可以同时运行 ss-redir 和 ss-local,ss-local 的配置文件和 ss-redir 基本一致,去掉 local_address 设置即可(ss-server 也是一样)。

然后重启 shadowsocks 服务:

sudo service shadowsocks-libev restart

接着安装 chinadns,这个软件源里没有,需要自己编译:

git clone https://github.com/clowwindy/ChinaDNS
cd ChinaDNS
./configure && make
sudo make install

(再次建议打包成 deb 后安装,sudo checkinstall

添加开机启动脚本 /etc/init.d/chinadns

#!/bin/sh
### BEGIN INIT INFO
# Provides:          chinadns
# Required-Start:    $network $local_fs $remote_fs $syslog
# Required-Stop:     $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start ChinaDNS at boot time
### END INIT INFO

DAEMON=/usr/local/bin/chinadns
DESC=ChinaDNS
NAME=chinadns
PIDFILE=/var/run/$NAME.pid

test -x $DAEMON || exit 0

case "$1" in
  start)
    echo -n "Starting $DESC: "
    $DAEMON \
        -m \
        -c /usr/local/share/chnroute.txt \
        -p 15353 \
        1> /var/log/$NAME.log \
        2> /var/log/$NAME.err.log &
    echo $! > $PIDFILE
    echo "$NAME."
    ;;
  stop)
    echo -n "Stopping $DESC: "
    kill `cat $PIDFILE`
    rm -f $PIDFILE
    echo "$NAME."
    ;;
  restart|force-reload)
    $0 stop
    sleep 1
    $0 start
    ;;
  *)
    N=/etc/init.d/$NAME
    echo "Usage: $N {start|stop|restart|force-reload}" >&2
    exit 1
    ;;
esac

exit 0

其中,-m 参数表示启用压缩指针(DNS pointer mutation),-c 指定 chnroute 文件,-p 指定监听的端口,没有指定将使用 dns 默认的 53 端口,-s 指定下游 dns 服务器。

建议配合 dnsmasq 使用,支持缓存、tcp 查询,只需要修改 dnsmasq 的配置文件:

no-resolv
server=127.0.0.1#15353

使用 chnroute 文件可以区分国内外 ip,对于国内 ip 可以使用国内的 dns 服务器,如 114.114.114.114。chnroute 文件通过如下命令更新:

curl 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' | grep ipv4 | grep CN | awk -F\| '{ printf("%s/%d\n", $4, 32-log($5)/log(2)) }' > chnroute.txt

可以用 crontab 添加定时任务,每周更新一次。

然后启动 chinadns 服务,并设为开机启动:

sudo chmod +x /etc/init.d/chinadns
sudo service chinadns start
sudo update-rc.d chinadns defaults

为了让连到热点的设备使用我们搭建的 dns 服务器,修改 udhcpd 或 dnsmasq 的配置文件,设置 dns 服务器地址为 192.168.42.1,参考这里

最后,添加 iptables 规则。参考这里,通过启动脚本的方式自动配置 iptables 规则。

修改 /etc/init.d/iptables,在 do_start 函数里面添加:

# shadowsocks rules
iptables -t nat -N SHADOWSOCKS

# - google, chrome, youtube, appspot, blogspot, blogger, feedburner (google)
iptables -t nat -A SHADOWSOCKS -p tcp -d 173.194.0.0/16 -j REDIRECT --to-ports 1080
iptables -t nat -A SHADOWSOCKS -p tcp -d 203.208.32.0/19 -j REDIRECT --to-ports 1080
iptables -t nat -A SHADOWSOCKS -p tcp -d 216.239.32.0/19 -j REDIRECT --to-ports 1080
iptables -t nat -A SHADOWSOCKS -p tcp -d 74.125.0.0/16 -j REDIRECT --to-ports 1080
iptables -t nat -A SHADOWSOCKS -p tcp -d 64.233.160.0/19 -j REDIRECT --to-ports 1080
iptables -t nat -A SHADOWSOCKS -p tcp -d 216.58.192.0/19 -j REDIRECT --to-ports 1080

iptables -t nat -A SHADOWSOCKS -p tcp -j RETURN
iptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS

do_stop 函数里添加:

# shadowsocks rules
iptables -t nat -D PREROUTING -p tcp -j SHADOWSOCKS
iptables -t nat -F SHADOWSOCKS
iptables -t nat -X SHADOWSOCKS

这里面我只加了 google 的 ip 段,其他 ip 段请按以下步骤添加(取自这里):

  1. 使用 dignslookup 查询 chinadns 获得正确 ip。
  2. 借助 APNIC 的 whois 工具,查询 ip 所属的 ip 段,注意单个 ip 和 ip 段的取舍,比如 google 可以加入整个 ip 段,其他的一些小站可能只有一个 ip,就只用加一个了。
  3. 按以上 google 的格式添加 ip 段。

或者暴力一点,所有的国外请求均走代理,参考这里

做完以后重启 iptables 服务,基本就大功告成了。

以上方法的缺点是配置比较麻烦,而且更新代理规则比较麻烦(得先将域名转成 ip)。

二、ss-local + privoxy

上篇文章介绍了使用 privoxy 去广告,其实 privoxy 本身就是一个代理程序,由于支持 intercepting proxy,可用作透明代理。只需要写一些规则,对于匹配的 url 转发给下一级代理 shadowsocks,配置非常简单。

ss-local 的安装与配置跟 ss-redir 基本一致,不再详述。

privoxy 的安装与配置参照上篇文章,亦不再详述。只需要增加一个 actionsfile,并打开 accept-intercepted-requests

actionsfile shadowsocks.action
accept-intercepted-requests 1

actionsfile /etc/privoxy/shadowsocks.action 内容仿照以下格式:

{+forward-override{forward-socks5 127.0.0.1:1080 .}}
.google.com
.google.com.hk
.googleapis.com
.googlecode.com
.googleusercontent.com
.googlevideo.com
.google-analytics.com
.chrome.com
.android.com
.gstatic.com
.appspot.com
.youtube.com
.ytimg.com
.goo.gl
.blogspot.com
.blogger.com
.feedburner.com

同样地,这里只加了 google 的一些网站,其他的自己添加吧,一目了然。

最后,别忘了添加 iptables 规则,同样参考上篇文章

这种方法的优点自然是简单,缺点是受 privoxy 限制,只支持 http 和 https。

实际上,我是两种方法一起用的,将 privoxy 的 iptables 规则加在 shadowsocks 规则前面,这样 http、https 走第二种方法,其他协议走第一种方法,这样所有的协议都支持,而且对去广告没有影响。