今天入手了一个TP-LINK的WR841N路由器。 于是迫害妄想症发作,将路由器刷成开源固件OpenWRT,并进行了一些配置,将折腾的过程写在这里。

简介

正面图

(图片来自TP-LINK官网)

WR841N外观设计比较简洁,因为看到有2个天线,觉得性能应该不错,就入手了。

在购买之前在OpenWRT的网站上查到, WR841N 和 WR841ND 另一款路由可以使用同样的固件,在型号上的区别,D是Detachable,指天线可以拆下。

那么,WR841ND 能否刷 OpenWRT 呢?还是查OpenWRT的维基,结果大概有以下几点:

  • 该路由器是可以安装OpenWRT的(废话,不然就没有这篇博文了)。
  • WR841N 有多种硬件版本:v1.x, v3.x, v5.x, v7.x, v8.x(汉语和国际版两种), v9.x, v10.x, v11.x,发售时间从2007年到2015年不等。
  • 这个路由器的缺点是,各种版本的硬件上的闪存容量都小得可怜,只有4MB。内存还有32MB呢。这样给OpenWRT扩展功能的空间就比较有限。

刷OpenWRT

第一步:确定硬件版本,寻找相配的固件

像WR841N这种同一个型号的路由器,在市场上存在了很长时间,其硬件也随着不断的开发有所改变,这就是所说的硬件版本。 不同版本的硬件可以差别很大,比如用到的芯片都不同。对于固件(操作系统)来说,这意味着各种驱动和配置上的不同。 所以,一定要根据硬件的版本,选择能配合工作的固件——仅仅知道路由器的型号是不同的!

查看硬件版本可以进入路由器的管理界面。

将路由器接上电源、网线,等待一会启动后,用电脑登录192.168.0.1,默认用户名和密码都是admin。 在系统固件升级的界面中,可以看到硬件版本(Hardware Version)一项。笔者的路由器是v10。

根据前面查到的OpenWRT的维基中的数据,这个版本还是很新的,是2015年发售的路由器才有,所以目前没有官方维护的固件。

对路由器各个硬件版本支持的情况如下(英语好的读者,请移步到原文页面,以便查看最新的状态):

硬件版本 发售时间 支持的OpenWRT版本 最新版本 注释
v1.x 2007 10.03(.01) & 12.09 & 14.07 & 15.05 15.05 OpenWRT开始支持本型号
v3.x 2008 10.03(.01) & 12.09 & 14.07 & 15.05 15.05 报告
v5.x 2010 10.03(.01) & 12.09 & 14.07 & 15.05 15.05 报告
v7.x 2010 12.09 & 14.07 & 15.05 15.05 本版变成碟形外壳; 12.09完全可用
v8.x 中文 - Trunk r29631(modified) ? ? 硬件闪存只有2MB,需要修改硬件
v8.x 国际 2012/08 12.09 & 14.07 & 15.05 15.05 DB120; 论坛贴子
v9.x 2014 14.07 & 15.05 15.05 14.07 wifi慢,应升级到15.05
v10.x 2015 trunk & 15.05(非官方) 15.05+luci的镜像(非官方) 论坛贴子。对应的Ticket20757
v11.x 2015 未知 15.05+luci的镜像(非官方) 贴子。镜像的内核版本和正常的15.05不同,可能在安装其他包时出错。很接近v10.x

第二步:给路由器刷入固件

首先根据上一步下载合适的固件。

下载时应当尽量使用https链接,这样可以减少下载到的固件内容出错或者被篡改的可能。 当然,最好是能使用md5校验工具,计算下载到的固件的md5散列值,然后和官方发布的md5sum结果对比下。

刷入固件直接使用路由器管理界面中的系统固件升级功能即可。但是要注意OpenWRT的官方维基中提到的一个细节:

从TP-LINK官方的大约是150310之后的固件开始,刷新固件会验证固件文件的文件名。
所以直接下载的固件按照原本的文件名上传到路由器,路由器会直接不认(笔者测试后直接显示连接被重置——当然这和墙无关,只是路由器程序上粗暴的检验方式而已)。

(这一条奇怪的说明更加坚定了我刷掉官方固件的决心~)

所以,在刷新固件之前,要将固件按照官方固件的格式进行重命名:

