bGZo 's blog

READMI AX6000 刷机

当初买这个路由的原因就是想刷机,不能刷机的路由器压根不想买,刚刚看了下,已经一年多了,早过了质保,所以刷机势在必然。

当前版本:MiWiFi 稳定版 1.0.67

前置扫盲

开启开发/调试模式

http://192.168.31.1/cgi-bin/luci/;stok=cddaa7adbc9ed560ec63cef8989975eb/api/misystem/set_sys_time?timezone=%20%27%20%3B%20zz%3D%24%28dd%20if%3D%2Fdev%2Fzero%20bs%3D1%20count%3D2%202%3E%2Fdev%2Fnull%29%20%3B%20printf%20%27%A5%5A%25c%25c%27%20%24zz%20%24zz%20%7C%20mtd%20write%20-%20crash%20%3B%20

重启

http://192.168.31.1/cgi-bin/luci/;stok=cddaa7adbc9ed560ec63cef8989975eb/api/misystem/set_sys_time?timezone= ' ; reboot ;

设置 Bdata 永久开启 telnet

http://192.168.31.1/cgi-bin/luci/;stok=75b99c4379fcdc2994f42cfddbce9cc2/api/misystem/set_sys_time?timezone=%20%27%20%3B%20bdata%20set%20telnet_en%3D1%20%3B%20bdata%20set%20ssh_en%3D1%20%3B%20bdata%20set%20uart_en%3D1%20%3B%20bdata%20commit%20%3B%20

重启

http://192.168.31.1/cgi-bin/luci/;stok=75b99c4379fcdc2994f42cfddbce9cc2/api/misystem/set_sys_time?timezone=%20%27%20%3b%20reboot%20%3b%20

开启 SSH

telnet 连上去,才发现 Are U Ok 的彩蛋,哈哈

~/workspaces/proxies > telnet 192.168.31.1 23
Trying 192.168.31.1...
Connected to xiaoqiang.
Escape character is '^]'.
BusyBox v1.25.1 (2023-01-30 10:31:26 UTC) built-in shell (ash)

 -----------------------------------------------------
       Welcome to XiaoQiang!
 -----------------------------------------------------
  $$$$$$\  $$$$$$$\  $$$$$$$$\      $$\      $$\        $$$$$$\  $$\   $$\
 $$  __$$\ $$  __$$\ $$  _____|     $$ |     $$ |      $$  __$$\ $$ | $$  |
 $$ /  $$ |$$ |  $$ |$$ |           $$ |     $$ |      $$ /  $$ |$$ |$$  /
 $$$$$$$$ |$$$$$$$  |$$$$$\         $$ |     $$ |      $$ |  $$ |$$$$$  /
 $$  __$$ |$$  __$$< $$  __|        $$ |     $$ |      $$ |  $$ |$$  $$<
 $$ |  $$ |$$ |  $$ |$$ |           $$ |     $$ |      $$ |  $$ |$$ |\$$\
 $$ |  $$ |$$ |  $$ |$$$$$$$$\       $$$$$$$$$  |       $$$$$$  |$$ | \$$\
 \__|  \__|\__|  \__|\________|      \_________/        \______/ \__|  \__|

echo -e 'admin\nadmin' | passwd root
Changing password for root
New password:
Bad password: too short
Retype password:
passwd: password for root changed by root
nvram set ssh_en=1
nvram set telnet_en=1
nvram set uart_en=1
nvram set boot_wait=on
nvram commit

永久化 SSH 需要配置创建如下目录

mkdir /data/auto_ssh && cd /data/auto_ssh
vim auto_ssh.sh

并贴上如下脚本

#!/bin/sh
auto_ssh_dir="/data/auto_ssh"
host_key="/etc/dropbear/dropbear_rsa_host_key"
host_key_bk="${auto_ssh_dir}/dropbear_rsa_host_key"

unlock() {
    # Restore the host key.
    [ -f $host_key_bk ] && ln -sf $host_key_bk $host_key

    # Enable telnet, ssh, uart and boot_wait.
    [ "$(nvram get telnet_en)" = 0 ] && nvram set telnet_en=1 && nvram commit
    [ "$(nvram get ssh_en)" = 0 ] && nvram set ssh_en=1 && nvram commit
    [ "$(nvram get uart_en)" = 0 ] && nvram set uart_en=1 && nvram commit
    [ "$(nvram get boot_wait)" = "off" ]  && nvram set boot_wait=on && nvram commit

    [ "`uci -c /usr/share/xiaoqiang get xiaoqiang_version.version.CHANNEL`" != 'stable' ] && {
        uci -c /usr/share/xiaoqiang set xiaoqiang_version.version.CHANNEL='stable'
        uci -c /usr/share/xiaoqiang commit xiaoqiang_version.version 2>/dev/null
    }

    channel=`/sbin/uci get /usr/share/xiaoqiang/xiaoqiang_version.version.CHANNEL`
    if [ "$channel" = "release" ]; then
        sed -i 's/channel=.*/channel="debug"/g' /etc/init.d/dropbear
    fi

    if [ -z "$(pidof dropbear)" -o -z "$(netstat -ntul | grep :22)" ]; then
        /etc/init.d/dropbear restart 2>/dev/null
        /etc/init.d/dropbear enable
    fi
}

