小米路由器开启SSH以及配置阿里云DDNS

作者:zhangyunlong 发布时间: 2026-01-01 阅读量:10 评论数:0

前言

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

image-Epdu.png

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"
fi

2.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

评论