例如,对于v9的硬件,可以用类似wr841nv9_wr841ndv9_en_3_16_9_up(150310).bin的名字。 我猜测: wr841nv9_wr841ndv9应该是适合的型号,即WR841N的v9版本固件和WR841ND的v9版本固件; en应该是语言; 3_16_9是内核版本; 150310是2015年3月10日的意思。

于是将我下载的v10版本的非官方固件命名成 wr841nv10_wr841ndv10_en_3_16_9_up(160105).bin 。 之后再刷,果然成功。

在读者点击确定之前,这里当然还要例行提醒一遍:

刷固件的过程中,要仔细注意每个细节,另外不能中途断电,否则会失败。 刷固件是危险的,如果失败,可能导致路由器变砖(无法启动,或者软件错误,无法继续修复),甚至因此失去质保。

于是开始刷固件。这个过程大概持续几分钟。不要动路由器,它会自动重启。

重启后看到路由器的灯亮起来,从一个亮变成两个亮,然后闪动。 连接路由器的电脑会开始提示网络已经断开,然后又提示已经连接到网络,这时候就可以重新登录到路由器了。

配置路由器

我的固件自带luci这个浏览器界面,所以直接重新用浏览器访问路由器管理界面即可。

默认的管理界面地址是192.168.1.1, 和TP-LINK的官方固件是不同的。输入地址,然后可以看到一个用Bootstrap制作的简陋的界面= =……

默认密码是没有的。用户名root,密码留空登录即可。

登录成功后,重要的是首先修改root的密码。根据需要,还可以为路由器添加ssh访问用的公钥。这里不再赘述。

界面顶部的菜单有Status(状态)、System(系统)、Network(网络)和Logout(退出登录)等几项。 在Network-Interfaces(网络接口)中,可以看到已经事先配置好的几个接口。LAN是对应局域网区域的接口,WAN是对应互联网的。

如果使用拨号的宽带上网,可以配置WAN接口为(例如)PPPoE模式,然后输入用户名和密码,保存设置,稍等一会,就可以上网了。

为路由器安装dnscrypt

OpenWRT值得折腾的地方很多,今天就以dnscrypt为例先熟悉一下折腾的过程。

dnscrypt是加密DNS查询的方法。

DNS是一种类似电话本的服务: 计算机在我们输入网址后访问网站前,首先需要将网址中的域名部分(比如www.google.com)(类似一个人的名字),翻译成网络中实际使用的IP地址(类似电话号码)。 为了完成这个翻译过程,计算机要向给定的几个DNS服务器(类似提供电话黄页的商店之类的地方)发出查询。 然而,这个查询的过程,会被人看到,查询到的结果,也会被人看到。这样,我们没有访问某个网站之前,就有人可以知道我们的意图。 不怀好意的人,也可以在我们拿到查询结果前,将结果修改,以便将我们引到错误的网站。

dnscrypt可以将这个查询过程加密,避免查询和查询的结果在路上被窃听和篡改。 然而,dnscrypt不能保证DNS服务器本身不给出错误的结果。这个过程需要DNSSEC机制来解决,这里先不讨论了。

dnscrypt在路由器上安装后,会实现一个DNS查询的代理。 路由器本身会在局域网中担任DNS服务器的责任,发往路由器的DNS查询,会被加密然后送往互联网上的指定DNS服务器处理,然后同样加密返回。 路由器拿到结果后,解密结果,然后返回给发起查询的计算机。这样,局域网内的各种计算机,就不需要什么特殊配置了。

ssh登录到路由器

在Linux下,可以直接使用命令ssh root@192.168.1.1登录到路由器。根据配置,可能要求输入root用户的密码,或者本地计算机上的ssh私钥密码。

dnscrypt安装和配置

登录成功后就具有了路由器的管理员权限了。可以使用OpenWRT的包管理器opkg(名字类似Debian的dpkg呢)来安装卸载软件包了。

为了安装dnscrypt,需要的软件包是dnscrypt-proxy,安装方法是执行如下命令:

# opkg install dnscrypt-proxy

安装后,配置dnscrypt。需要修改/etc/config/dnscrypt-proxy文件。我的文件内容是这样的:

