1. 准备工作
硬件需求:确保你有一台小米路由器4A。
软件需求:下载适合你设备的OpenWrt固件和相关工具。
备份
备份文件:2024-07-23--14_07_48.tar.gz
除此之外在正式刷机之前还需备份编程器固件和无线驱动固件
2.28.xx为V1版本,2.30.xx为V2版本
2. 下载所需文件
Breed固件:用于刷入OpenWrt的基础固件。
可以从Breed官网下载。
breed-mt7621-pbr-m1.bin
。
OpenWrt固件:适合小米路由器4A的OpenWrt固件。
可以从OpenWrt官网下载。
openwrt-21.02.0-ramips-mt7621-xiaomi_mi-router-4a-gigabit-squashfs-sysupgrade.bin
。后台: 10.0.0.1 账号密码: rootopenwrt-07.17.2024-ramips-mt7621-xiaomi_mi-router-4a-gigabit-v2-squashfs-sysupgrade.bin Xiaomi Mi Router 4A Gigabit Edition v2 https://openwrt.ai/?target=ramips%2Fmt7621&id=xiaomi_mi-router-4a-gigabit-v2
后台: 10.0.0.1 账号密码: root
Python脚本:用于获取路由器的root权限。
OpenWRTInvasion.7z
padavan固件下载 https://opt.cn2qq.com/padavan/?_refluxos=a10
其他工具:
FTP客户端(如WinSCP)用于上传文件到路由器。
Telnet客户端(如PuTTY)用于远程连接路由器。
软件汇总:https://nwt2vfwrjfh.feishu.cn/drive/folder/HuunfrME6lWEQid9rSocpD37nNe?from=from_copylink
3. 获取路由器的root权限
路由器必须要能访问外网
LAN口使用网线连接电脑网口,设置网卡自动获取IP
安装Python:
在Windows系统中,下载并安装Python 3.7.4。
确保在安装过程中勾选“添加到Path环境变量”。
安装Python依赖:
打开命令提示符(cmd),输入以下命令:
pip install requests
运行Python脚本:
解压下载的
OpenWRTInvasion-0.0.7.zip
文件。管理员身份打开命令提示符,切换到解压后的文件夹路径。
运行以下命令:
#运行一次之后不能telnet的话,运行2次 python remote_command_execution_vulnerability_2.py
输入路由器的IP地址(默认为
192.168.31.1
),然后输入获取的stok值(从路由器管理界面的URL中获取)这个页面不要关闭。用户名root密码root
开启Telnet:
脚本运行完成后,使用Telnet连接路由器:
telnet 192.168.31.1
输入用户名
root
和密码root。
4. 刷入Breed固件
上传Breed固件:
使用FTP客户端(如WinSCP)将
breed-mt7621-pbr-m1.bin
上传到路由器的/tmp
目录。
刷入Breed固件:
在Telnet会话中,输入以下命令:
cd /tmp mtd write breed-mt7621-pbr-m1.bin Bootloader
路由器会自动重启。
5. 进入Breed模式
0.拔掉光猫和路由器连接的那个网线
重启路由器:
重启一下以太网卡
断开路由器电源,按住reset按钮,通电,3秒后松开。
访问Breed界面:
使用浏览器访问``。
须确保局域网内没有其他的网卡地址是192.168.1.1
6. 刷入padavan固件
1.刷入MI-R4A-Gigabit_3.4.3.9-099.trx固件
2.等待路由器重启以后,查看网关地址。
3.浏览器打开web管理控制台,账号密码都是admin
7. 刷入OpenWrt固件
首先重复第五步,如果重复第5步没有用,那么就在padavan的web控制台上恢复出厂设置。
上传OpenWrt固件:
刷入OpenWrt固件:
重启路由器:
路由器会自动重启并进入OpenWrt系统。
8. 配置OpenWrt
访问OpenWrt管理界面:
使用浏览器访问后台: 10.0.0.1 账号密码: root
配置网络:
设置WAN和LAN连接,配置无线网络的SSID和密码。
安装额外的软件包:
通过OpenWrt的软件包管理界面安装需要的插件和工具。
系统-软件包-clash
服务-clash进行相应配置
/磁盘空间不够,手动将luci-app-openclash_0.46.001-beta_all.ipk下载下来,放入到/tmp目录安装
路由器重启后,/tmp下的内容会被删除。
备份当前配置:
在OpenWrt管理界面中,选择“备份”选项,保存当前配置。
恢复备份:
系统-备份与升级,保存的备份文件。
9.配置阿里云ddns
使用脚本:https://gitcode.com/gh_mirrors/al/AliDDNSBash/blob/master/ReadMe.md
使用方法:
安装依赖 首先需要一个shell(目标是支持所有符合 POSIX 标准的 shell,在 ash 和 bash 上测试通过)。
然后安装curl,openssl-util。这些软件包在OpenWRT下可直接使用 opkg 命令安装。 opkg install curl openssl-util 修改脚本的setting代码段,其中DomainRecordId不清楚的话暂时不用修改,DNSServer修改为你在万网上使用的DNS服务器。如: AccessKeyId="MyID" AccessKeySec="MySecret" DomainRecordId="00000" DomainRR="www" DomainName="example.com" DomainType="A" DNSServer="dns9.hichina.com" 如果不清楚DomainRecordId的话,修改main函数,在里面调用describe_record,如: main() { describe_record #update_record } 然后执行这个脚本。如果没问题的话,就能获取到域名的所有解析记录的列表了: "RecordId":"914743353444791296", RR":"openwrt","DomainName":"rongtech.top","TTL":600,"Weight":1,"Remark":"openwrt xiaomi","Line":"default","Locked":false,"Type":"AAAA","Value":"2409:8a6a:b01c:32f0:e0da:8ff:fe0b:346a","RecordId":"914743353444791296",
上面的结果中,RecordId为914743353444791296得到结果后再修改DomainRecordId为正确的值。
修改main函数: main() { #describe_record update_record } 执行脚本即可。脚本会在本机IP地址和当前域名解析设置不同的时候调用API更新设置。
设置定时任务: */10 * * * * /bin/ash /overlay/ali_ddns.sh >> /tmp/ali_ddns.log
说明:*/10 * * * * :每10分钟执行一次 需要执行都脚本全路径 >> 执行日志输出位置全路径
1、下载脚本,修改脚本,上传脚本
#!/bin/sh
#By h46incon
#Dependences: curl, openssl-util, tr, sort
## ----- Setting -----
AccessKeyId="ak"
AccessKeySec="sk"
DomainRecordId="914743353444791296"
# DomainRR, use "@" to set top level domain
DomainRR="openwrt"
DomainName="rongtech.top"
DomainType="AAAA"
DNSServer="dns13.hichina.com"
# The server address of ALi API
ALiServerAddr="alidns.aliyuncs.com"
# A url provided by a third-party to echo the public IP of host
MyIPEchoUrl="http://members.3322.org/dyndns/getip"
# MyIPEchoUrl="http://icanhazip.com"
# the generatation a random number can be modified here
#((rand_num=${RANDOM} * ${RANDOM} * ${RANDOM}))
rand_num=$(openssl rand -hex 16)
## ----- Log level -----
_DEBUG_=true
_LOG_=true
_ERR_=true
## ===== private =====
## ----- global var -----
# g_pkey_$i # param keys
# g_pval_$key # param values
g_pn=0 # number of params
_func_ret=""
## ----- Base Util -----
_debug() { ${_DEBUG_} && echo "> $*"; }
_log() { ${_LOG_} && echo "* $*"; }
_err() { ${_ERR_} && echo "! $*"; }
reset_func_ret()
{
_func_ret=""
}
## ----- params -----
# @Param1: Key
# @Param2: Value
put_param()
{
eval g_pkey_${g_pn}=$1
eval g_pval_$1=$2
g_pn=$((g_pn + 1))
}
reset_param()
{
g_pn=0
}
# This function will init all public params EXCLUDE "Signature"
put_params_public()
{
put_param "Format" "JSON"
put_param "Version" "2015-01-09"
put_param "AccessKeyId" "${AccessKeyId}"
put_param "SignatureMethod" "HMAC-SHA1"
put_param "SignatureVersion" "1.0"
# time stamp
local time_utc=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
_debug time_stamp: ${time_utc}
put_param "Timestamp" "${time_utc}"
# random number
_debug rand_num: ${rand_num}
put_param "SignatureNonce" "${rand_num}"
}
# @Param1: New IP address
put_params_UpdateDomainRecord()
{
put_param "Action" "UpdateDomainRecord"
put_param "RR" "${DomainRR}"
put_param "RecordId" "${DomainRecordId}"
put_param "Type" "${DomainType}"
put_param "Value" "${1}"
}
put_params_DescribeDomainRecords()
{
put_param "Action" "DescribeDomainRecords"
put_param "DomainName" ${DomainName}
}
put_params_DescribeDomainRecordInfo()
{
put_param "Action" "DescribeDomainRecordInfo"
put_param "RecordId" "${DomainRecordId}"
}
pack_params()
{
reset_func_ret
local ret=""
local key key_enc val val_enc
local i=0
while [ $i -lt ${g_pn} ]
do
eval key="\$g_pkey_${i}"
eval val="\$g_pval_${key}"
rawurl_encode "${key}"
key_enc=${_func_ret}
rawurl_encode "${val}"
val_enc=${_func_ret}
ret="${ret}${key_enc}=${val_enc}&"
i=$((++i))
done
#delete last "&"
_func_ret=${ret%"&"}
}
# ----- Other utils -----
get_my_ip()
{
reset_func_ret
#local my_ip=$(curl ${MyIPEchoUrl} --silent --connect-timeout 10)
local my_ip=$(ip addr show wan | grep inet6|head -1 |awk '{print $2}'|awk -F '/' '{print $1}')
#echo ${my_ip}
_func_ret=${my_ip}
}
get_domain_ip()
{
put_params_public
put_params_DescribeDomainRecordInfo
send_request
local result=${_func_ret}
reset_param
reset_func_ret
_func_ret=$(echo ${result} |grep -Eo '"Value":"[0-9a-f:.]+"' |grep -Eo '[0-9a-f:.]{5,}')
}
# @Param1: Raw url to be encoded
rawurl_encode()
{
reset_func_ret
local string="${1}"
local strlen=${#string}
local encoded=""
local pos c o
pos=0
while [ ${pos} -lt ${strlen} ]
do
c=${string:$pos:1}
case "$c" in
[-_.~a-zA-Z0-9] ) o="${c}" ;;
* ) o=$(printf "%%%02X" "'$c")
esac
encoded="${encoded}${o}"
pos=$(($pos + 1))
done
_func_ret="${encoded}"
}
calc_signature()
{
reset_func_ret
local sorted_key=$(
i=0
while [ $i -lt ${g_pn} ]
do
eval key="\$g_pkey_$i"
echo "${key}"
i=$((++i))
done | LC_ALL=C sort
)
local query_str=""
for key in ${sorted_key}
do
eval val="\$g_pval_${key}"
rawurl_encode "${key}"
key_enc=${_func_ret}
rawurl_encode "${val}"
val_enc=${_func_ret}
query_str="${query_str}${key_enc}=${val_enc}&"
done
query_str=${query_str%'&'}
_debug Query String: ${query_str}
# encode
rawurl_encode "${query_str}"
local encoded_str=${_func_ret}
local str_to_signed="GET&%2F&"${encoded_str}
_debug String to Signed: ${str_to_signed}
local key_sign="${AccessKeySec}&"
_func_ret=$(/bin/echo -n ${str_to_signed} | openssl dgst -binary -sha1 -hmac ${key_sign} | openssl enc -base64)
}
send_request()
{
reset_func_ret
# put signature
calc_signature
local signature=${_func_ret}
put_param "Signature" "${signature}"
# pack all params
pack_params
local packed_params=${_func_ret}
local req_url="${ALiServerAddr}/?${packed_params}"
_debug Request addr: ${req_url}
local respond=$(curl -3 ${req_url} --silent --connect-timeout 10 -w "HttpCode:%{http_code}")
echo ${respond}
_func_ret=${respond}
}
describe_record()
{
put_params_public
put_params_DescribeDomainRecords
send_request
}
update_record()
{
# get ip
get_my_ip
local my_ip=${_func_ret}
# Check if need update
_debug My IP: ${my_ip}
if [ -z "${my_ip}" ]; then
_err Could not get my ip, exitting...
exit
fi
get_domain_ip
local domain_ip=${_func_ret}
_debug Current Domain IP: ${domain_ip}
if [ "${my_ip}" == "${domain_ip}" ]; then
_log Need not to update, current IP: ${my_ip}
exit
fi
# init params
put_params_public
put_params_UpdateDomainRecord ${my_ip}
send_request
}
main()
{
#describe_record
update_record
}
main
上传脚本,给脚本执行权限
2、安装依赖
3、设置定时任务
*/10 * * * * /bin/ash /overlay/ali_ddns.sh >> /tmp/ali_ddns.log
4、等待10-20分钟查看日志文件验证ddns,如果解析记录更改成功,此时也会收到阿里云的邮件通知
10.刷回小米原厂
需要使用备份的编程器固件刷回原厂,我刷之前没有备份。
注意事项
防火墙设置:确保防火墙允许相关端口的访问,否则可能会导致连接失败。
固件版本:确保下载的固件版本与路由器型号匹配。
网络连接:在获取root权限和刷入Breed固件时,确保路由器可以访问外网。