Netgear WNDR4300 翻墙手册

写在开篇

该文仅仅适合程序员阅读,除非你至少明白什么是telnet和ssh,否则就去找更适合的教程吧

1.背景介绍:什么是gfw

gfw的定义可以参见维基百科。最直观的感受,就是google,facebook等一票网站访问不了。但是作为程序员,我们有必要知道为什么这些网站访问不了?当然这些网站被阻止访问了,但是是如何阻止的??

作为程序员,你可能会首先想到,不就是这个网站ip被阻止访问了嘛。但实际上,这只是原因之一,gfw手段中最不起眼的一个。因为google和facebook这样的大公司有成千上万的ip,且每天都在变化,因此,封ip根本来不及。其实,更大的原因是:DNS污染

来做个实验(在家中,在单位代理上网的情况下无法进行),调出终端,打入以下命令

nslookup twitter.com

nslookup是用来查看某个域名真实ip的命令

各系统返回稍有不同,但基本上都是如下:

Server: 172.25.23.1

Address: 172.25.23.1#53

Non-authoritative answer:

Name: twitter.com

Address: 37.61.54.158

可以看到twitter.com被解析到了37.61.54.158,如果进一步用whois跟踪,你会发现这个地址的详细信息







key value
IP Location Azerbaijan Azerbaijan Bakixanov Baktelekom
ASN Azerbaijan AS28787 BAKINTER-AS Baktelekom,AZ (registered Feb 24, 2003)
Whois Server whois.ripe.net
IP Address 37.61.54.158

那么问题来了,你觉得twitter.com这样的公司,会使用一个阿塞拜疆的ip地址吗,这就是问题所在,gfw把要屏蔽的网站的域名都解析到了类似于37.61.54.158这样的空地址上,且在你家的宽带,手机等等所有设备上蔓延。

程序员可能会想到,不是可以指定dns地址嘛,我用第三方的dns是不是就没有问题了,那我们再来做个实验

nslookup twitter.com 8.8.8.8

nslookup可以指定第二个参数,强制使用这个dns解析

8.8.8.8是google提供的公共dns服务

但返回结果依然是

Non-authoritative answer:

Name: twitter.com

Address: 37.61.54.158

这是为什么,还是这个地址。原因是dns使用的是udp的协议,基本逻辑是本机先发往本机的53端口进行查询,如果本机不知道,就向dns查询,依次向上。upd协议是不建立连接的,且是明文传递,非常容易被伪造。gfw就利用了这一点,你发向8.8.8.8的dns查询,gfw先给你一个假回执,就诱骗了你的机器。(实际上,8.8.8.8的回执稍后也会到来,但是本机会认为已经拿到回执,就把它忽略了)

其实从这里就可以看出,在一些公共wifi下,如果你忽略证书有问题的警告,被钓鱼是一件多么容易的事情,亲们

程序员可能会想,那有没有办法用tcp协议查询,答案是肯定的:

nslookup -vc twitter.com 8.8.8.8

你会得到如下应答

Server: 8.8.8.8

Address: 8.8.8.8#53

Non-authoritative answer:

Name: twitter.com

Address: 199.59.150.7

Name: twitter.com

Address: 199.59.150.39

Name: twitter.com

Address: 199.59.149.198

Name: twitter.com

Address: 199.59.149.230

这才是真实的ip

亲们看完是不是一身冷汗,其实网络世界确实挺可怕的,小白被骗钱简直分分钟的事情,所以,程序员们有必要学习有关知识


开始我们的实践吧,基于以上的认识,我们要科学上网,至少需要做两件事情

  • 解决ip被阻断问题

  • 解决dns污染问题

我们的使用的方法:将被墙的站点通过dnsmasq+ipset打标记,然后通过iptables的路由功能将这些ip通过shadowsocks转发出去,其中这些名词,下面一步一步做完,你就会熟悉


2.准备工作

  • 我们需要一个shadowsocks服务帐号,用来通过加密通道访问网站。我目前使用的 http://my.ssh91.net 的服务,一个月10RMB,可以流畅看720p的youtube。购买后,会收到确认邮件,内含密码等信息。几个节点自己选一个,我目前使用ss02台湾节点。

  • 一台路由器,理论上能刷openwrt的内存足够的路由器都可,但这里针对Netgear wndr4300写的。我在京东活动时购买的,299RMB

  • 一个adsl上网环境,或者静态ip的也可以,再复杂的上网认证方式,我就不保证有效了

  • 一根网线,openwrt刚刷好时,是关闭wifi的,只能通过网线连接

  • 没有了

3.刷新ROM

