Skip to content

路由器折腾记

作者:Atom
字数统计:5.9k 字
阅读时长:22 分钟

很久之前购入红米AX6000路由器, 信号比自己之前的网件R7000好太多了, 于是网件路由器成了子路由。本文主要记录红米AX6000折腾的具体操作步骤, 方便回溯

一、路由器拨号

家里需要链接网络的设备实在太多了, 加之为了发挥路由器的能力, 所以需要将光猫改成桥接模式, 再使用路由器拨号上网

这一步直接找电信客服, 说要改成桥接模式, 然后找他们拿到宽带拨号的账号密码, 然后在路由器的上网设置中填入账号密码, 点击拨号即可

红米AX6000, 浏览器输入http://192.168.31.1进入到管理后台, 进入到常用设置->上网设置, 填入相关信息

pppoe

二、路由器开启SSH

折腾之路的关键步骤是开启SSH, 只有开启了SSH, 才能刷第三方固件或者自定义路由器各种配置。 例如防火墙或者网络等

安装telnet工具

作者使用的是Mac电脑, 所以需要安装一个telnet工具。 如果读者使用的是Windows电脑, 只需启用系统的telnet工具即可, 请自行搜索解决。而Mac中, 使用brew安装telnet工具即可

sh
brew install telnet

固件降级

  • 下载Redmi AX6000 1.0.60固件
  • 需要利用老版本的漏洞才能开启ssh, 所以需要手动降级到1.0.60版本,如下图上传下载的固件然后点升级

升级到1.0.60版本

  • 升级到1.0.60版本

在这个升级过程会报如下错误: 出于安全考虑,不允许选择低于当前版本的固件进行升级。解决方法是在地址栏的url最后一个0改成1或者1改成0, 然后回车就可以直接升级了。

获取token

登陆小米路由器admin,浏览器地址栏stok=后面部分就是token, 这个token是每次登录都会变化,后面都会用到这个token。如果重新登录后,都要重新复制这个token

获取token

开启开发者模式

先更改crash分区, 然后重启路由器

I. 更改路由器的crash分区,使其进入到开发者模式

将下面的URL里面的stok=tokentoken替换成上面获取路由器的token值,然后复制到到浏览器并且按回车打开

sh
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=tokentoken替换成上面获取路由器的token

sh
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=tokentoken替换成上面获取路由器的token

sh
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%20

II. 重启路由器

在浏览器地址栏输入下面的URL, 和上面的做法一样,将stok=tokentoken替换成上面获取路由器的token

sh
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作为你的密码

bash
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登录命令

bash
ssh root@192.168.31.1

永久开启SSH

该步骤分为创建开机脚本和固化SSH脚本两个步骤

I. 创建开机脚本

telnet开启的ssh,路由器重启会失效,添加一个开机自动运行的脚本,来实现自动开启

注意

如果恢复出厂设置或重新刷机后则需要重新添加

bash
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保存并退出

bash
#!/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
fi

II. 固化SSH脚本

输入下面的命令, 用于固化SSH脚本

bash
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连接上路由器后,输入指令关闭开发者模式

bash
mtd erase crash
reboot

修复时区异常

如果路由器时区异常,SSH连接中路由器后, 输入指令修复时区异常

bash
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.67SSH还是开启了,密码也是myPassword

三、桥接模式访问光猫后台

目前,我们光猫设为桥接模式,使用路由器来进行拨号上网。但在这种情况下,如果我们要访问光猫的管理界面,通常的做法是,断开网络,把猫直接连接到电脑,或者把猫连接到路由器LAN口, 之后可能还需要修改电脑IP才可以进入猫的配置界面

为了能把这个问题简单化, 让路由器直接访问光猫的管理后台http://192.168.1.1,就需要给路由器的WAN口添加一个和猫IP同网段的IP,并设置访问规则

步骤

为路由器WAN口新建一个 interface,设置为和光猫LAN同网段的一个静态IP

在防火墙配置中,将新建的接口设置为和WAN口同一区域

查看物理网卡类型

登陆SSH,然后通过下面命令查看物理网卡类型

bash
ssh root@192.168.31.1
cat /etc/config/network

在打印中找到如下 config interface 'wan' 的配置项, 其中 option ifname 'eth4' 表示此接口使用的物理网卡是eth4,将该值复制下来, 我们等下需要使用到

bash
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文件

bash
vim /etc/config/network

将下面的内容复制到文件的末尾中, 其中option ifname的值就是上面我们复制的物理网卡类型, option ipaddr 要和光猫IP(192.168.1.1)同网段

bash
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'

sh
vim /etc/config/firewall

最终的zone配置如下

bash
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'

保存配置后, 执行重启网络命令后, 就能直接通过拨号的路由器来访问光猫配置后台页面了

sh
/etc/init.d/network restart

Network 持久化

请查看配置防火墙章节-局部开放固定端口

四、配置静态路由表

网件R7000通过有线连接到红米AX6000LAN后, 我把R7000作为独立子路由使用, 而不是AP(Access Point)模式

但是在这种情况下, 由于R7000WAN口是通过DHCP获取IP的, 所以R7000WANIP是动态的, 但是R7000LANIP是静态的

