路由器折腾记

很久之前购入红米AX6000路由器, 信号比自己之前的网件R7000好太多了, 于是网件路由器成了子路由。本文主要记录红米AX6000折腾的具体操作步骤, 方便回溯
一、路由器拨号
家里需要链接网络的设备实在太多了, 加之为了发挥路由器的能力, 所以需要将光猫改成桥接模式, 再使用路由器拨号上网
这一步直接找电信客服, 说要改成桥接模式, 然后找他们拿到宽带拨号的账号密码, 然后在路由器的上网设置中填入账号密码, 点击拨号即可
红米AX6000, 浏览器输入http://192.168.31.1进入到管理后台, 进入到常用设置->上网设置, 填入相关信息

二、路由器开启SSH
折腾之路的关键步骤是开启SSH, 只有开启了SSH, 才能刷第三方固件或者自定义路由器各种配置。 例如防火墙或者网络等
安装telnet工具
作者使用的是Mac电脑, 所以需要安装一个telnet工具。 如果读者使用的是Windows电脑, 只需启用系统的telnet工具即可, 请自行搜索解决。而Mac中, 使用brew安装telnet工具即可
brew install telnet固件降级
- 下载Redmi AX6000 1.0.60固件
- 需要利用老版本的漏洞才能开启ssh, 所以需要手动降级到1.0.60版本,如下图上传下载的固件然后点升级

- 升级到
1.0.60版本
在这个升级过程会报如下错误: 出于安全考虑,不允许选择低于当前版本的固件进行升级。解决方法是在地址栏的url最后一个0改成1或者1改成0, 然后回车就可以直接升级了。
获取token
登陆小米路由器admin,浏览器地址栏stok=后面部分就是token, 这个token是每次登录都会变化,后面都会用到这个token。如果重新登录后,都要重新复制这个token