config dnscrypt-proxy
        option address '127.0.0.1'
        option port '5353'
        option resolver 'opendns'
        option resolvers_list '/usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv'

这个文件很简单,作用就是在路由器本地(127.0.0.1)的端口5353上成为一个代理。 在互联网上使用的resolver(解析服务器),是在resolvers_list中列出的名为opendns的那个。

完成后,使用如下命令启用和启动dnscrypt-proxy服务:

# /etc/init.d/dnscrypt-proxy enable
# /etc/init.d/dnscrypt-proxy start

这样dnscrypt-proxy就启动了。

配置dnsmasq服务,使之使用dnscrypt

我们还需要让负责进行DNS查询的dnsmasq服务,使用dnscrypt-proxy作为DNS查询的代理。

打开/etc/config/dhcp文件,里面能看到关于dnsmasq的配置,类似这样:

config dnsmasq
        option domainneeded '1'
        option boguspriv '1'
        option filterwin2k '0'
        option localise_queries '1'
        option rebind_protection '1'
        option rebind_localhost '1'
        option local '/lan/'
        option domain 'lan'
        option expandhosts '1'
        option nonegcache '0'
        option authoritative '1'
        option readethers '1'
        option leasefile '/tmp/dhcp.leases'
        option resolvfile '/tmp/resolv.conf.auto'
        option localservice '1'

在这一节配置后(即option localservice '1'这一行后面),新添加下面两行

        option noresolv '1'
        list server '127.0.0.1#5353'

然后,将option resolvfile...这一行注释掉(如果有这一行的话),即在这一行最前面添加一个#号:

#       option resolvfile '/tmp/resolv.conf.auto'

文件最后就成了这样:

config dnsmasq
        option domainneeded '1'
        option boguspriv '1'
        option filterwin2k '0'
        option localise_queries '1'
        option rebind_protection '1'
        option rebind_localhost '1'
        option local '/lan/'
        option domain 'lan'
        option expandhosts '1'
        option nonegcache '0'
        option authoritative '1'
        option readethers '1'
        option leasefile '/tmp/dhcp.leases'
#	    option resolvfile '/tmp/resolv.conf.auto'
        option localservice '1'
        option noresolv '1'
        list server '127.0.0.1#5353'

就可以保存文件退出编辑了。然后,重启dnsmasq服务:

# /etc/init.d/dnsmasq restart

dnscrypt启动太早的故障

dnscrypt正常来说根据/etc/init.d/dnscrypt-proxy enable的命令就应该可以自动启动了, 然而我的路由器在重启之后,仍然无法提供DNS服务,电脑无法上网。

这个原因是dnsmasq在系统启动时启动太早,在别的服务没有初始化之前就自己退出了。

于是方法是让dnscrypt在稍后重新启动一遍(什么破解决方法):修改/etc/rc.local文件,在最后一行exit 0之前增加如下两行:

sleep 10
/etc/init.d/dnscrypt-proxy start

就是让dnscrypt-proxy在休息10秒之后自己启动。

收尾工作

现在,路由器运行的地址192.168.1.1已经可以作为一个不泄露秘密的DNS服务器工作了。

检查电脑的联网配置,确定用到的DNS服务器,要么设定为192.168.1.1,要么直接由DHCP分配。

如果觉得这样还不够安全,可以在路由器上配置防火墙,将所有目标端口53,发往互联网的TCP/UDP数据包都drop或者reject掉。

确认配置成功

为了检验dnscrypt到OpenDNS上已经成功,在Linux上使用如下命令:

$ dig txt debug.opendns.com

这一方法只是对使用OpenDNS服务作为dnscrypt的DNS提供者的情况(如本文)有效。

返回结果中应当有一部分类似下文(已经过修改):

;; ANSWER SECTION:
debug.opendns.com.	0	IN	TXT	"server 7.fra"
debug.opendns.com.	0	IN	TXT	"flags 20 0 70 ********************"
debug.opendns.com.	0	IN	TXT	"originid 0"
debug.opendns.com.	0	IN	TXT	"actype 0"
debug.opendns.com.	0	IN	TXT	"source ***.***.***.***:*****"
debug.opendns.com.	0	IN	TXT	"dnscrypt enabled (******************)"

如果看到了dnscrypt enabled,就说明成功。