首先从openwrt官网下载适合wndr4300的rom,openwrt的官网下载地址是:http://downloads.openwrt.org , 在写该文时,最新的版本是14.07,因此对应的下载地址是http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/nand/openwrt-ar71xx-nand-wndr4300-ubi-factory.img ,注意一定不能下载错了,否则就变砖了。下载好了之后,就可以通过路由器控制台的系统更新,将该ROM刷进去。正常情况下,路由器自动重启后,就刷新完毕了。

这里要注意一下,带有factory的版本是从官方固件升级时使用的,而带有sysupgrade标志的,是给已经刷了openwrt的用户升级用的

4.设置openwrt上网环境

刚刷好openwrt,系统默认关闭了wifi,只能通过网线连接。插好网线,浏览器输入http://192.168.1.1

即可进入控制台。默认的用户名为root,密码为空,因此直接点击login就可以进入了。进入后,注意到上半部分有change password的提示,点击进入后,就可以设置新的登录密码。设置时,只需要填写好密码并点击Save & Apply保存幷应用设置即可。

登录密码设置后,默认系统终端就从telnet转为了ssh登录方式

设置好之后,重新进入http://192.168.1.1 ,就来到了主界面。主界面显示的都是当前路由器的状态。接下来我们设置wifi。找到wireless部分,应该可以看到两个disabled的节点。上面一个是2.4GHz的,下面一个是5GHz的。首先设置上面一个2.4GHz的,点击默认的SSID(一般为openwrt),设置新的SSID,第二个Security页签,Encryption建议选择WPA2-PSK,Cipher选择Force CCMP,Key填写您的密码。以上是标准部分设置,接下来我们再进行一些优化设置。页面上半部分有个Advanced Setting,其中HT Mode选择40MHz,Force 40Mhz选中,Country选择US。好了,点击Save & Apply保存幷应用设置。最后,点击页面上半部分中的General Setup中的Enable,打开wifi就可以了。5GHz的设置一模一样,只不过SSID不同即可。

现在wifi应该已经正常工作了,可以拔掉网线,连接wifi使用。接下来设置宽带pppoe。菜单中选择Network-Interfaces,点击WAN端的Edit进行编辑。首先选择protocol为PPPoE,再点击Switch Protocol进行应用。出现了username和password字段,填入您的宽带帐号和密码,点击Save & Apply保存幷应用设置。过一会,回到主页面,应该可以在WAN Status看到宽带分配的IP等信息,证明联网成功了。好了,暂时可以享受正常的上网生活了。

5.尝试ssh登录

Windows默认没有ssh命令,因此需要下载其它软件登录,推荐PuTTY,其它系统ssh肯定是内建命令。Windows下,打开PuTTY,输入192.168.1.1,用户名root,密码是你刚才设置的登录密码。其它系统下,直接命令行输入ssh root@192.168.1.1即可。这时候,你就进入了openwrt的系统,openwrt是基于Linux的系统,因此,什么ls,vi等命令都是直接可以用的,你可以先把玩把玩

6.升级dnsmasq

Dnsmasq 提供 DNS 缓存和 DHCP 服务功能。作为域名解析服务器(DNS),dnsmasq可以通过缓存 DNS 请求来提高对访问过的网址的连接速度。作为DHCP 服务器,dnsmasq 可以为局域网电脑提供内网ip地址和路由。

默认的dnsmasq为base版本,该版本不能对特定的域名地址进行标记操作(因为我们需要对一些特定域名如twitter等进行标记),因此,首先我们需要升级为更高版本的dnsmasq-full,运行如下命令即可重新安装高级版的dnsmasq:

#更新软件列表

opkg update

#运行remove命令后,会提示有一个文件被改动,无法删除,请手工删除

opkg remove dnsmasq

#安装新软件

opkg install dnsmasq-full

#重新启动dnsmasq

/etc/init.d/dnsmasq restart

opkg是openwrt的包管理器,如果只熟悉WIndows的同志,你就理解为360软件中心吧。update命令刷新最新的软件列表,一般重启路由器后,要使用opkg安装包,都需要先运行update。remove就是删除已经安装的软件。install是安装软件

之后,运行如下命令

dnsmasq -v

确认版本信息中有ipset字样

7.安装chinadns

chinadns项目主页:https://github.com/clowwindy/ChinaDNS-C ,该项目就是为了阻止dns污染而开发的。

因为chinadns并没有登记到opkg软件列表中,因此只能手动下载安装。从 http://sourceforge.net/projects/chinadns/files/dist/ 找到属于ar71xx的最新版本并下载,之后上传到路由器的/tmp目录下。Windows下,可以用WinScp软件进行上传;其它系统,可以直接用scp命令上传。当然,也可以在路由器用wget命令直接下载到/tmp目录。之后运行如下命令进行安装