开启开发者模式
先更改crash分区, 然后重启路由器
I. 更改路由器的crash分区,使其进入到开发者模式
将下面的URL里面的stok=token的token替换成上面获取路由器的token值,然后复制到到浏览器并且按回车打开
http://192.168.31.1/cgi-bin/luci/;stok=token/api/misystem/set_sys_time?timezone=%20%27%20%3B%20zz%3D%24%28dd%20if%3D%2Fdev%2Fzero%20bs%3D1%20count%3D2%202%3E%2Fdev%2Fnull%29%20%3B%20printf%20%27%A5%5A%25c%25c%27%20%24zz%20%24zz%20%7C%20mtd%20write%20-%20crash%20%3B%20注意
通过URL进行的操作, 只要浏览器返回{“code”:0},表示成功。
II. 通过浏览器重启路由器
在浏览器地址栏输入下面的URL, 和上面的做法一样,将stok=token的token替换成上面获取路由器的token值
http://192.168.31.1/cgi-bin/luci/;stok=token/api/misystem/set_sys_time?timezone=%20%27%20%3b%20reboot%20%3b%20设置Bdata参数
也有两个步骤, 先设置参数后重启
I. 设置参数telnet_en、 ssh_en、uart_en
重启后,要重新获取token, 然后在浏览器地址栏输入下面的URL, 将stok=token的token替换成上面获取路由器的token值
http://192.168.31.1/cgi-bin/luci/;stok=token/api/misystem/set_sys_time?timezone=%20%27%20%3B%20bdata%20set%20telnet_en%3D1%20%3B%20bdata%20set%20ssh_en%3D1%20%3B%20bdata%20set%20uart_en%3D1%20%3B%20bdata%20commit%20%3B%20II. 重启路由器
在浏览器地址栏输入下面的URL, 和上面的做法一样,将stok=token的token替换成上面获取路由器的token值
http://192.168.31.1/cgi-bin/luci/;stok=token/api/misystem/set_sys_time?timezone=%20%27%20%3b%20reboot%20%3b%20通过telnet开启临时ssh
在终端输入telnet 192.168.31.1, 可以看到Are you ok的界面,就证明telnet成功了
telnet连接上,输入以下指令开启ssh,并修改下面的myPassword作为你的密码
bdata set boot_wait=on
bdata commit
nvram set ssh_en=1
nvram set telnet_en=1
nvram set uart_en=1
nvram set boot_wait=on
nvram commit
sed -i 's/channel=.*/channel="debug"/g' /etc/init.d/dropbear
/etc/init.d/dropbear restart
# 这里的myPassword是你需要修改的密码, root是账户名
echo -e 'myPassword\nmyPassword' | passwd root此时, 就可以使用ssh链接路由器了。 新开一个bash窗口,输入下面的ssh登录命令
ssh root@192.168.31.1永久开启SSH
该步骤分为创建开机脚本和固化SSH脚本两个步骤
I. 创建开机脚本
从telnet开启的ssh,路由器重启会失效,添加一个开机自动运行的脚本,来实现自动开启
注意
如果恢复出厂设置或重新刷机后则需要重新添加
mkdir /data/auto_ssh && cd /data/auto_ssh
touch auto_ssh.sh
chmod +x auto_ssh.sh
vim auto_ssh.sh上述命令会创建auto_ssh.sh文件,然后打开vim将下面的内容复制到文件中,复制完后输入:x保存并退出
#!/bin/sh
host_key=/etc/dropbear/dropbear_rsa_host_key
host_key_bk=/data/auto_ssh/dropbear_rsa_host_key
if [ -f $host_key_bk ]; then
ln -sf $host_key_bk $host_key
fi
channel=`/sbin/uci get /usr/share/xiaoqiang/xiaoqiang_version.version.CHANNEL`
if [ "$channel" = "release" ]; then
sed -i 's/channel=.*/channel="debug"/g' /etc/init.d/dropbear
/etc/init.d/dropbear restart
fi
if [ ! -s $host_key_bk ]; then
i=0
while [ $i -le 30 ]
do
if [ -s $host_key ]; then
cp -f $host_key $host_key_bk 2>/dev/null
break
fi
let i++
sleep 1s
done
fiII. 固化SSH脚本
输入下面的命令, 用于固化SSH脚本
uci set firewall.auto_ssh=include
uci set firewall.auto_ssh.type='script'
uci set firewall.auto_ssh.path='/data/auto_ssh/auto_ssh.sh'
uci set firewall.auto_ssh.enabled='1'
uci commit firewall关闭开发者模式
SSH连接上路由器后,输入指令关闭开发者模式
mtd erase crash
reboot修复时区异常
如果路由器时区异常,SSH连接中路由器后, 输入指令修复时区异常
uci set system.@system[0].timezone='CST-8'
uci set system.@system[0].webtimezone='CST-8'
uci set system.@system[0].timezoneindex='2.84'
uci commit注意事项
升级固件后,可能需要通过telnet重新开启SSH。不过目前我还没遇到过这种情况,在开启SSH后,我是直接将1.60的固件自动升级到1.67,SSH还是开启了,密码也是myPassword
三、桥接模式访问光猫后台
目前,我们光猫设为桥接模式,使用路由器来进行拨号上网。但在这种情况下,如果我们要访问光猫的管理界面,通常的做法是,断开网络,把猫直接连接到电脑,或者把猫连接到路由器LAN口, 之后可能还需要修改电脑IP才可以进入猫的配置界面
为了能把这个问题简单化, 让路由器直接访问光猫的管理后台http://192.168.1.1,就需要给路由器的WAN口添加一个和猫IP同网段的IP,并设置访问规则
步骤
为路由器WAN口新建一个 interface,设置为和光猫LAN同网段的一个静态IP
在防火墙配置中,将新建的接口设置为和WAN口同一区域
查看物理网卡类型
登陆SSH,然后通过下面命令查看物理网卡类型
ssh root@192.168.31.1
cat /etc/config/network在打印中找到如下 config interface 'wan' 的配置项, 其中 option ifname 'eth4' 表示此接口使用的物理网卡是eth4,将该值复制下来, 我们等下需要使用到
config interface 'wan'
option proto 'pppoe'
option peerdns '0'
option username 'CD12345678' # 这里是你的宽带账号
option password '123456' # 这里是你的宽带密码
option special '0'
option mru '1480'
option ifname 'eth4' # 这里就是我们需要查看的物理网卡类型
option ipv6 'auto'新建一个moden接口
通过下面命令编辑/etc/config/network文件
vim /etc/config/network将下面的内容复制到文件的末尾中, 其中option ifname的值就是上面我们复制的物理网卡类型, option ipaddr 要和光猫IP(192.168.1.1)同网段
config interface 'modem'
option proto 'static'
# eth4就是上面我们复制的物理网卡类型
option ifname 'eth4'
option ipaddr '192.168.1.254'
option netmask '255.255.255.0'输入:x保存并退出文件, 然后输入下面的命令将这个
添加防火墙规则
执行 vim /etc/config/firewall,并找到zone的配置后,在 list network 'wan6' 下面添加一行 list network 'modem'
vim /etc/config/firewall最终的zone配置如下
config zone
option name 'wan'
list network 'wan'
list network 'wan6'
list network 'modem'
option input 'REJECT'
option output 'ACCEPT'
option forward 'REJECT'
option masq '1'
option mtu_fix '1'保存配置后, 执行重启网络命令后, 就能直接通过拨号的路由器来访问光猫配置后台页面了
/etc/init.d/network restartNetwork 持久化
请查看配置防火墙章节-局部开放固定端口
四、配置静态路由表
网件R7000通过有线连接到红米AX6000的LAN后, 我把R7000作为独立子路由使用, 而不是AP(Access Point)模式
但是在这种情况下, 由于R7000的WAN口是通过DHCP获取IP的, 所以R7000的WAN口IP是动态的, 但是R7000的LAN口IP是静态的
所以需要在红米AX6000上配置静态路由表, 将R7000的WAN口IP添加到静态路由表中, 这样就可以访问R7000了
Network 配置
打开network配置文件
vim /etc/config/network将下面配置添加到network文件的最后
config route
option interface 'lan'
option target '10.0.0.0/24'
option netmask '255.255.255.0'
option gateway '192.168.31.175'route表示路由,target表示目标网段(也就是子路由的起始网段),netmask表示掩码,gateway表示主路由上LAN口的IP地址(作为子路由器的网关),interface表示接口,这里的接口是lan,也就是主路由的lan口
上面的配置是把子路由的网段指向主路由AX6000给子路由R7000分配的WAN IP
重启 network 服务
/etc/init.d/network restart验证静态路由配置
通过命令route -n确认路由的配置是否生效, 可以看到已经添加了静态路由
root@XiaoQiang:~# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 117.30.124.1 0.0.0.0 UG 0 0 0 pppoe-wan
10.0.0.0 192.168.31.175 255.255.255.0 UG 0 0 0 br-lan # 这就是添加的静态路由
192.168.32.0 0.0.0.0 255.255.255.0 U 0 0 0 br-miot配置转发防火墙
这一步可以配置为全局转发也可以配置为局部转发, 强烈推荐配置为局部转发, 这样会更加安全
输入以下命令, 打开防火墙配置编辑页
vim /etc/config/firewall方式一、配置全局转发 不安全
config defaults
option syn_flood '0'
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'REJECT'
option drop_invalid '1'
option forward 'ACCEPT'
option drop_invalid '0'
option disable_ipv6 '1'
config zone
option name 'lan'
option network 'lan'
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'REJECT'
option forward 'ACCEPT'方式二、配置局部转发 强烈推荐
config defaults
option syn_flood '0'
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'REJECT'
option drop_invalid '1'
option drop_invalid '0'
option disable_ipv6 '1'
config zone
option name 'R7000'
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'ACCEPT'
list subnet '10.0.0.0/24'
config forwarding
option src 'lan'
option dest 'R7000'重启服务
/etc/init.d/firewall restart验证静态路由转发是否成功
可以在浏览器输入子路由的管理界面 http://10.0.0.1 进行验证, 也可以通过ping命令进行验证
ping 10.0.0.1五、配置防火墙
在上文中, 我们已经为网络开通了IPv6, 那内部每一个设备都有自己的IPv6地址,这个好处就在于可以通过公网直接访问内网的设备或者服务了
为了 IPv6 的安全, 我们需要配置防火墙, 限制外部访问内部的IPv6地址。主要有两种配置来控制公网对内网IPv6设备的访问
- 全局关闭IPv6防火墙(不安全)
- 局部开放固定端口
全局关闭IPv6防火墙 极不推荐
既可以使用命令来完成, 也可以使用修改配置文件的方式来完成
方式一、使用命令
ip6tables -F
ip6tables -X
ip6tables -P INPUT ACCEPT
ip6tables -P OUTPUT ACCEPT
ip6tables -P FORWARD ACCEPT方式二、使用配置文件
这种方式其实已经在上文中使用过了, 请参考配置静态路由表章节的配置全局转发 然后 重启服务
局部开放固定IPv6端口 强烈推荐
在该场景下, 仅会开启用户配置的IPv6端口, 其他端口无法访问, 安全性得到了极大的保障
配置防火墙规则, 既可以使用命令行来完成, 也可以使用修改配置文件来完成
方式一、使用命令并进行固化
直接使用命令开启固定端口的防火墙, 会随着路由器的重启而失效(因为只会将数据保存于内存中)。因为路由器重启后会重置这些防火墙配置,这种方式下会多一个固化的步骤
使用下面命令开启端口后, 便可以允许公网访问固定的端口的服务或设备
ip6tables -I forwarding_rule -p tcp --dport 5000 -j ACCEPT
ip6tables -I forwarding_rule -p tcp --dport 5000 -j ACCEPT接着我们来解决红米AX6000路由重启后重置防火墙配置的问题
首先, 参考上文中的auto_ssh.sh创建自定义脚本方式, 我们此处也创建一个自定义脚本,该脚本用来做很多初始化的工作
cd /data/auto_ssh
touch user_script_init.sh
chmod +x user_script_init.sh
vim user_script_init.sh接着编辑user_script_init.sh的内容。 我们的脚本中
add_modem_interface用来解决光猫桥接后无法访问光猫的管理界面的函数add_firewall_forward用来开放固定的IPv6防火墙的端口
#!/bin/sh
# This is user custom script for initialization
# Network
add_modem_interface(){
echo 'start add interface modem...'
/sbin/uci set network.modem=interface
/sbin/uci set network.modem.proto='static'
/sbin/uci set network.modem.ifname='eth1.5'
/sbin/uci set network.modem.ipaddr='192.168.1.254'
/sbin/uci set network.modem.netmask='255.255.255.0'
/sbin/uci commit network
/etc/init.d/network reload >/dev/null
echo 'add interface modem success!'
}
# Firewall
add_firewall_forward(){
echo 'start add firewall forward port...'
local isEnabled=$(ip6tables -L | grep -c "tcp dpt:9999")
if [ $isEnabled -eq 0 ]; then
# nas
ip6tables -I forwarding_rule -p tcp --dport 9999 -j ACCEPT
ip6tables -I forwarding_rule -p udp --dport 9999 -j ACCEPT
# blog
ip6tables -I forwarding_rule -p tcp --dport 5173 -j ACCEPT
ip6tables -I forwarding_rule -p udp --dport 5173 -j ACCEPT
echo 'add firewall forward port success!'
fi
}
exec > /tmp/auto_ssh.log 2>&1
start_time=$(date +"%Y-%m-%d %H:%M:%S")
echo "User_script_init.sh started at: $start_time"
add_modem_interface
add_firewall_forward
echo 'User_script_init.sh run complete!'最后, 我们需要将这个脚本放到定时任务Crontab中去执行
使用命令打开定时任务的编辑界面
crontab -e然后给该文件添加一行配置文件
注意
作者之所以要配置为 0 4,5 * * * /data/auto_ssh/user_script_init.sh >/dev/null 2>&1
是因为作者AX6000路由器设定了每晚3点30分定时重启, 此处可以根据自己的需求而自定义
*/5 * * * * command -v sp_check.sh >/dev/null && sp_check.sh
*/2 * * * * command -v logrotate >/dev/null && logrotate /etc/logrotate.conf
*/15 * * * * /usr/sbin/ntpsetclock 60 log >/dev/null 2>&1
* * * * * /usr/sbin/startscene_crontab.lua `/bin/date "+%u %H:%M"`
1 3,4,5 * * * /usr/sbin/otapredownload >/dev/null 2>&1
*/3 * * * * /usr/sbin/mobile_accel.sh check >/dev/null 2>&1
# 上面都是原来的任务, 我们在最后追加
0 4,5 * * * /data/auto_ssh/user_script_init.sh >/dev/null 2>&1注意 >/dev/null 与 2>&1 的区别
>/dev/null: 表示将命令的标准输出重定向到/dev/null,即不保存标准输出,相当于将输出丢弃2>&1: 表示将标准错误(stderr)重定向到标准输出(stdout),因此标准错误和标准输出都被重定向到/dev/null
方式二、直接修改防火墙配置
作者更推荐这种方式,因为在该种方式下,不需要进行固化防火墙配置,直接修改防火墙配置文件即可,非常简单
直接通过以下命令, 开启防火墙配置文件的编辑
vim /etc/config/firewall打开配置文件后, 将下面内容添加到配置文件的末尾
config rule
option name 'Allow_TCP_Port_5000'
option src 'wan'
option dest 'lan'
option proto 'tcp'
option dest_port '5000' # 这是需要开启的TCP端口
option target 'ACCEPT'
config rule
option name 'Allow_UDP_Port_5000'
option src 'wan'
option dest 'lan'
option proto 'udp'
option dest_port '5000' # 这是需要开启的UDP端口
option target 'ACCEPT'最后使用命令重启防火墙服务即可
/etc/init.d/firewall reload方式三、使用命令修改配置文件
这种方式是通过命令来修改方式二中的配置文件,效果是一样的
# 添加允许TCP流量的规则
uci add firewall rule
uci set firewall.@rule[-1].name='Allow_TCP_Port_5000'
uci set firewall.@rule[-1].src='wan'
uci set firewall.@rule[-1].dest='lan'
uci set firewall.@rule[-1].proto='tcp'
uci set firewall.@rule[-1].dest_port='5000'
uci set firewall.@rule[-1].target='ACCEPT'
# 添加允许UDP流量的规则
uci add firewall rule
uci set firewall.@rule[-1].name='Allow_UDP_Port_5000'
uci set firewall.@rule[-1].src='wan'
uci set firewall.@rule[-1].dest='lan'
uci set firewall.@rule[-1].proto='udp'
uci set firewall.@rule[-1].dest_port='5000'
uci set firewall.@rule[-1].target='ACCEPT'
# 提交更改
uci commit firewall
# 重新加载防火墙配置
/etc/init.d/firewall reload六、内网DNS回环
然而在配置完各种步骤后, 通过使用 DDNS 访问家庭内网 之后却出现了一个问题:虽然外网能够通过域名正常访问家庭 NAS 服务,但当我在家庭内网(通过 Wi-Fi)访问同一个域名时,却无法访问到服务。
经过排查,发现问题的根源是 DNS 回环(DNS Loopback)的问题。这个问题的解决需要理解一下几个概念。
概念
DDNS(动态域名解析)
DDNS 允许用户通过动态 IP 地址来更新域名的解析记录。通常,家庭用户的公网 IP 地址是动态变化的,而 DDNS 通过不断地将公网 IP 地址更新到域名解析系统中,让用户能够通过固定的域名来访问自己的家庭网络服务。
DNS 回环(DNS Loopback)
DNS 回环指的是 DNS 请求返回与请求源相同的 IP 地址。简单来说,如果你在家庭内网的设备上请求一个外部域名解析,这个请求会被内部的 DNS 服务器解析为公网地址,而设备还试图使用外网地址来连接自己。这种情况可能导致无法通过域名访问内网的服务。
内网与外网的访问
内网访问通常是指设备在同一网络中的访问,这时设备的 IP 地址是局域网地址(例如,192.168.x.x 或 10.x.x.x)。而外网访问则是设备通过互联网进行的访问,涉及到路由器的 NAT(网络地址转换)与公网 IP 地址。
原因分析
在家庭网络中,当你通过 Wi-Fi 连接到路由器时,实际上你的设备既在外网(指的是通过公网与外部互联网连接)也在内网(指的是家庭局域网)。因此,当你尝试通过域名访问 NAS 服务时,设备的 DNS 查询会先通过外网的 DNS 服务器发起解析,结果是解析为公网 IP 地址
由于设备本身是通过 Wi-Fi 连接到内网,而不是直接访问外网,这就导致了回环问题。路由器和内网 DNS 服务器无法将公网 IP 正确路由到 NAS 内网 IP,从而造成访问失败。
处理方案
方案一:在家庭内网配置 DNS 回环处理
为了让内网设备正确访问自己的服务,可以通过配置路由器或内网 DNS 服务器来处理 DNS 回环。具体做法是:
- 设置 DNS 解析规则:
在路由器中设置特定的 DNS 解析规则,当内网设备访问特定的域名时,路由器会直接将该域名解析为内网的服务地址(例如内网的 NAS 地址)。
- 修改本地 hosts 文件:
你也可以在内网设备的 hosts 文件中手动添加一条记录,将域名解析为内网的 IPv6 地址。例如,在 Windows 系统中,可以编辑 C:\Windows\System32\drivers\etc\hosts 文件,添加类似以下的记录:
192.168.x.x yourdomain.com这样,内网设备访问 yourdomain.com 时会直接连接到内网地址。
此处, 笔者用的是这种方案, 我的家庭主路由器是一个红米AX6000, 可以在米家App中配置Host规则即可
AX6000具体操作图示

