前言
小米路由器本身自带了DDNS,但是局限性比较高只能用以下4种, 默认不支持阿里云DDNS.

1. 开启路由器的SSH功能
1.1 下载工具
这里使用的是Github上的开源项目XMiR-Patcher实现。
项目地址
下载项目到本地, 然后运行以下命令,出现交互对话框
# Windows
Run run.bat
# Linux / Mac OS
Install python 3.8, openssl
Run run.sh需要注意的是Linux或Mac需要安装python3.8和openssl
1.2 开启路由器的SSH服务并修改路由器的root密码
运行后按如下顺序进行交互:
先选择1, 输入路由器地址
再选择2, 连接路由器, 根据提示输入路由器登录密码, 此时ssh服务会开启
再选择8, 进入其他选项
在其他选项中选择2, 修改路由器的root密码
==========================================================
Xiaomi MiR Patcher
1 - Set IP-address (current value: 192.168.31.1)
2 - Connect to device (install exploit)
3 - Read full device info
4 - Create full backup
5 - Install EN/RU languages
6 - Install permanent SSH
7 - Install firmware (from directory "firmware")
8 - {{{ Other functions }}}
9 - [[ Reboot device ]]
0 - Exit
Select: 1
Enter device IP-address: 192.168.31.1
Device IP-address changed to 192.168.31.1
==========================================================
Xiaomi MiR Patcher
1 - Set IP-address (current value: 192.168.31.1)
2 - Connect to device (install exploit)
3 - Read full device info
4 - Create full backup
5 - Install EN/RU languages
6 - Install permanent SSH
7 - Install firmware (from directory "firmware")
8 - {{{ Other functions }}}
9 - [[ Reboot device ]]
0 - Exit
Select: 2
device_name = RB03
rom_version = 1.0.57 release
mac_address = 00:72:ee:11:5b:ca
CountryCode = CN
Enter device WEB password: 你的路由器密码
WARN: Exploits "arn_switch/start_binding/set_mac_filter" not working!!!
Enable smartcontroller scene executor ...
Wait smartcontroller activation ...
Unlock dropbear service ...
Unlock SSH server ...
Set password "root" for root user ...
Enabling dropbear service ...
Run SSH server on port 22 ...
Test SSH connection to port 22 ...
#### SSH server are activated! ####
#### 如果不需要重置root密码, 到这里已经可以了
==========================================================
Xiaomi MiR Patcher
1 - Set IP-address (current value: 192.168.31.1)
2 - Connect to device (install exploit)
3 - Read full device info
4 - Create full backup
5 - Install EN/RU languages
6 - Install permanent SSH
7 - Install firmware (from directory "firmware")
8 - {{{ Other functions }}}
9 - [[ Reboot device ]]
0 - Exit
Select: 8
----------------------------------------------------------
Xiaomi MiR Patcher (extended functions)
1 - Set IP-address (current value: 192.168.31.1)
2 - Change root password
3 - Read dmesg and syslog
4 - Create a backup of the specified partition
5 - Uninstall EN/RU languages
6 - Set kernel boot address
7 - Install Breed bootloader
8 - __test__
9 - [[ Reboot device ]]
0 - Return to main menu
Choice: 2
Enter new password for root user: 新的root用户密码
The root password has been changed.
----------------------------------------------------------
Xiaomi MiR Patcher (extended functions)
1 - Set IP-address (current value: 192.168.31.1)
2 - Change root password
3 - Read dmesg and syslog
4 - Create a backup of the specified partition
5 - Uninstall EN/RU languages
6 - Set kernel boot address
7 - Install Breed bootloader
8 - __test__
9 - [[ Reboot device ]]
0 - Return to main menu
Choice:2. 部署DDNS工具
2.1 ssh连接到路由器
# 如果曾经重置过密码, 这里需要先删除本地保存的秘钥记录
PS C:\Users\zhangyunlong> ssh-keygen -R 192.168.31.1
PS C:\Users\zhangyunlong> ssh -oHostKeyAlgorithms=+ssh-rsa root@192.168.31.1
root@192.168.31.1's password:
BusyBox v1.25.1 (2023-01-30 08:16:20 UTC) built-in shell (ash)
-----------------------------------------------------
Welcome to XiaoQiang!
-----------------------------------------------------
$$$$$$\ $$$$$$$\ $$$$$$$$\ $$\ $$\ $$$$$$\ $$\ $$\
$$ __$$\ $$ __$$\ $$ _____| $$ | $$ | $$ __$$\ $$ | $$ |
$$ / $$ |$$ | $$ |$$ | $$ | $$ | $$ / $$ |$$ |$$ /
$$$$$$$$ |$$$$$$$ |$$$$$\ $$ | $$ | $$ | $$ |$$$$$ /
$$ __$$ |$$ __$$< $$ __| $$ | $$ | $$ | $$ |$$ $$<
$$ | $$ |$$ | $$ |$$ | $$ | $$ | $$ | $$ |$$ |\$$\
$$ | $$ |$$ | $$ |$$$$$$$$\ $$$$$$$$$ | $$$$$$ |$$ | \$$\
\__| \__|\__| \__|\________| \_________/ \______/ \__| \__|
root@XiaoQiang:~#2.2 创建DDNS脚本
创建ddns脚本并验证
root@XiaoQiang:~# cd /data
root@XiaoQiang:/data# ls
etc etc_bak ini userdisk usr
root@XiaoQiang:/data# mkdir scripts
root@XiaoQiang:/data# cd scripts/
root@XiaoQiang:/data/scripts# vim aliyun_ddns.sh
root@XiaoQiang:/data/scripts# chmod a+x aliyun_ddns.sh
root@XiaoQiang:/data/scripts# ./aliyun_ddns.sh
**************************************************
Thu Jan 1 21:10:13 CST 2026
fn.zhangwenyuan.cn
ddns is IPv4.
machine_ip = 219.157.215.133
BusyBox v1.25.1 (2023-01-30 08:16:20 UTC) multi-call binary.
Usage: nslookup [HOST] [SERVER]
Query the nameserver for the IP address of the given HOST
optionally using a specified DNS server
ddns_ip =
start update...
---------------- \n
add record starting
added record 2006714581972355072 \n
root@XiaoQiang:/data/scripts#脚本内容如下, 按需修改(ak, sk, 域名, 解析类型):
#!/bin/sh
set -e
#================================================================================================================#
# 功能:用于更新阿里云域名IP,实现DDNS功能
#
# 在 http://www.gebi1.com/forum.php?mod=viewthread&tid=287344&page=1&_dsign=8f94f74c 提供的脚本文件基础上修改的。
# ghui, modified 12/2/2019
# 在 N1 debian Buster with Armbian Linux 5.3.0-aml-g12 手动执行/定时任务(crontab)执行测试通过
#================================================================================================================#
#
# 使用方法:
#
# 方法1. 外部参数
# 修改源码,将对应参数 修改为$1,$2,$3,$4,$5,$6
# aliddns.sh <aliddns_ak> <aliddns_sk> <aliddns_subdomain> <aliddns_domain> <aliddns_iptype> <aliddns_ttl>
# 示例(A 代表 IPv4,AAAA 代表 IPv6):
# 执行:aliddns.sh "xxxx" "xxx" "test" "mydomain.site" "A" 600
# 执行:aliddns.sh "xxxx" "xxx" "test" "mydomain.site" "AAAA" 600
#
# 方法2. 内部参数
# 修改源码,将$1,$2,$3,$4,$5,$6 替换为对应参数
#
# 示例:
# aliddns_ak="<aliddns_ak>"
# aliddns_sk="<aliddns_sk>"
# aliddns_subdomain="<aliddns_subdomain>"
# aliddns_domain="<aliddns_domain> "
# aliddns_iptype="<aliddns_iptype>"
# aliddns_ttl=<aliddns_ttl>
# 执行:aliddns.sh
#
#================================================================================================================#
#--------------------------------------------------------------
# 参数
#
# (*)阿里云 AccessKeyId
aliddns_ak="阿里云 AccessKeyId "
# (*)阿里云 AccessKeySecret
aliddns_sk="阿里云 AccessKeySecret "
# (*)域名:test.mydomain.com
aliddns_subdomain="test.mydomain.com " #'test'
aliddns_domain="mydomain.com.cn" #'mydomain.com'
# (*)ip地址类型:'A' 或 'AAAA',代表ipv4 和 ipv6
aliddns_iptype="A" # 'A' 或 'AAAA',代表ipv4 和 ipv6
# TTL 默认10分钟 = 600秒
aliddns_ttl=600 #"600"
#--------------------------------------------------------------
machine_ip=""
ddns_ip=""
aliddns_record_id=""
if [ "$aliddns_subdomain" = "@" ]
then
aliddns_name=$aliddns_domain
else
aliddns_name=$aliddns_subdomain.$aliddns_domain
fi
now=`date`
echo "**************************************************"
echo "$now"
echo "$aliddns_name"
function getMachine_IPv4() {
echo $(/usr/bin/wget -qO- -t1 -T2 http://ip.3322.net)
}
function getMachine_IPv6() {
ipv6=`ip addr | grep "inet6.*global" | grep -v "deprecated" | awk '{print $2}' | awk -F"/" '{print $1}' | sed -n '1,1p'`
echo $ipv6
}
function getDDNS_IP() {
current_ip=`nslookup -query=$aliddns_iptype $aliddns_name | grep "Address" | grep -v "#53" | awk '{print $2}'`
echo $current_ip
}
function urlencode() {
# urlencode <string>
out=""
while read -n1 c
do
case $c in
[a-zA-Z0-9._-]) out="$out$c" ;;
*) out="$out`printf '%%%02X' "'$c"`" ;;
esac
done
echo -n $out
}
function enc() {
echo -n "$1" | urlencode
}
function send_request() {
local args="AccessKeyId=$aliddns_ak&Action=$1&Format=json&$2&Version=2015-01-09"
local hash=$(echo -n "GET&%2F&$(enc "$args")" | openssl dgst -sha1 -hmac "$aliddns_sk&" -binary | openssl base64)
curl -s "http://alidns.aliyuncs.com/?$args&Signature=$(enc "$hash")"
}
function get_recordid() {
grep -Eo '"RecordId":"[0-9]+"' | cut -d':' -f2 | tr -d '"'
}
function query_recordid() {
send_request "DescribeSubDomainRecords" "SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&SubDomain=$aliddns_name&Timestamp=$timestamp&Type=$aliddns_iptype"
}
function update_record() {
send_request "UpdateDomainRecord" "RR=$aliddns_subdomain&RecordId=$1&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&TTL=$aliddns_ttl&Timestamp=$timestamp&Type=$aliddns_iptype&Value=$(enc $machine_ip)"
}
function add_record() {
send_request "AddDomainRecord&DomainName=$aliddns_domain" "RR=$aliddns_subdomain&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&TTL=$aliddns_ttl&Timestamp=$timestamp&Type=$aliddns_iptype&Value=$(enc $machine_ip)"
}
if [ "$aliddns_iptype" = 'A' ]
then
echo "ddns is IPv4."
machine_ip=`echo "$(getMachine_IPv4)"`
echo "machine_ip = $machine_ip"
aliddns_record_id=$aliddnsipv4_record_id
else
echo "ddns is IPv6."
machine_ip=`echo "$(getMachine_IPv6)"`
echo "machine_ip = $machine_ip"
aliddns_record_id=$aliddnsipv6_record_id
fi
ddns_ip=`echo "$(getDDNS_IP)"`
echo "ddns_ip = $ddns_ip"
if [ "$machine_ip" = "" ]
then
echo "machine_ip is empty!"
exit 0
fi
if [ "$machine_ip" = "$ddns_ip" ]
then
echo "skipping\n"
exit 1
fi
echo "start update..."
timestamp=`date -u "+%Y-%m-%dT%H%%3A%M%%3A%SZ"`
if [ "$aliddns_record_id" = "" ]
then
aliddns_record_id=`query_recordid | get_recordid`
echo "----------------" $aliddns_record_id "\n"
if [ "$aliddns_iptype" = 'A' ]
then
aliddnsipv4_record_id=$aliddns_record_id
else
aliddnsipv6_record_id=$aliddns_record_id
fi
fi
#add support */%2A and @/%40 record
if [ "$aliddns_record_id" = "" ]
then
echo "add record starting"
aliddns_record_id=`add_record | get_recordid`
if [ "$aliddns_record_id" = "" ]
then
echo "aliddns_record_id is empty. \n"
else
if [ "$aliddns_iptype" = 'A' ]
then
aliddnsipv4_record_id=$aliddns_record_id
else
aliddnsipv6_record_id=$aliddns_record_id
fi
echo "added record $aliddns_record_id \n"
fi
else
echo "update record starting"
update_record $aliddns_record_id
echo "updated record $aliddns_record_id \n"
fi2.3 添加定时任务
添加定时任务, 每20分钟执行这个DDNS脚本
root@XiaoQiang:/data/scripts# echo "*/20 * * * * /data/scripts/aliyun_ddns.sh" >> /etc/crontabs/root
root@XiaoQiang:/data/scripts# /etc/init.d/cron restart
root@XiaoQiang:/data/scripts#2.4 配置路由器访问策略
先在路由器管理后台按需配置端口转发, 保证公网访问指定端口转发到局域网指定ip的指定端口
然后编辑防火墙配置文件
vi /etc/config/firewall在末尾添加以下内容, 禁止公网访问路由器
config rule
option name 'Deny-WAN-to-Router'
option src 'wan'
option dest_ip '192.168.31.1'
option proto 'tcp udp'
option target 'REJECT'
option family 'ipv4'注: 此措施可避免路由器本身暴露在公网环境下, 只开放特定端口到公网环境, 特定端口转发到局域网后, 由局域网内的设备灵活处理(例如限制仅中国大陆ip访问)
https://dl-pc-zb.drive.quark.cn/FF1UEXib/2570223830/63c488c605d51fc7146a43b5bfc8fad934a65c77/63c488c6c9af147fb85b48dd83f99559bb2e421a?abt=8_0_&auth_key=1769477494-13624735-681220-20bbf2ec3dde97c36e395ed99772bcc3&sp=100&token=5-4157e4319af12ae9819506d61b5e63a8-8-1-400-6b6d721124044b87a508034b7be894af-400-0-0-0-1768796274852-6f225df4c9383382bd40365ab3b14d81&ork=3BJ311G3HKJ539J3eN528jbTSwS1qPk82U17BvZJn&ud=16-0-1-2-1-N-4-N-1-16-0-N-N-N-N&dfi=193&filename=Game.of.Thrones.S01E05.The.Wolf.and.the.Lion.2011.UHD.Blu-ray.2160p.10bit.DoVi.2Audio.TrueHD%28Atmos%29.7.1.x265-beAst.mkv
https://dl-pc-zb-cf.pds.quark.cn/RXFphHCk/2570223830/63c488c67fea9536795c4759be6906d3f70358a8/63c488c67863ed8cccd14e79afbff0d07a7ca0b9?Expires=1769659657&OSSAccessKeyId=LTAI5tJJpWQEfrcKHnd1LqsZ&Signature=5QeXcN0hg5QraANrJDoWFspjEWc%3D&x-oss-traffic-limit=503316480&response-content-disposition=attachment%3B filename%3DGame.of.Thrones.S01E06.A.Golden.Crown.2011.UHD.Blu-ray.2160p.10bit.DoVi.2Audio.TrueHD%2528Atmos%2529.7.1.x265-beAst.mkv%3Bfilename%2A%3Dutf-8%27%27Game.of.Thrones.S01E06.A.Golden.Crown.2011.UHD.Blu-ray.2160p.10bit.DoVi.2Audio.TrueHD%2528Atmos%2529.7.1.x265-beAst.mkv&callback-var=eyJ4OmF1IjoiMTc2OTY1OTY1Ny0xNzI2NDkwMC04NjMyNDAtYmJiMiIsIng6b3JrIjoiRjU4NEx1ckVhNDgzQWhGTzExNkJaZWdJcUdTREY5UGt2OWljUGRNZFkiLCJ4OmhzcCI6InF1YXJrX25vbl9wZXJzb25hbF9iaWdfZmlsZV9kdCIsIng6dWQiOiIxNi0wLTEtMi0xLU4tNC1OLTEtMTYtMC1OLU4tTi1OIiwieDpkdF9zcCI6IjEiLCJ4OnNwIjoiMTAwIiwieDp0b2tlbiI6IjQtNDE1N2U0MzE5YWYxMmFlOTgxOTUwNmQ2MWI1ZTYzYTgtOC0xLTQwMC1kZTgwMzU0MjEzMmM0M2MxOTM5ZTE2ZjRiOTJjYTNiMS00MDAtMC0wLTAtNGE0NjRhYzQ3MjlhYzJjYjE3NmMwYzJmYzBiNTljNTYiLCJ4OnR0bCI6Ijg2MzI0MCJ9&abt=8_0_&dfi=193&callback=eyJjYWxsYmFja0JvZHlUeXBlIjoiYXBwbGljYXRpb24vanNvbiIsImNhbGxiYWNrU3RhZ2UiOiJiZWZvcmUtZXhlY3V0ZSIsImNhbGxiYWNrRmFpbHVyZUFjdGlvbiI6Imlnbm9yZSIsImNhbGxiYWNrVXJsIjoiaHR0cHM6Ly9kcml2ZS1hdXRoLnF1YXJrLmNuL291dGVyL29zcy9jaGVja3BsYXkiLCJjYWxsYmFja0JvZHkiOiJ7XCJob3N0XCI6JHtodHRwSGVhZGVyLmhvc3R9LFwic2l6ZVwiOiR7c2l6ZX0sXCJyYW5nZVwiOiR7aHR0cEhlYWRlci5yYW5nZX0sXCJyZWZlcmVyXCI6JHtodHRwSGVhZGVyLnJlZmVyZXJ9LFwiY29va2llXCI6JHtodHRwSGVhZGVyLmNvb2tpZX0sXCJtZXRob2RcIjoke2h0dHBIZWFkZXIubWV0aG9kfSxcInVscnBcIjoke2h0dHBIZWFkZXIueC11bHJwfSxcImlwXCI6JHtjbGllbnRJcH0sXCJwb3J0XCI6JHtjbGllbnRQb3J0fSxcIm9ya1wiOiR7eDpvcmt9LFwib2JqZWN0XCI6JHtvYmplY3R9LFwic3BcIjoke3g6c3B9LFwidWRcIjoke3g6dWR9LFwidG9rZW5cIjoke3g6dG9rZW59LFwiYXVcIjoke3g6YXV9LFwidHRsXCI6JHt4OnR0bH0sXCJkdF9zcFwiOiR7eDpkdF9zcH0sXCJoc3BcIjoke3g6aHNwfSxcImNsaWVudF90b2tlblwiOiR7cXVlcnlTdHJpbmcuY2xpZW50X3Rva2VufX0ifQ%3D%3D&ud=16-0-1-2-1-N-4-N-1-16-0-N-N-N-N