install() {
    # unlock SSH.
    unlock

    # host key is empty, restart dropbear to generate the host key.
    [ -s $host_key ] || /etc/init.d/dropbear restart 2>/dev/null

    # Backup the host key.
    if [ ! -s $host_key_bk ]; then
        i=0
        while [ $i -le 30 ]
        do
            if [ -s $host_key ]; then
                cp -f $host_key $host_key_bk 2>/dev/null
                break
            fi
            let i++
            sleep 1s
        done
    fi

    # Add script to system autostart
    uci set firewall.auto_ssh=include
    uci set firewall.auto_ssh.type='script'
    uci set firewall.auto_ssh.path="${auto_ssh_dir}/auto_ssh.sh"
    uci set firewall.auto_ssh.enabled='1'
    uci commit firewall
    echo -e "\033[32m SSH unlock complete. \033[0m"
}

uninstall() {
    # Remove scripts from system autostart
    uci delete firewall.auto_ssh
    uci commit firewall
    echo -e "\033[33m SSH unlock has been removed. \033[0m"
}

main() {
    [ -z "$1" ] && unlock && return
    case "$1" in
    install)
        install
        ;;
    uninstall)
        uninstall
        ;;
    *)
        echo -e "\033[31m Unknown parameter: $1 \033[0m"
        return 1
        ;;
    esac
}

main "$@"
uci set firewall.auto_ssh=include
uci set firewall.auto_ssh.type='script'
uci set firewall.auto_ssh.path='/data/auto_ssh/auto_ssh.sh'
uci set firewall.auto_ssh.enabled='1'
uci commit firewall

cd
uci set system.@system[0].timezone='CST-8'
uci set system.@system[0].webtimezone='CST-8'
uci set system.@system[0].timezoneindex='2.84'
uci commit

mtd erase crash

reboot

之后就可以用 SSH 连接路由器了,但是会报错:

~> ssh -p 22 root@192.168.31.1
Unable to negotiate with 192.168.31.1 port 22: no matching host key type found. Their offer: ssh-rsa

因为路由器 只支持 RSA-SHA1 host key。然后 SSH 觉得这个算法太旧了,不接受,SSH 有两种 RSA:ssh-rsa (SHA1) 和 rsa-sha2-256/rsa-sha2-512,所以需要调整一下命令:

ssh -o HostKeyAlgorithms=+ssh-rsa root@192.168.31.1

测试没问题,长期的方法是修改自己本地的 SSH 配置 ~/.ssh/config,加入:

Host 192.168.31.1
    HostKeyAlgorithms +ssh-rsa
    PubkeyAcceptedAlgorithms +ssh-rsa

官方固件上刷 Clash?

最终决定不刷,因为害怕官方搞鬼,例如:

刷写 OpenWrt

查看当前分区:

root@XiaoQiang:~# ubinfo -a
UBI version:                    1
Count of UBI devices:           2
UBI control device major/minor: 10:62
Present UBI devices:            ubi0, ubi1

ubi0
Volumes count:                           2
Logical eraseblock size:                 126976 bytes, 124.0 KiB
Total amount of logical eraseblocks:     240 (30474240 bytes, 29.0 MiB)
Amount of available logical eraseblocks: 64 (8126464 bytes, 7.7 MiB)
Maximum count of volumes                 128
Count of bad physical eraseblocks:       0
Count of reserved physical eraseblocks:  19
Current maximum erase counter value:     1
Minimum input/output unit size:          2048 bytes
Character device major/minor:            249:0
Present volumes:                         0, 1

Volume ID:   0 (on ubi0)
Type:        dynamic
Alignment:   1
Size:        26 LEBs (3301376 bytes, 3.1 MiB)
State:       OK
Name:        kernel
Character device major/minor: 249:1
-----------------------------------
Volume ID:   1 (on ubi0)
Type:        dynamic
Alignment:   1
Size:        127 LEBs (16125952 bytes, 15.3 MiB)
State:       OK
Name:        rootfs
Character device major/minor: 249:2

===================================

