用OpenWRT+Shadowsocks实现全自动爬梯子指南

那天在网上瞎逛,无意中发现OpenWRT这个好东东,想用自己路由器试试,无奈我用的这个屌丝水星路由器刷不上OpenWRT(你可以在官网列表上查看自己的路由器是否可刷),第二天逛公司BBS时居然就有人在转二手的TL-WDR4320,180收了!市场价400+这波不亏啊,回来赶紧去官网下固件,这里注意到官网没有WDR4320的固件,但是与WDR4310型号是相同的,故刷上4310的固件是没有问题的.

刷成功之后你的路由器就相当于一个轻量的Linux server,你可以直接在你的电脑上用ssh登录,ip默认是192.168.1.1,端口是22,需要修改的话可以跟一般的路由器一样,用浏览器进入后台管理页面进行配置修改,建议把端口和root密码修改掉.可以在上面装软件呀什么的,由于OpenWRT是基于debian开发来的,所以也有一个类似于ubuntu的apt-get的包管理工具,这里是opkg,安装软件全靠它,当然你也可以直接ipk包然后直接安装,但是然后安装的软件有依赖包就会非常的麻烦,所以推荐直接用opkg管理.另外还需要注意的是路由器上的硬件和实际的server是不能比的,所以OpenWRT上的软件也是精简过的,体积比较小,可以用opkg直接从官网下载已经编译好的包,看了一下好多软件上面都会有,但是直接从官网下载有一个问题,下载速度慢暴了!不能忍了啊,8成跟操蛋的GFW有关,话说之前去香港用联通的漫游网居然也有操蛋的GFW…………….

  • 配置软件包镜像

google了一下大陆居然没有的OpenWRT软件集镜像,也罢,用自己VPS搭一个吧,先用wget -mk –no-parent https://downloads.openwrt.org/chaos_calmer/15.05/ar71xx/generic/packages/ 把官网上的包下载到VPS上,全部包加起来也就300多m,我这里用的是15.05的版本ar71xx固件的包,你可以根据自己的路由硬件下载,然后配置nginx,

location / {
autoindex on; #显示索引
autoindex_exact_size on; #显示大小
autoindex_localtime on; #显示时间
}

我这里的域名是openwrt.herowong.me,再去域名供应商那把二级域名的IP绑定在用的VPS的IP上,再到/etc/opkg.conf 中把所有官网的地址downloads.openwrt.org替换成openwrt.herowong.me,保存,这样下载包的速度就比官网的快多了,然后自己再写个crontab什么的定期mirror一下我就懒得搞了,有需要的同学可以用我的镜像,如果你用也是ar71xx固件的话^_^

OK,环境搭好以后,我们就来安装Shadowsocks客户端了,这里需要注意的是有4个版本的client可以下载,具体用途看看官网上的说明吧,我用的是 shadowsocks-libev-spec,直接用wget下载到router server上,或者如果需要想要先把文件下载到本地,再从本地拷贝到router server的话,建议安装一下lrzsz, opkg install lrzsz,然后就可以用命令rz -e -y从本地拷贝文件了.用opkg安装指定文件的方法是opkg install /your-file-path/filename.ipk, opkg会自动判断依赖关系进行相关包的下载

  • 配置shadowsocks

 接下来是配置shadowsocks-client让它实现自动爬梯子,我们先来讲一下实现原理,我们需要一个被墙网站的域名列表(gfwlist),让ss-client判断如果用户访问到这个列表中的网站就自动走梯子,否则就走”其它国家”的网,这里注意到一点是,我们知道在访问一个域名时,浏览器先会对这个域名进行DNS解析,取到这个域名的真实IP,再请求这个IP取得网站的具体内容,所以一个请求对路由器而言,它看到的是IP而不是域名.那么我们就需要把gfwlist中所有的域名通过DNS转换成IP,

这里用到了ipset,简单的说,ipset的作用是维护ip列表,我们需要把gfwlist里的真实IP导入ipset中,用iptables来控制用户请求的流向(是走向墙内还是墙外).顺便多说一句,之前查了好多类似的教程,可能写的时候ss-openwrt版本还比较老,需要手动增加iptables,我用的这个版本2.3.3已经在脚本中帮你写好了,安装完ss-openwrt后,每次启动都会向iptables中写入几条规则,停掉程序时会把原来写入的规则自动清除.刚开始我也是按照网上的教程手动写入规则,发现规则死活不生效,一个匹配规则的包的没有,看了一下ss-rules源码,其实它是一个shell脚本,才发现原来请求先被程序里写入的规则匹配走了,汗…..

iptables -t nat -L

20151108155212

我们可以看到脚本在NAT表中加入了一些规则,在SS_SPEC_WAN_AC和SS_SPEC_WAN_FW这两条chain中,注意SS_SPEC_WAN_AC中的第二条规则是我自己加上的,功能是查询gfwlist,后面会说到先忽略这条规则,翻译一下意思是,当要发送所有tcp请求的时候,先匹配SS_SPEC_WAN_AC

RETURN     all  —  any    any     anywhere             anywhere             match-set ss_spec_wan_ac dst

RETURN     all  —  any    any     anywhere             anywhere             ! match-set fuckgfw dst (先忽略我,当我不存在)

