Build Own Router Firmware

最近为了绕过校园网的多设备HTTP-UA检测,记录一下折腾路由器过程。

Newifi D2

一开始使用的是秦朝元老新路由3,CPU是MIPS架构的MT7621AT,双核880MHz,内存512MB,闪存32MB。这台路由器是2019年差不多100块购入的,在当年除了闪存小了一点外,其他都是非常完美的配置,性价比超高。直到2025年了也能翻出来继续发光发热。

这台路由一直以来运行的是老毛子固件,自定义自由度不如OpenWRT,经过一番搜索,决定使用immortalwrt-24.10。

下载完固件后,按下reset,插电开机,进入breed,刷入固件,一气呵成。

PS:在Breed刷入编程器固件时,请务必勾上保留bootloader,因为breed就是保障不让bootloader被覆盖导致变砖。(血的教训)
因为我以为Breed中备份编程器固件是将flash中的每一个字节备份,于是某一次将备份刷回去的时候,我去掉了保留bootloader和保留eeprom的选项,然后就成砖了😇

校园网检测多设备原理是通过检测明文的HTTP头UA来判断的,于是可以在路由器装上UA3F来将所有UA修改为统一的值,然后就能绕过检测。

换源后,安装依赖,安装插件

opkg update
opkg install kmod-nft-queue kmod-nft-tproxy
opkg install /tmp/ua3f.ipk

安装完成后,系统存储大约还剩余7MB,内存占用率小于50%,不安装其他插件也差不多够用了。接上网线测速能跑满校园网100Mbps,但尝试下载一个数GB的文件发现速度在6MB/s ~ 10MB/s波动,打开管理后台一看,CPU占用100%,且负载高达5+。果然双核880M mips的7621在这个任务下还是太弱了,但好在刷视频,刷各种App网页,FPS游戏都非常流畅,只有在持续GB级的文件下载才会影响到其他用户,就这样姑且用着吧。

用了一段时间后,5Ghz WiFi开始莫名奇妙消失,没有什么规律,突然信号消失,接上有线网登入后台发现下面一段日志:

[ 1613.148785] WARNING: CPU: 2 PID: 1704 at lib/list_debug.c:62 __list_del_entry_valid_or_report+0x12c/0x16c
[ 1613.163054] list_del corruption. prev->next should be 81d03a30, but was 849bfe88. (prev=849bfe88)
[ 1613.443953] [<849d4d60>] mt76_wcid_cleanup+0x1f4/0x1fc [mt76]
[ 1613.449860] [<849d4e78>] __mt76_sta_remove+0x8c/0xec [mt76]
[ 1613.455564] [<849d50d4>] mt76_sta_state+0x1fc/0x488 [mt76]
......
[88753.547837] mt76x2e 0000:01:00.0: Firmware Version: 0.0.00
[88753.586566] mt76x2e 0000:01:00.0: Firmware running!
[88753.595305] ieee80211 phy1: Hardware restart was requested

LLM说,这是驱动崩溃导致的,起初我以为是硬件损坏导致驱动崩溃,毕竟这个路由器使用了这么多年了,之前也有听说过新三路由在挖矿时原厂固件BUG导致烧5G。为了验证这个问题,我刷回了老毛子固件,用了几天除了经常被校园网检测共享封禁外,5G WiFi毫无问题。看来OpenWRT固件确实是不太稳定。

就在这时,我刷到一个UP主分享到,他的CR8808的OpenWRT固件比原厂固件还要稳定,巧了吗不是,我刚好就有一个CR8808!然后曲折的折腾之路就开始了~

CR8808

CR8808是红米AX3000的移动运营商定制版,大概是50块在海鲜市场购入。CPU是高通IPQ5000,Aarch64架构,双核A53 1Ghz,内存256MB,闪存128MB。

参考的教程是恩山的一篇帖子。大概的思路是用这个Exploit打开路由器SSH,然后刷写新的Uboot,利用Uboot更新系统。

这里有个坑是APPSBL_1分区和APPSBL1.bin需要对应,我的分区就和帖子里的不一样

root@XiaoQiang:~# cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00080000 00020000 "0:SBL1"
mtd1: 00080000 00020000 "0:MIBIB"
mtd2: 00040000 00020000 "0:BOOTCONFIG"
mtd3: 00040000 00020000 "0:BOOTCONFIG1"
mtd4: 00100000 00020000 "0:QSEE"
mtd5: 00100000 00020000 "0:QSEE_1"
mtd6: 00040000 00020000 "0:DEVCFG"
mtd7: 00040000 00020000 "0:DEVCFG_1"
mtd8: 00040000 00020000 "0:CDT"
mtd9: 00040000 00020000 "0:CDT_1"
mtd10: 00080000 00020000 "0:APPSBLENV"
mtd11: 00140000 00020000 "0:APPSBL_1"
mtd12: 00140000 00020000 "0:APPSBL"
mtd13: 00100000 00020000 "0:ART"
mtd14: 00080000 00020000 "0:TRAINING"
mtd15: 00080000 00020000 "bdata"
mtd16: 00080000 00020000 "crash"
mtd17: 00080000 00020000 "crash_log"
mtd18: 02400000 00020000 "rootfs"
mtd19: 02400000 00020000 "rootfs_1"
mtd20: 01f00000 00020000 "overlay"
mtd21: 00d80000 00020000 "data"
mtd22: 00364000 0001f000 "kernel"
mtd23: 0158e000 0001f000 "ubi_rootfs"
mtd24: 01b20000 0001f000 "rootfs_data"
mtd25: 00a2c000 0001f000 "data_ignor_reset"

