Wenjian's Blog

Live and Learn

HOWTO: 利用OpenWrt路由器上的Shadowsocks+DNSMasq科学上网

HOWTO: Prevent DNS cache pollution一文中,我介绍了利用DNS服务器的非标准端口来防止DNS污染。但即使获得了正确的ip地址,我们也不一定能上网,原因。。。你懂的。这儿介绍一种方法,在OpenWrt路由器上利用Shadowsocks和DNSMasq达到局域网内零配置科学上网。

一个Shadowsocks服务器是必须的,你可以在自己的VPS上搭建一个,方法参见HOWTO: Install and configure shadowsocks on VPS/Ubuntu。或者你可以找一个免费的Shadowsocks服务器,推荐一个获取免费账号的网址https://www.shadowsocks.net/get

安装Shadowsocks

我的OpenWrt版本是AA 12.09,首先更新libpolarssl到最新版本:

$ wget https://downloads.openwrt.org/snapshots/trunk/ar71xx/packages/base/libpolarssl_1.3.8-1_ar71xx.ipk
$ sudo opkg install libpolarssl_1.3.8-1_ar71xx.ipk

下载并安装Shadowsocks:

$ wget http://shadowsocks.org/nightly/shadowsocks-libev-polarssl_1.4.6_ar71xx.ipk
$ sudo opkg install shadowsocks-libev-polarssl_1.4.6_ar71xx.ipk

配置Shadowsocks

Shadowsocks安装之后在/usr/bin会有三个文件:

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

本文方法利用的是shadowsocks的透明代理功能。

编辑配置文件/etc/shadowsocks.json,

{
    "server":"xxx.xxx.xxx.xxx",
    "server_port":8388,
    "local_port":1081,
    "password":"demo",
    "timeout":600,
    "method":"aes-256-cfb"
}
  • server: 你的Shadowsocks服务器的IP地址 (IPv4/IPv6).
  • server_port: 你的Shadowsocks服务器端口.
  • local_port: 本地端口.
  • password: 你的Shadowsocks服务器的账号密码.
  • method: 你的Shadowsocks服务器采用的加密方式, “bf-cfb”, “aes-256-cfb”, “des-cfb”, “rc4”, 等等.

编辑/etc/init.d/shadowsocks

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

START=94

SERVICE_USE_PID=1
SERVICE_WRITE_PID=1
SERVICE_DAEMONIZE=1

start() {
 service_start /usr/bin/ss-redir -c /etc/shadowsocks.json
}

stop() {
 service_stop /usr/bin/ss-redir
}

运行Shadowsocks透明代理:

$ sudo /etc/init.d/shadowsocks start
$ sudo /etc/init.d/shadowsocks enable

添加防火墙规则

我们可以从APNIC获得最新的中国IP地址列表,利用iptables添加防火墙规则,保存以下文本为gen-firewall-gfw.sh

#!/bin/ash

# Write gfw iptables
firewall_gfw="/usr/bin/firewall-gfw.sh"
if [ -f $firewall_gfw ]; then
 rm $firewall_gfw
fi

echo "#!/bin/ash" >>$firewall_gfw
echo >>$firewall_gfw
echo "# Create a new chain named SHADOWSOCKS" >>$firewall_gfw
echo "iptables -t nat -N SHADOWSOCKS" >>$firewall_gfw
echo >>$firewall_gfw

echo "# Ignore shadowsocks server" >>$firewall_gfw
echo "iptables -t nat -A SHADOWSOCKS -d xxx.xxx.xxx.xxx -j RETURN" >>$firewall_gfw
echo >>$firewall_gfw

echo "# Ignore LANs ip addresses" >>$firewall_gfw
echo "iptables -t nat -A SHADOWSOCKS -d 0.0.0.0/8 -j RETURN" >>$firewall_gfw
echo "iptables -t nat -A SHADOWSOCKS -d 10.0.0.0/8 -j RETURN" >>$firewall_gfw
echo "iptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN" >>$firewall_gfw
echo "iptables -t nat -A SHADOWSOCKS -d 169.254.0.0/16 -j RETURN" >>$firewall_gfw
echo "iptables -t nat -A SHADOWSOCKS -d 172.16.0.0/16 -j RETURN" >>$firewall_gfw
echo "iptables -t nat -A SHADOWSOCKS -d 192.168.0.0/16 -j RETURN" >>$firewall_gfw
echo "iptables -t nat -A SHADOWSOCKS -d 224.0.0.0/4 -j RETURN" >>$firewall_gfw
echo "iptables -t nat -A SHADOWSOCKS -d 240.0.0.0/4 -j RETURN" >>$firewall_gfw
echo >>$firewall_gfw

echo "# Ignore China ip addresses" >>$firewall_gfw
# Get latest delegated internet number resources from apnic
cd /tmp
if [ -f "delegated-apnic-latest" ]; then
 echo "deleting old delegated internet number resources ..."
 rm delegated-apnic-latest
fi
echo "Downloading latest delegated internet number resources from apnic ..."
wget -c http://ftp.apnic.net/stats/apnic/delegated-apnic-latest

echo "Extracting china ip addresses from downloaded latest delegated internet number resources ..."
cat delegated-apnic-latest | awk -v awk_firewall_gfw=$firewall_gfw -F '|' '/CN/&&/ipv4/ \
 {print "iptables -t nat -A SHADOWSOCKS -d " $4 "/" 32-log($5)/log(2) " -j RETURN" >>awk_firewall_gfw}'
 
echo >>$firewall_gfw

echo "# Ohter ip addresses should be redirected to shadowsocks' local port" >>$firewall_gfw
echo "iptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports 1081" >>$firewall_gfw
echo >>$firewall_gfw

echo "# Apply the rules" >>$firewall_gfw
echo "iptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS" >>$firewall_gfw

echo "Firewall rules for shadowsocks have been written into file " $firewall_gfw

然后

$ chmod +x gen-firewall-gfw.sh
$ ./gen-firewall-gfw.sh
$ sudo ./firewall-gfw.sh

用iptables命令查看一下这些规则有没有添加进去:

$ sudo iptables -t nat --list

大功告成。

现在所有通过你的路由器上网的设备无需设置就可以科学上网啦。

2 responses to “HOWTO: 利用OpenWrt路由器上的Shadowsocks+DNSMasq科学上网

  1. BaiBai December 24, 2015 at 3:23 pm

    这篇教程正是我苦苦寻找的!谢谢你!另外有以下问题:

    为什么使用ss-redir?这个和ss-local到底有什么区别?在你的文章中,如果使用ss-local建立一个本地的socks5代理,将国外ip段都foward到这个socks5代理的端口去,会发生什么?

    这个方法貌似只把TCP给代理了,但是UDP怎么办?如果服务器的ss server支持UDP转发,是否用iptables直接转发udp(抄tcp的配置)就可以了?

    Like

Leave a comment