SS_SPEC_WAN_FW  all  —  any    any     anywhere             anywhere

SS_SPEC_WAN_AC中第一条规则的意思是,当请求目的地址匹配到ss_spec_wan_ac中的信息时,退出规则匹配,直接请求这个网址.再看看ipset里ss_spec_wan_ac写着什么

ipset list ss_spec_wan_ac

20151108161124

原来ss-rules已经帮我们写了一些局域网的IP,访问这些IP不需要爬梯子,否则…

OK,那我加的第二条规则的意思就是请求目的地址匹配到fuckgfw中的信息时,也直接请求这个网址,不走梯子,换一句话说,就是匹配了fuckgfw中的信息就需要走梯子,大家很容易就知道了,fuckgfw这个ipset中存放的就是gfwlist中域名的真实IP

  • gfwlist域名IP转换

现在我们的问题是怎么把gfwlist中的域名转换成IP,并且把IP增加到名为fuckgfw的ipset中呢?首先我们需要创建一下ipset

ipset -N fuckgfw iphash

这里我们需要感谢gfwlist2dnsmasq项目,为了防止DNS污染把router的DNS修改为google的8.8.4.4.这个项目会生成一个gfwlist转dns的列表,格式是这样

server=/.google.com/127.0.0.1#5353
ipset=/.google.com/fuckgfw
server=/.facebook/127.0.0.1#5353
ipset=/.facebook/fuckgfw
server=/.twitter.com/127.0.0.1#5353
ipset=/.twitter.com/fuckgfw

但是这样并不安全,如果操蛋的运营商把你的53端口给劫持了就呵呵了,具体看我的另外一篇博客

这里注意.OpenWRT原装的dnsmasq默认是不支持ipset的,需要安装dnsmasq-full版本,而这里,可以你把原来的dnsmasq卸载掉之后,需要修改/etc/resolv.conf文件中的dns地址,由原来指向本地的dnsmasq 127.0.0.1,修改为一个可以正常解析的地址,比如8.8.4.4.以免再用opkg安装dnsmasq-full版本的时候无法解析dns而下载失败

 新建目录/etc/dnsmasq.d, 把生成的文件dnsmasq_list.conf拷贝进去,再在/etc/dnsmasq.conf 的最后加入一行

conf-dir=/etc/dnsmasq.d

表示当dns服务启动时,要读取/etc/dnsmasq.d目录中的配置文件,然后重启一下dnsmasq

 /etc/init.d/dnsmasq restart

解释一下生成的文件的意思,拿前两行作例子,这是系统dnsmasq自带的功能.当dns服务启动时,会向127.0.0.1:5353这个端口对google.com这个网址发送dns解析请求,解析得出的IP地址,存放到名字为fuckgfw的ipset中,我在本地用了ChinaDNS,所以请求的端口是127.0.0.1:5353,你可以把它修改成其它的dns服务器,比如8.8.4.4:53

重启完以后到ipset里看一下,ip是否已经导入,ipset list fuckgfw,发现什么也没有?当时我就慌了.难道是IP木有导入?于是google了一下,没有太详细的答案…咦…不对呀..肿么可以直接连上google了,再去看一下ipset,里面多个几个IP,去看系统日志,gfwlist里所有的域名都进行过dns解析了呀.原来从dnsmasq里导入ipset的时候,虽然已经导入成功了,刚导入的时候用ipset list 是显示不出来了,只有当请求过这个IP之后,这个IP才会在list里表示出来…好了.哪位大神可以告诉我一下这是为什么….

至此,我们就可以实现自动爬梯子了,如果你发现哪个网站被墙了,可以你需要强制给哪个网址加梯子,可以先用ping,解析出它的真实IP,然后ipset add fuckgfw xxx.xxx.xxx.xxx,加入列表就可以了

但是,还有一个问题,我不可能在每次路由器重启的时候都手动去加一条规则吧..所以在/usr/bin/ss-rules,这个ss-openwrt生成的规则脚本中 ,ipset_r函数中加上一行

$ipt_n -A SS_SPEC_WAN_AC -m set ! –match-set fuckgfw dst -j RETURN && \

20151108171204

这里还需要注意一个问题就是,当路由重启的时候,ipset中的数据会丢失,所以我们需要重新创建一个ipset列表,为了在重启时自动创建ipset列表,我们需要在dnsmasq脚本中加一行命令,路径/etc/init.d/dnsmasq

ipset list fuckgfw > /dev/null || ipset -N fuckgfw iphash

意思是当ipset 中不存在fuckgfw表列的时候,新建一个,ipset list的时候,如果表列不存在会返回非0,用||判断非0来选项是否执行后面的命令

20151212161345

注意加的位置要对哦~

然后/etc/init.d/shadowsocks enable ,每次路由器重启的时候都启动shadowsocks

Now enjoy it~~~

参考:

Shadowsocks + GfwList 实现 OpenWRT 路由器自动翻墙

OpenWrt VPN 按域名路由

OpenWrt智能、自动、透明翻墙路由器教程

GitHub : gfwlist2dnsmasq

Leave a Reply

Your email address will not be published. Required fields are marked *