在Ubuntu上为Redmi路由器AC2100编写可执行程序

304 阅读1分钟

背景

我有一台Redmi路由器AC2100,想为其编写程序。由于Ubuntu编译的程序无法在路由器上运行(因为系统和内核不同),我需要建立一个适合的编译环境。

获取SSH访问权限

详细可以看Openwrt官方文档

电脑连接上路由器,浏览器访问路由器IP,我这个里的是http://192.168.28.1/

QQ20241016-000334.png

登录后,F12通过控制台中输入脚本

function getSTOK() {
    let match = location.href.match(/;stok=(.*?)//);
    if (!match) {
        return null;
    }
    return match[1];
}

function execute(stok, command) {
    command = encodeURIComponent(command);
    let path = `/cgi-bin/luci/;stok=${stok}/api/misystem/set_config_iotdev?bssid=SteelyWing&user_id=SteelyWing&ssid=-h%0A${command}%0A`;
    console.log(path);
    return fetch(new Request(location.origin + path));
}

function enableSSH() {
    stok = getSTOK();
    if (!stok) {
        console.error('stok not found in URL');
        return;
    }
    console.log(`stok = "${stok}"`);

    password = prompt('Input new SSH password');
    if (!password) {
        console.error('You must input password');
        return;
    }

    execute(stok, 
`
nvram set ssh_en=1
nvram commit
sed -i 's/channel=.*/channel=\"debug\"/g' /etc/init.d/dropbear
/etc/init.d/dropbear start
`
    )
        .then((response) => response.text())
        .then((text) => console.log(text));
    console.log('New SSH password: ' + password);
    execute(stok, `echo -e "${password}\n${password}" | passwd root`)
        .then((response) => response.text())
        .then((text) => console.log(text));
}

enableSSH();

回车执行,输入密码如下

QQ20241016-001912.png

SSH连接路由器

Windows打开CMD执行SSH命令(可以用其他SSH工具)

# 使用SSH连接
ssh -o HostKeyAlgorithms=+ssh-rsa root@192.168.28.1

进入SSH,执行cat /etc/os-release系统信息,可以看到是OpenWrt 18.06-SNAPSHOT,ramips/mt7621

root@XiaoQiang:/bin# cat /etc/os-release
NAME="OpenWrt"
VERSION="18.06-SNAPSHOT"
ID="openwrt"
ID_LIKE="lede openwrt"
PRETTY_NAME="OpenWrt 18.06-SNAPSHOT"
VERSION_ID="18.06-snapshot"
HOME_URL="http://openwrt.org/"
BUG_URL="http://bugs.openwrt.org/"
SUPPORT_URL="http://forum.lede-project.org/"
BUILD_ID="unknown"
LEDE_BOARD="ramips/mt7621"
LEDE_ARCH="mipsel_24kc"
LEDE_TAINTS="no-all busybox"
LEDE_DEVICE_MANUFACTURER="OpenWrt"
LEDE_DEVICE_MANUFACTURER_URL="http://openwrt.org/"
LEDE_DEVICE_PRODUCT="Generic"
LEDE_DEVICE_REVISION="v0"
LEDE_RELEASE="OpenWrt 18.06-SNAPSHOT unknown"
root@XiaoQiang:/bin# 

OpenWrt官网下载编译好的SDK,也可以自己去编译。 根据上面系统信息,选择18.06.4/targets/ramips/mt7621/,复制下载连接openwrt-sdk-18.06.4-ramips-mt7621_gcc-7.3.0_musl.Linux-x86_64.tar.xz

安装编译的环境

我这里选择的是Ubuntu系统,尝试问GPT:Ubuntu那个版本时候编译openwrt-sdk-18.06.4

QQ20241016-005254.png

他推荐的是Ubuntu 16.04,为了方便使用Docker去部署这个环境

# docker命令启动Ubuntu 16.04容器,允许22端口,并且进入容器
docker run -it -p 22:22 --name ubuntu-16.04-container ubuntu:16.04
# 进入容器
docker exec -it ubuntu-16.04-container bash

为了方便编译程序,Ubuntu需要开启root账号的SSH连接,进入容器后执行

# 更新源
apt update
# 安装SSH服务和netstat,vim
apt install -y openssh-server net-tools vim curl xz-utils
# 添加SSH目录来存放临时文件
mkdir -p /var/run/sshd
# root用户设置密码
passwd root 
# 允许root登录,修改sshd_config下的PermitRootLogin yes
sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# 启动服务
/usr/sbin/sshd
# 查看22端口是否启动
netstat -plnt

在Ubuntu容器里,使用wget下载OpenWrt的SDK,下面可能会下载很慢,可以用迅雷下下载,再用SCP命令上传到容器里

# 下载
wget -p /usr/local/src https://downloads.openwrt.org/releases/18.06.4/targets/ramips/mt7621/openwrt-sdk-18.06.4-ramips-mt7621_gcc-7.3.0_musl.Linux-x86_64.tar.xz
# cd 
cd /usr/local/src
# 解压
tar -xvf openwrt-sdk-18.06.4-ramips-mt7621_gcc-7.3.0_musl.Linux-x86_64.tar.xz

配置环境变量,在/etc/profile添加

export STAGING_DIR=/usr/local/src/openwrt-sdk-18.06.4-ramips-mt7621_gcc-7.3.0_musl.Linux-x86_64/staging_dir
export PATH=$STAGING_DIR/toolchain-mipsel_24kc_gcc-7.3.0_musl/bin:$PATH
export PATH=$STAGING_DIR/host/bin:$PATH

配置文件生效

source /etc/profile

编写Hello, World

vi创建helloworld.c,写入下面代码

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

下面编译代码,当前系统执行不了,用file可以查看他是MIPS类型

# 编译文件
mipsel-openwrt-linux-gcc -o helloworld helloworld.c
# 执行文件
./helloworld
# 查看文件类型
file helloworld

通过scp将文件上传的红米路由器上,然后执行

# 上传文件
scp helloworld root@192.168.28.1:/tmp
# 执行文件
/tmp/helloworld