因此我这里需要执行的是

mtd write /tmp/MIBIB.bin /dev/mtd1
reboot
mtd write /tmp/APPSBL.bin /dev/mtd12
mtd write /tmp/APPSBL1.bin /dev/mtd11

然后按住reset键插上电源即可进入Uboot。这里我又因为reset按键接触不良导致进不去Uboot,开始还以为被我刷成砖了😭但好在最后还是进去了🫠

上传后缀为squashfs-nand-factory.ubi的固件即可。

最开始,我安装的是Kmiit的immortalWRT 24 snap-shot版本,在换源的时候配置发现第一行immortalwrt_core源是仓库作者自定义的地址,但是访问这个地址已经404了,于是我就在各个镜像源里找啊找,发现都没有适配ipq50xx或者是redmi ax3000设备,但是除了第一个源,后面的源都是可以成功update,那就试试能不能装吧🧐

/etc/opkg/distfeeds.conf

src/gz immortalwrt_core https://kmiit.github.io/Redmi_AX3000_immortalwrt/redmi_ax3000-24.10/ci-20250228-140825-e0b8eff3
src/gz immortalwrt_base https://mirrors.vsean.net/openwrt/releases/24.10-SNAPSHOT/packages/aarch64_cortex-a53/base
src/gz immortalwrt_luci https://mirrors.vsean.net/openwrt/releases/24.10-SNAPSHOT/packages/aarch64_cortex-a53/luci
src/gz immortalwrt_packages https://mirrors.vsean.net/openwrt/releases/24.10-SNAPSHOT/packages/aarch64_cortex-a53/packages
src/gz immortalwrt_routing https://mirrors.vsean.net/openwrt/releases/24.10-SNAPSHOT/packages/aarch64_cortex-a53/routing
src/gz immortalwrt_telephony https://mirrors.vsean.net/openwrt/releases/24.10-SNAPSHOT/packages/aarch64_cortex-a53/telephony

果然不能😵

开始以为是snap-shot版本的原因,然后经过一番搜索才知道,ua3f因为涉及到改包操作,依赖kmod-nft-queue kmod-nft-tproxy两个带kmod名内核模块包,内核模块包是在immortalwrt_core源中的,这个包依赖于编译的具体系统版本以及目标平台(target),由于ipq50xx已经没有了官方支持的编译,所以只能自己编译得到内核包😳。PS: 后来编译完了看到产物才知道,kmiit已经把他编译好的内核包放在release里了🙃

然后就装依赖,等待编译,刷入固件!

将编译产物中的target/ipq50xx/package使用Python开的http服务给路由器更新完源后,终于是顺利装上ua3f了😭

虽然顺利运行起来了,但是还是存在一些问题:测速的时候发现CPU占用非常高,并且也会在6MB/s~10MB/s反复波动,但这还算能接受。不能接受的是路由器开启ua3f后剩余内存特别少,导致高并发下载的时候,系统会因为OOM将ua3f和无线驱动都kill,表现就是下载了几十秒后WiFi突然消失了。

ChatGPT说,是因为这个版本的系统使用的是ath11开源驱动,内存占用量大,换成QSDK带有NSS加速的系统就没这个问题了,于是又尝试刷新系统了。

在Github上相对较新,带NSS加速的只有这个OpenWRT21系统了。一开始装上release中编译好的版本后,两个kmod包也顺利装上了,但是运行ua3f就报错

Error relocating /usr/bin/ua3f: __nanosleep_time64: symbol not found

ChatGPT说是libc版本不兼容导致的,建议我在编译固件的时候就将ua3f编译,这样就不容易有兼容性问题。

下面就将我的编译过程以及排过的坑记录一下叭~😇

我编译的分支是”ipq50xx-qsdk-kernel-5.4-openwrt-21.02-qsdk-11.5.05.841.1029“,5.4内核分支刚好有一个release,下载release中的”dl.tar”,解压后放在源码目录的dl目录中。

然后更新一下golang的版本

./scripts/feeds update -a
rm -rf feeds/packages/lang/golang
git clone https://github.com/sbwml/packages_lang_golang -b 24.x feeds/packages/lang/golang
./scripts/feeds install -a

然后添加UA3F源码到package目录中

git clone https://github.com/SunBK201/UA3F.git package/UA3F

配置编译选项,勾选Network → Web Servers/Proxies → ua3f,看看kernel里netfilter的tproxy和queue有没有配置成[*] (内置到固件)。目标平台选择32位的arm,因为aarch64系统装上后剩余内存特别少。

make menuconfig
make -j16 download
make -j$(nproc)

然后刷上固件测速!

持续下载了1.4GB,剩余内存依然保持在20%以上,且负载低于1!以前刷过的immortalWRT在这种工况下,剩余内存已经低于10%了,且负载也接近2。呼!总算是折腾完了,礼花庆祝🎉🎉🎉

总结

这次路由器折腾经过了刷机->变砖->买编程器救砖->编译固件->编译插件进固件。这么一套下来感觉已经变成了恩山里的大神(不是)了🤣现在给我的感觉是已经不再惧怕编译固件了(虽然本来就很简单),然后在网络编程中,我发现拆包改包要涉及到这么多内核态的操作,感觉到对系统和网络还是几乎一无所知,但进一步有一步的欣喜嘛~希望我在计算机宇宙中持续进步探索吧,就酱😌

上一篇