From 3b2f3daec07da07e04eda48f63573cc0c57fb6f0 Mon Sep 17 00:00:00 2001 From: mikeeq Date: Tue, 22 Feb 2022 12:54:47 +0100 Subject: [PATCH] Add OpenWRT install tutorial --- .github/workflows/build.yml | 23 +++++ .gitignore | 1 + README.MD | 169 ++++++++++++++++++++++++++++++++++++ build.sh | 24 +++++ password.py | 37 ++++++++ script.sh | 27 ++++++ 6 files changed, 281 insertions(+) create mode 100644 .github/workflows/build.yml create mode 100644 .gitignore create mode 100644 README.MD create mode 100755 build.sh create mode 100644 password.py create mode 100755 script.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..dc994e8 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,23 @@ +--- +name: Build OpenWRT + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: "Build OpenWRT" + run: ./build.sh + - name: Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + tag_name: ${{ github.ref }} + name: Release ${{ github.ref }} + draft: true + files: | + ./xiaomi_openwrt/* + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # You don't need to add this in secrets it's by default. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af048c5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +xiaomi_openwrt diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..d494f3d --- /dev/null +++ b/README.MD @@ -0,0 +1,169 @@ +# Xiaomi Router AX6S / AX3200 OpenWRT + +## Overview + +I'm planning to add pipeline for building OpenWRT images, as for now you'll only find here a tutorial for installing already built images. + +## Tested HW + +| Device | System version | Model | Production Date | Market | +| -------------------- | --------------------- | ----- | --------------- | ------ | +| Xiaomi Router AX3200 | MiWiFi Release 1.0.71 | RB01 | 09/2021 | EU | + +> Xiaomi AX3200 RB01 EU revision should have Telnet enabled from factory + +```bash +# Stock RB01 telnet output +❯ telnet 192.168.31.1 +Trying 192.168.31.1... +Connected to 192.168.31.1. +Escape character is '^]'. + +XiaoQiang login: root +Password: +``` + +### Tutorial: How to install OpenWRT + +0. I recommend restoring router settings to factory defaults, before installing OpenWRT + +1. Finish initial setup by going to + +2. Check if telnet is enabled on your device + + ```bash + # Create temporary directory + mkdir -p xiaomi_openwrt + cd xiaomi_openwrt + + # Pull scripts for generating telnet password + curl -Ls -o ./script.sh + curl -Ls -o ./password.py + + # Replace with the session token grabbed from the login URL after initial setup + ## http://192.168.31.1/cgi-bin/luci/;stok=1675d313f8c5d384e191b653c44c5e3a/web/home#router + ### i.e.: STOK="1675d313f8c5d384e191b653c44c5e3a" bash script.sh + STOK="" bash script.sh + + # look for telnet_en=1 or "telnet":true + ``` + + > If `telnet_en=0` or `"telnet": false`, then telnet is not enabled on your device you need to wait for the [exploit](https://forum.openwrt.org/t/adding-openwrt-support-for-xiaomi-redmi-router-ax6s-xiaomi-router-ax3200/111085/74?u=mikeeq) or use [CH341A programmer](https://forum.openwrt.org/t/adding-openwrt-support-for-xiaomi-redmi-router-ax6s-xiaomi-router-ax3200/111085/151?u=mikeeq) + +3. Start SSHd on router using telnet + + ```bash + # Create telnet terminal session, use TELNET_PASSWORD from script output from previous point + telnet 192.168.31.1 + + # Enable SSH + nvram set ssh_en=1 + nvram set uart_en=1 + nvram set boot_wait=on + nvram commit + sed -i '/flg_ssh.*release/ { :a; N; /fi/! ba };/return 0/d' /etc/init.d/dropbear + + # Set password for root user, `echo -e “/n” | passwd root` didn't work for me + passwd root + + # Start SSHd (dropbear) + /etc/init.d/dropbear enable + /etc/init.d/dropbear start + + # Test SSH connection, for authentication use password set earlier + ssh root@192.168.31.1 + # cat /proc/mtd + ``` + +4. SCP (copy over SSH) `factory.bin` and `rootfs.ubi` and + + ```bash + # Create temporary directory + mkdir -p xiaomi_openwrt_images + cd xiaomi_openwrt_images + + # Download images from Internet + curl -Ls -o factory.bin + curl -Ls -o rootfs.ubi + + # Copy images over SSH to router + cd ../ + scp -r xiaomi_openwrt_images root@192.168.31.1:/tmp/ + ``` + +5. Validate sha256 checksums and flash OpenWRT + + ```bash + # Open SSH terminal session + ssh root@192.168.31.1 + cd /tmp/xiaomi_openwrt_images + + # Validate those checksums against checksums found in github releases file sha256 + sha256sum *.bin + + # Set NVRAM flags + nvram set flag_boot_success=1 + nvram set flag_try_sys1_failed=0 + nvram set flag_try_sys2_failed=0 + + # Flash images + mtd write factory.bin firmware + mtd write factory.bin firmware1 + mtd write -r rootfs.ubi overlay + ``` + +6. After running last command `mtd write -r` router should automatically reboot and after it gets up you can open in the browser and try to login (default password is blank/empty) and set root password here: + + > If something go wrong make sure that you've tried to restart your NIC to grab fresh IP from DHCP + +7. If you're sure that you've bricked your device there'a recovery TFTP mode: + - You must set the ip address 192.168.31.100 on your pc, and you can use Xiaomi Recovery Tool. +If you use other tftp software, you need rename the firmware by C0A81F02.img and setup dhcp server with 192.168.31.0/24. ([SOURCE](https://forum.openwrt.org/t/adding-openwrt-support-for-xiaomi-redmi-router-ax6s-xiaomi-router-ax3200/111085/164?u=mikeeq>)) + - + + +### SSH Output from OpenWRT after successful flash + +```bash +❯ ssh root@192.168.1.1 +root@192.168.1.1's password: + + +BusyBox v1.35.0 (2022-02-14 13:40:34 UTC) built-in shell (ash) + + _______ ________ __ + | | .-----.-----.-----. | | | | .----. | | _ | + | --- || _ | -__| || | | || _|| _| + |_______|| __|_____|__|__||________||__| |____| + |__| W I R E L E S S F R E E D O M + ----------------------------------------------------- + OpenWrt SNAPSHOT, r18806-2120cad38d + ----------------------------------------------------- +root@OpenWrt:~# df -h +Filesystem Size Used Available Use% Mounted on +/dev/root 14.5M 14.5M 0 100% /rom +tmpfs 113.7M 944.0K 112.8M 1% /tmp +/dev/ubi0_1 31.6M 56.0K 29.9M 0% /overlay +overlayfs:/overlay 31.6M 56.0K 29.9M 0% / +tmpfs 512.0K 0 512.0K 0% /dev + +root@OpenWrt:/# dmesg | grep -i xia +[ 0.000000] Machine model: Xiaomi Redmi Router AX6S +``` + +## Docs + +- +- +- +- +- +- +- +- +- + +## Credits + +- [@namidairo](https://github.com/namidairo) for adding support for AX3200/AX6S in OpenWRT +- [@thorsten97](https://forum.openwrt.org/u/thorsten97/summary) for building images diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..5733e0a --- /dev/null +++ b/build.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +RUN_PATH=$PWD +SCRIPT_PATH=${SCRIPT_PATH:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)} + +echo "===]> Info: RUN_PATH=$RUN_PATH" +echo "===]> Info: SCRIPT_PATH=$SCRIPT_PATH" + +TMP_PATH=$SCRIPT_PATH/xiaomi_openwrt +IMAGE_URL="https://www.dropbox.com/s/cbuwbt0b4zztfp2/AX6S-big.zip" + + +echo "===]> Info: TMP_PATH=$TMP_PATH" +echo "===]> Info: IMAGE_URL=$IMAGE_URL" + +mkdir -p $TMP_PATH + +echo "===]> Info: Downloading images..." +curl -Ls $IMAGE_URL -o $TMP_PATH/images.zip + +cd $TMP_PATH + +unzip images.zip +sha256sum ./* > ./sha256 diff --git a/password.py b/password.py new file mode 100644 index 0000000..7db74fd --- /dev/null +++ b/password.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +import sys +import hashlib + +if sys.version_info < (3,7): + print("python version is not supported", file=sys.stderr) + sys.exit(1) + +# Credits to namidairo: https://forum.openwrt.org/t/adding-openwrt-support-for-xiaomi-redmi-router-ax6s-xiaomi-router-ax3200/111085/18 + +# credit goes to zhoujiazhao: +# https://blog.csdn.net/zhoujiazhao/article/details/102578244 + +salt = {'r1d': 'A2E371B0-B34B-48A5-8C40-A7133F3B5D88', + 'others': 'd44fb0960aa0-a5e6-4a30-250f-6d2df50a'} + + +def get_salt(sn): + if "/" not in sn: + return salt["r1d"] + + return "-".join(reversed(salt["others"].split("-"))) + + +def calc_passwd(sn): + passwd = sn + get_salt(sn) + m = hashlib.md5(passwd.encode()) + return m.hexdigest()[:8] + + +if __name__ == "__main__": + if len(sys.argv) != 2: + print(f"Usage: {sys.argv[0]} ") + sys.exit(1) + + serial = sys.argv[1] + print(calc_passwd(serial)) diff --git a/script.sh b/script.sh new file mode 100755 index 0000000..3560b22 --- /dev/null +++ b/script.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +RUN_PATH=$PWD +SCRIPT_PATH=${SCRIPT_PATH:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)} + +echo "===]> Info: RUN_PATH=$RUN_PATH" +echo "===]> Info: SCRIPT_PATH=$SCRIPT_PATH" + +[ -x "$(command -v jq)" ] || echo "===]> Exit: Install jq!" + +STOK="${STOK:-}" +ROUTER_IP="${ROUTER_IP:-192.168.31.1}" + +echo "===]> Info: STOK=$STOK" +echo "===]> Info: ROUTER_IP=$ROUTER_IP" + +echo "===]> Info: Printing device information..." + +curl -sLk http://$ROUTER_IP/cgi-bin/luci/api/xqsystem/fac_info | jq +curl -sLk http://$ROUTER_IP/cgi-bin/luci/api/xqsystem/bdata | jq . + +TELNET_PASSWORD=$(python3 password.py $(curl -sLk http://$ROUTER_IP/cgi-bin/luci/api/xqsystem/bdata | jq -r .SN)) + +echo +echo "===]> Info: telnet $ROUTER_IP" +echo "===]> Info: TELNET_USER=root" +echo "===]> Info: TELNET_PASSWORD=$TELNET_PASSWORD"