cd /tmp

opkg install chinadns-xxx.ipk

安装好了之后,用vi编辑/etc/init.d/chinadns文件,找到含有iptables字样的两行,删除或者用#注释掉

之所以要删除iptables两行,是因为默认chinadns利用路由表直接拦截dns请求,但是因为我们要用dnsmasq配合chinadns打标记,因此要禁用其iptables功能

之后运行如下命令

#启动chinadns

/etc/init.d/chinadns restart

#设置chinadns为开机自动启动

/etc/init.d/chinadns enable

#确认chinadns已经启动

netstat -an|grep 5353

之后配置dnsmasq,让其用chinadns作为上游dns。vi编辑/etc/dnsmasq.conf,在最后加入如下内容

no-resolv

server=127.0.0.1#5353

log-queries

这三行的意思是:1.禁用宽带提供商提供的dns 2.设置上游dns为127.0.0.1#5353 3.开启日志功能

之后,重启dnsmasq

/etc/init.d/dnsmasq restart

好了,可以试一试dns是不是有污染了,在路由器上运行

nslookup twitter.com

看看是不是得到了真实的ip

再来试一试局域网内的机器。首先需要清除本机的dns缓存。Windows下输入

ipconfig /flushdns

其它系统可以关闭wifi再打开即可

有问题如何调试

  • 确认chinadns已经启动,netstat -an|grep 5353

  • 确认chinadns可以工作,电脑上运行如下命令,nslookup -p 5353 twitter.com 192.168.1.1,确认得到正确解析

  • 确认dnsmasq可以工作,电脑上运行如下命令,nslookup -p 53 twitter.com 192.168.1.1,确认得到正确解析

  • 清楚本机缓存,或者重启

8.安装ipset

我们一直说要把特殊的域名打标记,但是至今还没有做什么嘛。是的,这就做起,就用ipset。首先安装他

opkg install ipset iptables-mod-nat-extra 

安装时,可能会提示如下

kmod: failed to insert /lib/modules/3.10.44/ip_set.ko

kmod: failed to insert /lib/modules/3.10.44/ip_set_bitmap_ip.ko

kmod: failed to insert /lib/modules/3.10.44/ip_set_bitmap_ipmac.ko

kmod: failed to insert /lib/modules/3.10.44/ip_set_bitmap_port.ko

kmod: failed to insert /lib/modules/3.10.44/ip_set_hash_ip.ko

kmod: failed to insert /lib/modules/3.10.44/ip_set_hash_ipport.ko

kmod: failed to insert /lib/modules/3.10.44/ip_set_hash_ipportip.ko

kmod: failed to insert /lib/modules/3.10.44/ip_set_hash_ipportnet.ko

kmod: failed to insert /lib/modules/3.10.44/ip_set_hash_net.ko

kmod: failed to insert /lib/modules/3.10.44/ip_set_hash_netiface.ko

kmod: failed to insert /lib/modules/3.10.44/ip_set_hash_netport.ko

kmod: failed to insert /lib/modules/3.10.44/ip_set_list_set.ko

kmod: failed to insert /lib/modules/3.10.44/xt_set.ko  

这个没有关系,需要重启一下路由器,再重启前,我们先把ipset初始化命令加入开机启动

编辑/etc/firewall.user,加入ipset -N setmefree iphash

之后运行reboot命令重启即可

重启好之后,登录路由器,然后运行

ipset list 

可以看到一个名为setmefree的节点,但是members为空

是时候加入需要打标签的域名了,vi编辑dnsmasq.conf,再到后面加入以下内容

#Google

ipset=/.google.com/setmefree

ipset=/.google.com.hk/setmefree

ipset=/.google.com.tw/setmefree

ipset=/.google.com.jp/setmefree

ipset=/.gstatic.com/setmefree

ipset=/.ggpht.com/setmefree

ipset=/.googleusercontent.com/setmefree

ipset=/.appspot.com/setmefree

ipset=/.googlecode.com/setmefree

ipset=/.googleapis.com/setmefree

ipset=/.google-analytics.com/setmefree

ipset=/.youtube.com/setmefree

ipset=/.googlevideo.com/setmefree

ipset=/.youtube-nocookie.com/setmefree

ipset=/.ytimg.com/setmefree

ipset=/.blogspot.com/setmefree

ipset=/.blogger.com/setmefree



#FaceBook

ipset=/.facebook.com/setmefree

ipset=/.thefacebook.com/setmefree

ipset=/.facebook.net/setmefree

ipset=/.fbcdn.net/setmefree

ipset=/.akamaihd.net/setmefree


#Twitter