作者的家庭网络中还有另一个子路由器网件R7000(梅林系统), 需要通过以下步骤来解决通过内网WIFI访问的问题,确保子路由器下的设备能够通过域名访问内网服务。
首先, 子路由器R7000是通过网线将自己的WAN口连接在主路由器AX6400的LAN口上的, 同时子路由器开启了DHCP有自己独立的网段。
经过测试,并不需要额外的配置子路由器的DNS解析,它无法访问的原因是DDNS解析出来的域名是一个IPv6地址, 而子路由器R7000并未开启IPv6功能
因此只需要通过以下图示的配置设置一下既可
R7000具体操作图示

此时 hosts 已经生效,浏览器访问或者ping 域名进行测试
方案二:使用 Split-Horizon DNS
Split-Horizon DNS 是指根据查询源的不同,返回不同的解析结果。你可以在家中的 DNS 服务器上配置 Split-Horizon DNS,这样外网和内网访问同一域名时,分别返回不同的 IP 地址:
外网请求解析为公网 IP。 内网请求解析为内网 IP。 如果你没有专门的 DNS 服务器,可以考虑使用路由器支持的类似功能,或者通过安装像 dnsmasq 这样的服务,在内网设备上配置 DNS 分流。
方案三:利用本地 DNS 服务器
如果你使用的是 IPv6 地址,可以设置一个本地的 DNS 服务器,专门处理内网的域名解析。这种方式比较复杂,但可以灵活定制,确保内网设备始终能访问到正确的服务。