所以需要在红米AX6000上配置静态路由表, 将R7000WANIP添加到静态路由表中, 这样就可以访问R7000

Network 配置

打开network配置文件

bash
vim /etc/config/network

将下面配置添加到network文件的最后

bash
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 服务

bash
/etc/init.d/network restart

验证静态路由配置

通过命令route -n确认路由的配置是否生效, 可以看到已经添加了静态路由

bash
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

配置转发防火墙

这一步可以配置为全局转发也可以配置为局部转发, 强烈推荐配置为局部转发, 这样会更加安全

输入以下命令, 打开防火墙配置编辑页

sh
vim /etc/config/firewall

方式一、配置全局转发 不安全

bash
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'

方式二、配置局部转发 强烈推荐

bash
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'

重启服务

bash
/etc/init.d/firewall restart

验证静态路由转发是否成功

可以在浏览器输入子路由的管理界面 http://10.0.0.1 进行验证, 也可以通过ping命令进行验证

bash
ping 10.0.0.1

五、配置防火墙

在上文中, 我们已经为网络开通了IPv6, 那内部每一个设备都有自己的IPv6地址,这个好处就在于可以通过公网直接访问内网的设备或者服务了

为了 IPv6 的安全, 我们需要配置防火墙, 限制外部访问内部的IPv6地址。主要有两种配置来控制公网对内网IPv6设备的访问

  • 全局关闭IPv6防火墙(不安全)
  • 局部开放固定端口

全局关闭IPv6防火墙 极不推荐

既可以使用命令来完成, 也可以使用修改配置文件的方式来完成

方式一、使用命令

sh
ip6tables -F
ip6tables -X
ip6tables -P INPUT ACCEPT
ip6tables -P OUTPUT ACCEPT
ip6tables -P FORWARD ACCEPT

方式二、使用配置文件

这种方式其实已经在上文中使用过了, 请参考配置静态路由表章节的配置全局转发 然后 重启服务

局部开放固定IPv6端口 强烈推荐

在该场景下, 仅会开启用户配置的IPv6端口, 其他端口无法访问, 安全性得到了极大的保障

配置防火墙规则, 既可以使用命令行来完成, 也可以使用修改配置文件来完成

方式一、使用命令并进行固化

直接使用命令开启固定端口的防火墙, 会随着路由器的重启而失效(因为只会将数据保存于内存中)。因为路由器重启后会重置这些防火墙配置,这种方式下会多一个固化的步骤

使用下面命令开启端口后, 便可以允许公网访问固定的端口的服务或设备

sh
ip6tables -I forwarding_rule -p tcp --dport 5000 -j ACCEPT
ip6tables -I forwarding_rule -p tcp --dport 5000 -j ACCEPT

接着我们来解决红米AX6000路由重启后重置防火墙配置的问题

首先, 参考上文中的auto_ssh.sh创建自定义脚本方式, 我们此处也创建一个自定义脚本,该脚本用来做很多初始化的工作

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防火墙的端口

sh
#!/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中去执行

使用命令打开定时任务的编辑界面

sh
crontab -e

然后给该文件添加一行配置文件

注意

作者之所以要配置为 0 4,5 * * * /data/auto_ssh/user_script_init.sh >/dev/null 2>&1

是因为作者AX6000路由器设定了每晚3点30分定时重启, 此处可以根据自己的需求而自定义

sh
*/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/null2>&1 的区别

  • >/dev/null: 表示将命令的标准输出重定向到/dev/null,即不保存标准输出,相当于将输出丢弃
  • 2>&1: 表示将标准错误(stderr)重定向到标准输出(stdout),因此标准错误和标准输出都被重定向到 /dev/null

方式二、直接修改防火墙配置

作者更推荐这种方式,因为在该种方式下,不需要进行固化防火墙配置,直接修改防火墙配置文件即可,非常简单

直接通过以下命令, 开启防火墙配置文件的编辑

sh
vim /etc/config/firewall

打开配置文件后, 将下面内容添加到配置文件的末尾

sh
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'

最后使用命令重启防火墙服务即可

sh
/etc/init.d/firewall reload

方式三、使用命令修改配置文件

这种方式是通过命令来修改方式二中的配置文件,效果是一样的

sh
# 添加允许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 文件,添加类似以下的记录:

sh
192.168.x.x  yourdomain.com

这样,内网设备访问 yourdomain.com 时会直接连接到内网地址。

此处, 笔者用的是这种方案, 我的家庭主路由器是一个红米AX6000, 可以在米家App中配置Host规则即可

AX6000具体操作图示

作者的家庭网络中还有另一个子路由器网件R7000(梅林系统), 需要通过以下步骤来解决通过内网WIFI访问的问题,确保子路由器下的设备能够通过域名访问内网服务。

首先, 子路由器R7000是通过网线将自己的WAN口连接在主路由器AX6400LAN口上的, 同时子路由器开启了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 服务器,专门处理内网的域名解析。这种方式比较复杂,但可以灵活定制,确保内网设备始终能访问到正确的服务。

参考