ipset=/.twitter.com/setmefree

ipset=/.t.co/setmefree

ipset=/.bitly.com/setmefree

ipset=/.twimg.com/setmefree

ipset=/.tinypic.com/setmefree

ipset=/.yfrog.com/setmefree

#Flickr

ipset=/.flickr.com/setmefree

ipset=/.staticflickr.com/setmefree



#Wordpress

ipset=/.wordpress.org/setmefree

ipset=/.wordpress.com/setmefree

ipset=/.w.org/setmefree

ipset=/.wp.com/setmefree



#Others

ipset=/.dropbox.com/setmefree

ipset=/.github.com/setmefree

ipset=/.hk/setmefree

ipset=/.tw/setmefree

ipset=/.btdigg.org/setmefree

ipset=/.keepvid.com/setmefree

ipset=/.feedly.com/setmefree

ipset=/.godaddy.com/setmefree

ipset=/.digicert.com/setmefree

ipset=/.gravatar.com/setmefree

ipset=/.live.com/setmefree

ipset=/.zdassets.com/setmefree

ipset=/.cloudfront.net/setmefree

ipset=/.instagram.com/setmefree

ipset=/.playstation.net/setmefree

ipset=/.akadns.net/setmefree  

这些域名包括了经常访问的域名地址

解释一下ipset规则,该规则为泛域名结构,即如果.google.com会包括www.google.com,mail.google.com等一切子域名,所以如果你不爽,甚至可以.com,哈哈

你可能注意到google部分没有gmail,因为我的shadowsocks服务商,似乎不支持gmail的imap协议,导致邮件客户端无法访问gmail。因此我把它拿掉了,如果要访问gmail,可以用mail.google.com

重新启动dnsmasq

/etc/init.d/dnsmasq restart

之后,我们再来试一试

#查询一次域名查找

nslookup twitter

#看看ipset里面有什么

ipset list

如果不出意外的话,已经可以看到members下面有twitter.com的ip了

有问题如何调试

  • nslookup twitter.com后,确认ipset list结果中有ip

  • ipset flush setmefree,可以清除列表

9.配置shadowsocks

shadowsocks客户端主页: https://github.com/aa65535/openwrt-shadowsocks

有了打标记的ip,我们只需要将这些ip的访问通过shadowsocks转发出去即可

shadowsocks同样不在opkg软件列表中,需要手动下载,下载地址 http://sourceforge.net/projects/openwrt-dist/files/shadowsocks-libev/ ,找到最新版本的ar71xx下的shadowsocks-libev-polarssl-xxx.ipk,下载并上传路由器并安装,方法同chinadns

默认该客户端是代理模式(socks5),我们需要使用转发模式

因此,编辑/etc/init.d/shadowsocks,将两行ss-local用#注释掉,再将ss-redir两行前的注释拿掉

编辑shadowsocks的配置文件 /etc/shadowsocks.json,按照服务提供商提供的信息,配置它,如

{

        "server": "ss02.8ke.co",

        "server_port": xxx,

        "local_port": 8964,

        "password": "xxxx",

        "method": "rc4-md5"

}

记录你的local_port,可以尝试启动一下

ss-redir /etc/shadowsocks.json

如果没有报错,就说明shadowsocks启动正常,ctrl-c杀掉他,用如下命令启动shadowsocks

#启动

/etc/init.d/shadowsocks restart

#加入开机启动

/etc/init.d/shadowsocks enable

#确认已经启动

netstat -an|grep 8964

有些版本的shadowsocks依赖有问题时,会报错缺少libpolarssl.so.5的错(版本有时候不是5),这时候只需要做一个符号链接即可

ln -s /usr/lib/libpolarssl.so /usr/lib/libpolarssl.so.5

最后,设置路由规则,让打标记的ip都去shadowsocks端口,运行如下命令

iptables -t nat -A PREROUTING -p tcp -m set --match-set setmefree dst -j REDIRECT --to-port 8964

注意端口用你配置的端口

然后将该命令加入/etc/firewall.user,让其随着开机一起启动

有问题如何调试

  • 确认shadowsocks已经启动,netstat -an|grep 8964

  • 确认路由表规则已经加入,iptables -t nat -L

到这里,所有的工作都完成了,打开浏览器,访问一下www.facebook.com,世界应该被还原了

结束语

其实就是将被墙的站点通过dnsmasq+ipset打标记,然后通过iptables的路由功能将这些ipset通过shadowsocks转发出去。明白原理,一步一步弄,应该没有问题,如果有问题,看看每一步的如何调试,确认问题是出在哪里。总归,openwrt是个伟大的系统,自己动手,搭个站点在路由器上,也没有问题。感谢程序员们。