折腾小米初代路由器R1D
2024年12月1日
随着装修逐步进入尾声,最近时不时就会开始想以后的Home Lab要怎么搭。眼光在家瞟来瞟去的,突然瞟到了已经十来年的小米路由器了。这是一台小米一代路由器(R1D),因为当时负责这款产品的老大还有一些同事都是以前腾讯的老同事,所以很早就注意到并且购买了这台造型独特、自带1T硬盘的路由器。
后来好多年我家一直使用这台路由器,也是这台路由器让我感觉到原来面积中小的房子只需要一台路由器就能稳定覆盖WiFi信号。同时它自带的硬盘还能存点文件,有时候还能远程下载点影视剧。
几年前IPv6开始普及了,当时这款路由器已经没有固件更新了,老固件没有对IPv6的支持。为了折腾IPv6,就换了一台路由器,这台小米一代路由器就被闲置了。
刷机修复错误
给路由器插上网线,通电之后,一开始是黄色灯常亮(开机中),后来变成了闪红灯。查了一下指示灯的显示:
- 黄灯常亮:启动中
- 蓝灯常亮:正常
- 红灯闪烁:系统故障
- 黄灯闪烁:升级/刷机安装系统中
那么看起来是系统坏了,进入了恢复模式。直接访问路由器的管理页面,也能看到很明显的提示,系统目前处于恢复模式。
网上的教程都说需要用U盘刷机,但此时管理页面是可以访问的,因此也可以直接从官网下载固件,然后在网页上选择刷入即可。因为本来就是想再折腾一下这台路由器,我直接选择了开发版固件。
几分钟后,路由器刷机完成自动重启,终于变成了蓝灯,此时路由器的功能已完全恢复正常,内置硬盘中的文件也可以浏览操作了。
打开SSH
接下来试着打开路由器的SSH,官网有说明,按说明从官网下载SSH的工具包,改名为miwifi_ssh.bin
,放入U盘(FAT文件系统)根目录插入路由器USB口,然后重启路由并用卡针顶住RESET口不放,直到黄灯闪烁,说明正在刷机。
这一次只需要几秒钟即可,随后路由器再次重启,SSH端口成功打开。
接下来兴高采烈地准备SSH连接上去ssh root@192.168.31.1
,结果碰到一个华丽丽的报错:
Unable to negotiate with 192.168.31.1 port 22: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1,diffie-hellman-group14-sha1
Unable to negotiate with 192.168.31.1 port 22: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1,diffie-hellman-group14-sha1
这个是什么意思呢?嗯……简单来说就是服务端和客户端的算法对不上,客户端是最新的macOS,而服务端是十年前的路由器系统(魔改OpenWRT),这十年间安全界也在不断淘汰旧算法,采纳新算法,于是一个跨越十年的“代沟”就这么产生了:服务端想用老算法,客户端说这玩意我不知道是啥。
解决方法也不难,就是让客户端兼容一下服务端,勉为其难用一用旧算法:
ssh -oKexAlgorithms=+diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 root@192.168.31.1
ssh -oKexAlgorithms=+diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 root@192.168.31.1
至此终于可以登录到路由器中了。不过关于SSH的坑还没有踩完,这里也一并记录一下。
一般来说登录到服务器后为了方便(也为了安全),会设置一下公钥登录。小米这款路由器的SSH服务端用的并不是OpenSSH,而是beardrop,因此需要将我们的公钥放在/etc/beardrop/authorized_keys
中,而不是常见的~/.ssh/authorized_keys
。
当我将公钥放上去之后,公钥登录却并没有生效,通过给ssh
命令添加-v
参数查看调试信息,可以看到另一个错误:
debug1: Offering public key: id_rsa_toobug RSA SHA256:cY3mrYxBSCKd9yDJYYSkvytZmKl6Btb+bMZG1SCrg/M agent
debug1: send_pubkey_test: no mutual signature algorithm
debug1: Offering public key: id_rsa_toobug RSA SHA256:cY3mrYxBSCKd9yDJYYSkvytZmKl6Btb+bMZG1SCrg/M agent
debug1: send_pubkey_test: no mutual signature algorithm
通过报错信息,结合一些资料,可以知道,这也是一个“代沟”:客户端和服务端的签名算法对不上。同样的方法,给客户端指定一下旧的算法(ssh-rsa
)即可。
我将相关参数直接写在了ssh的配置文件中:
Host mi-r1d
HostName 192.168.31.1
User root
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedAlgorithms +ssh-rsa
KexAlgorithms +diffie-hellman-group1-sha1,diffie-hellman-group14-sha1
Host mi-r1d
HostName 192.168.31.1
User root
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedAlgorithms +ssh-rsa
KexAlgorithms +diffie-hellman-group1-sha1,diffie-hellman-group14-sha1
以上关于SSH命令的调试、解决均有ChatGPT的协助。
OPKG源
解决了SSH的问题,本以为一切顺利了。正常来说就是用包管理软件了,先更新一下源,再安装想要的软件即可。
opkg update
opkg update
结果这里碰到了无数个问题,为了简单起见,直接用一个列表按时间顺序列出步骤、问题和解决方案:
- 软件源地址失效:
/etc/opkg.conf
文件中写的源地址已不存在http://downloads.openwrt.org/attitude_adjustment/12.09/brcm4709/R1D/packages
- 在上述网站中手工翻找,找到
https://downloads.openwrt.org/attitude_adjustment/12.09/brcm47xx/generic/packages
- 执行
opkg update
时报错wget: not an http or ftp url: https://downloads.openwrt.org/attitude_adjustment/12.09/brcm47xx/generic/packages/Packages.gz
,也就是说它调用了wget,但是wget不支持HTTPS - 尝试换用
http
协议,wget直接报错-1
,应该是网站不允许使用HTTP访问了 - 手工翻包列表,才发现原来wget还分wget-nossl和wget-ssl
- 手工下载
wget-ssl
的包,尝试通过SCP传到路由器上,报错(具体信息不记得了),同样也是SCP的传输方式已经变了,需要使用-O
强制使用旧版本的方式传输 wget-ssl
的包上传到路由器之后并不能安装,而且无论架构是brcm47xx
还是armv7
都一样报错:opkg install /tmp/wget_1.13.4-1_ar7.ipk Unknown package 'wget'. Collected errors: * pkg_hash_fetch_best_installation_candidate: Packages for wget found, but incompatible with the architectures configured * opkg_install_cmd: Cannot install package wget.
opkg install /tmp/wget_1.13.4-1_ar7.ipk Unknown package 'wget'. Collected errors: * pkg_hash_fetch_best_installation_candidate: Packages for wget found, but incompatible with the architectures configured * opkg_install_cmd: Cannot install package wget.
- 尝试使用下文的Entware的源,update可以成功,但所有软件都提示架构不兼容
- 执行
至此,折腾OPKG彻底失败,这台路由器到目前为止没有成功安装上任何软件。
安装Entware
在即将陷入僵局的时候,突然发现了有一个专为嵌入式设备服务的软件仓库:Entware(Github)。它的文档还是比较多的,但是组织并不友好,安装时可参与其在某一个平台的文档,例如在群晖上的安装文档。
其中最重要的是wget -O - https://bin.entware.net/armv7sf-k2.6/installer/generic.sh | /bin/sh
这句脚本。(注意其中armv7sf-k2.6
,其中2.6是内核,在路由器上通过uname -a
可看到内核版本是2.6)。很明显,我们的wget访问不了这个HTTPS地址,但我们还有两种方法可以处理:
- 下载这个安装脚本后再通过SCP传到路由器上
- 将命令中的
https
改成http
(是的,它支持使用HTTP协议访问!)
因为Entware安装的软件都会在/opt
目录中,我们需要按照提示,需要将/opt/bin
和/opt/sbin
放入$PATH
变量中,这样才可以直接执行它安装的软件。这里我选择在/etc/profile
中修改。
export PATH=/opt/bin:/opt/sbin:.....
export PATH=/opt/bin:/opt/sbin:.....
此外还有一条命令,建议放到开机命令中去,大致方法是在/etc/init.d
新建一个脚本,然后启用即可,这里我没有去做,可参考其他教程。
在安装完Entware后,就有了另一个opkg
命令,我们可以用它来安装软件了。你可以用which opkg
来确认,确保当前运行的是/opt
目录下的opkg
。
首先解决冤大头wget-ssl
,这样就可以访问HTTPS网站了,但实际上安装完之后依然不能访问HTTPS网站,会显示证书不信任。这同样是因为时间太久了,路由器内置的CA证书与目前公认受信任的CA证书列表已大不一样。此时还需要安装ca-certificates
,安装完后终于能正常访问HTTPS网站了。
后面我用Entware安装了nginx,使用完全正常使用。
软链
路由器的/opt
位于内置存储中,空间只有100多M,装几个软件就满了,因此我们需要给它们挪个位置,把软件都挪到1T的硬盘中去。
mkdir -p /userdisk/data/.system
mv /opt /userdisk/data/.system
ln -s /userdisk/data/.system/opt /opt
mkdir -p /userdisk/data/.system
mv /opt /userdisk/data/.system
ln -s /userdisk/data/.system/opt /opt
首先在硬盘中新建一个.system
目录(名字随意),然后将/opt
挪过去,最后将opt
目录软链回原来的路径/opt
。这样文件存储是在硬盘中,但访问路径没有任何变化,各个软件仍然可以正常工作。
设置防火墙
这个路由器现在是被当作Home Lab来使用,因此不承担路由的功能,它通过有线网连接到主路由下,对它来说有两个网络:
- LAN:即原来的
192.168.31.1
网段(实际上为了避免与主路由冲突,修改了网段,此处为示意仍然使用这个地址) - WAN:即主路由所在网段
如果电脑连接主路由,则只能访问到Home Lab的WAN接口,如果要访问LAN接口,则需要连接Home Lab的WiFi或者插入网线才可以。这两者主要区别是:管理界面和文件共享等功能都只允许从LAN访问,也就是说如果连接主路由,那Home Lab的管理界面和文件共享都访问不到。
此时我们需要修改它的防火墙设置,让它允许接受来自WAN的访问。修改/etc/config/firewall
,找到wan
,将其中的input
从REJECT
修改为ACCEPT
,然后重启/etc/init.d/firewall restart
即可。
其他和小结
虽然到目前为止,似乎解决了软件安装的问题和最常用的网络访问问题,但实际上在后续折腾的过程中还是碰到了更多问题。我尝试安装TailScale,安装成功了,但执行tailscale up
时,报了Illegal instruction (core dumped)
的错误。后续使用Node.js时也出现了同样现象,但神奇的是node -v
可以正常执行。
按照ChatGPT的说法,出现这种现象可能是程序使用了CPU不支持的指令,可以尝试使用gdb
调试。我也试了一下生成Coredump文件,但实际上这已经远远超出了我的知识范围,只能暂时放弃了。
至此,这个路由器的折腾告一段落,目前路由器功能正常,硬盘功能正常,有需要的话还可以开启nginx访问,只能说聊胜于无,先当个小垃圾用着吧。