ubi1
Volumes count:                           1
Logical eraseblock size:                 126976 bytes, 124.0 KiB
Total amount of logical eraseblocks:     400 (50790400 bytes, 48.4 MiB)
Amount of available logical eraseblocks: 0 (0 bytes)
Maximum count of volumes                 128
Count of bad physical eraseblocks:       0
Count of reserved physical eraseblocks:  19
Current maximum erase counter value:     628
Minimum input/output unit size:          2048 bytes
Character device major/minor:            247:0
Present volumes:                         0

Volume ID:   0 (on ubi1)
Type:        dynamic
Alignment:   1
Size:        377 LEBs (47869952 bytes, 45.6 MiB)
State:       OK
Name:        data
Character device major/minor: 247:1
> cat /proc/mtd
dev:    size   erasesize  name
mtd0: 08000000 00020000 "spi0.1"
mtd1: 00100000 00020000 "BL2"
mtd2: 00040000 00020000 "Nvram"
mtd3: 00040000 00020000 "Bdata"
mtd4: 00200000 00020000 "Factory"
mtd5: 00200000 00020000 "FIP"
mtd6: 00040000 00020000 "crash"
mtd7: 00040000 00020000 "crash_log"
mtd8: 01e00000 00020000 "ubi"
mtd9: 01e00000 00020000 "ubi1"
mtd10: 03200000 00020000 "overlay"

> cat /proc/partitions
major minor  #blocks  name

  31        0     131072 mtdblock0
  31        1       1024 mtdblock1
  31        2        256 mtdblock2
  31        3        256 mtdblock3
  31        4       2048 mtdblock4
  31        5       2048 mtdblock5
  31        6        256 mtdblock6
  31        7        256 mtdblock7
  31        8      30720 mtdblock8
  31        9      30720 mtdblock9
  31       10      51200 mtdblock10
 253        0      15748 ubiblock0_1

备份

dd if=/dev/mtd1 of=/tmp/mtd1_BL2.bin
dd if=/dev/mtd2 of=/tmp/mtd2_Nvram.bin
dd if=/dev/mtd3 of=/tmp/mtd3_Bdata.bin
dd if=/dev/mtd4 of=/tmp/mtd4_Factory.bin
dd if=/dev/mtd5 of=/tmp/mtd5_FIP.bin

本机 clone 一份:

scp -O root@192.168.31.1:/tmp/mtd\*.bin .

然后擦除 FIP,重新写一遍,分区 bin 可以在这里找到 http://github.com/hanwckf/bl-mt798x/releases

mtd erase FIP
mtd write mt7986_redmi_ax6000-fip-fixed-parts-multi-layout.bin FIP
mtd verify mt7986_redmi_ax6000-fip-fixed-parts-multi-layout.bin FIP

接着拔掉电源,按住 Reset(注意不是 Mesh),需要用卡针,然后按 15s 以上,连接 LAN 口,打开路由器页面 192.168.31.1 即可打开 Uboot 页面进行刷机。mtd layout 选择 immortalwrt-*,然后把准备好的固件,上传给 Uboot,然后等待完成即可。

immortalwrt 默认账户、密码是 root/password,进去改名即可。

OpenClash

最终目的当然是这个,直接在路由器上跑 Clash。但为什么不选 Sing-box,因为自己用的机场没有提供这个格式的订阅,并且我用的机场订阅是阅后即焚,折腾起来比较麻烦。

首先需要下载内核,因为路由器下载就算用加速站点一样非常慢,所以直接下载 https://github.com/MetaCubeX/mihomo/releases 最新内核 (mihomo-linux-arm64-v1.19.21),解压上传至 /etc/openclash/core/clash 并重命名为 clash_meta。因为下载的是最新内核,所以启用 OpenClash 依然有问题,正常启动会报内核错误:

2026-03-14 00:00:36 level=fatal msg="Parse config error: path is not subpath of home directory or SAFE_PATHS: /usr/share/openclash/ui \n allowed paths: [/etc/openclash]"
2026-03-14 00:00:36 level=info msg="Start initial config

Dashboard 的路径不在 /usr/share/openclash/ui 内核所在的路径 etc/openclash,内核认为不安全,所以拒绝运行,目前没有特别好的办法,因为无法关闭 Dashboard,并且显式声明的配置会被覆盖,只能进入如下操作:

ln -s /usr/share/openclash/ui/ /etc/openclash/

在覆写设置 - 开发者选项中加入 1

ruby_edit "$CONFIG_FILE" "['external-ui']" "\"/etc/openclash/ui\""

另一个修改建议是: https://github.com/vernesong/OpenClash/pull/4478/changes, 不过我没有尝试。接下来就可以正常的上网冲浪了,并且保留了原来的网段、WI-FI 以及 IP。

Cheat Sheet

References

  1. https://github.com/vernesong/OpenClash/issues/4461 ↩