上一篇已经在这台小米 BE10000 Pro 上实测:恢复出厂后,仍可通过 Telnet 直接登录 root,对应的解锁标志保存在 bdata 中。另外安装的 SSH 自动启动脚本和主机密钥属于用户配置,正常重启保留,恢复出厂会清除;重置后可以通过保留的 root 入口重新开启 SSH。

这一篇继续处理最初的需求:保留原厂无线驱动,把它作为主路由后面的 AP,同时承载普通设备和 IoT 设备,并为访客网络留下扩展位置。

前置条件见:小米 BE10000 Pro root 固化实录:从模块加载失败到恢复出厂后仍可登录。本文从“已经能够以 root 登录、已经完成本机备份”开始,不再展开 root 操作。

本文整理的是最终保留的配置和最小补丁。适用对象为 RP04、原厂 1.0.70、Linux 6.6.47。本机已经完成替换上线操作:主网上联和管理连接正常,三个无线电、五个 SSID 已启用并进入各自网桥,临时管理地址已删除,普通重启后端口补丁仍生效。万兆口实测协商到 10Gbps 和 5Gbps;IoT 有线成员已检测到物理链路。无线客户端的完整 DHCP/联网记录、两侧终端的广播与跨网隔离、IPv6 策略未形成逐项验收记录,访客网络仍为扩展方案。配置示例中的地址、SSID 均为示例值,没有放入设备密码、MAC、私钥或私人网络备份。

先确定边界:AP 分网,主路由执行访问策略

这套方案把工作分给两台设备:

  • 主路由负责各网络的网关、DHCP、DNS、IPv6 和跨网段防火墙。
  • 小米 AP 负责把不同 SSID、不同有线端口接入对应的二层网桥。

Linux bridge 工作在二层,负责以太帧转发,见 Linux 内核的网桥文档。把两组接口放进不同的 bridge,可以建立不同的二层连接关系;它不会自动替主路由禁止两个网段之间的路由访问。

因此,完整的“隔离”需要同时满足:

  1. AP 上的无线、有线成员分组正确,没有广播串网或交换芯片旁路转发。
  2. 上联确实进入主路由的不同网络。
  3. 主路由没有放行不需要的跨网访问,IPv4、IPv6 都执行对应策略。

如果主路由原来允许 lan ↔ iot,换一台分桥 AP 后仍然可以跨网访问。这种现象不能靠再改一次 SSID 名称解决。

拓扑:先用两条独立上联

本例采用独立的无标签以太网上联,不把 VLAN trunk 的配置混进来:

                       主路由
             ┌───────────┴───────────┐
          主网接口                  IoT 接口
       192.168.10.1/24          192.168.20.1/24
             │                       │
        一条主网上联              一条 IoT 上联
             │                       │
          小米 AP                  小米 AP
          br-lan                    br-iot
        ┌────┴────┐               ┌────┴────┐
     主网 SSID  主网有线口       IoT SSID  IoT 有线口

示例分配如下:

网络 网关由谁提供 AP 的角色
普通网络 192.168.10.0/24 主路由 192.168.10.1 br-lan;管理地址示例为 192.168.10.2
IoT 网络 192.168.20.0/24 主路由 192.168.20.1 br-iot;不配置管理 IP、网关或 DHCP
未来访客网络 192.168.30.0/24 主路由 192.168.30.1 另建 br-guest,另有对应上联

也可以经由管理型交换机的 access 端口接入,前提是两条线上确实属于不同的二层网络。把两根线都插进同一个普通 LAN,不能得到 IoT 隔离。 每个网桥先只接一条上联;没有配置链路聚合或环路控制时,不要把同一广播域的两条线同时接回上游。

这里不在 AP 上再次做 NAT,也不让 IoT 通过 AP 的主网管理地址绕回去上网。IoT 客户端直接从上游 IoT 网络获取地址,并以主路由的 IoT 地址为网关。

核对本机端口,不能照搬旧型号

本机 /etc/config/port_map 的映射是:

端口标签 Linux 接口 本例用途
第 1 个 2.5G eth2.2 普通网络
第 2 个 2.5G eth2.4 普通网络
第 3 个 2.5G eth2.3 IoT
第 4 个 2.5G eth2.5 IoT
第 1 个万兆,板级标签 5 eth1 普通网络
第 2 个万兆,板级标签 6 eth0 普通网络

2.5G 接口的顺序是 2、4、3、5,不是顺着接口后缀排列。本机还通过实际插线确认了第一个 2.5G 口对应 switch1 的物理端口 7、接口 eth2.2。其他端口采用本机板级映射,替换设备时仍应逐口验收。

只读检查:

cat /etc/config/port_map
ip link
brctl show
swconfig dev switch1 show

eth2.2 等接口使用的 VLAN 是原厂在内部交换机与 CPU 之间分拆物理端口的机制,不是本文定义的上联 VLAN 编号。保留原厂的 switch、switch_vlan 和端口映射配置,不要为了分成两个网络就删除这些段落,也不要把 CPU 接口 eth2 整体桥进去。

先备份,再进入 AP 模式

先从受控的有线管理连接操作,备份至少包括:

tar -czf /tmp/ap-before.tar.gz \
  /etc/config/network /etc/config/wireless /etc/config/dhcp \
  /etc/config/xiaoqiang /etc/config/port_map /etc/config/port_service \
  /etc/config/firewall /etc/crontabs/root
sha256sum /tmp/ap-before.tar.gz

把归档复制到电脑。/tmp 重启会清空,配置归档中也可能含有密码,不能把它当成公开教程附件。

先完成原厂有线 AP 模式切换,再配置自定义网桥。本文设备的状态应为:

uci -q get xiaoqiang.common.NETMODE
# lanapmode
uci -q get xiaoqiang.common.CAP_MODE
# ap

本机使用原厂 /usr/sbin/lanap_mode.sh open 完成模式切换;它不只是修改一个 UCI 字段,还会协调端口服务及其他原厂服务。自定义端口列表应在模式切换完成后设置,并由后文补丁保护。

AP 的 WAN 服务应处于关闭状态。本机涉及 network.wan.disabled、port_service.wan.enable、port_service.wan.wandt 和 port_service.wandt_attr.enable;存在第二 WAN 时也要检查它。不要仅改一个叫 LAN 的 IP,就认为已经完成 AP 模式切换。

配置期间先关闭各无线电,避免同名 SSID 把现有客户端吸引到尚未接上联的新 AP:

uci set wireless.wifi0.disabled='1'
uci set wireless.wifi1.disabled='1'
uci set wireless.wifi2.disabled='1'
uci commit wireless

网络配置:一个管理网桥,一个纯 IoT 网桥

下面是 /etc/config/network 中需要合并的核心结构,不是整份文件的替换内容。保留本机 MAC、交换机配置以及原厂需要的其他段落。

config interface 'lan'
        option type 'bridge'
        option ifname 'eth2.2 eth2.4 eth1 eth0'
        option proto 'static'
        option ipaddr '192.168.10.2'
        option netmask '255.255.255.0'
        option gateway '192.168.10.1'
        list dns '192.168.10.1'
        option force_link '1'

config interface 'iot'
        option type 'bridge'
        option ifname 'eth2.3 eth2.5'
        option proto 'none'
        option force_link '1'
        option bridge_empty '1'
        option ipv6 '0'

iot 的 proto 'none' 表示它承载二层转发,不在 AP 上充当 IoT 网关。这里的 ipv6 '0' 约束本接口的本机 IPv6 行为,不能把它理解为阻止网桥转发所有 IPv6 帧,更不能用它代替上游 IPv6 防火墙。

AP 不再自行分配客户端地址:

uci set dhcp.lan.ignore='1'
uci set dhcp.lan.miwifi_force_ignore='1'
uci set dhcp.lan.ra='disabled'
uci set dhcp.lan.dhcpv6='disabled'
uci set dhcp.lan.ndp='disabled'

uci set dhcp.iot='dhcp'
uci set dhcp.iot.interface='iot'
uci set dhcp.iot.ignore='1'
uci set dhcp.iot.ra='disabled'
uci set dhcp.iot.dhcpv6='disabled'
uci set dhcp.iot.ndp='disabled'
uci commit dhcp

同时检查原厂 miot 等其他网桥的地址分发设置;本例不启用它们,不保留额外的 DHCP/RA 服务。主网接口上原厂的 ip6assign 和独立 ULA 别名也不沿用为第二套路由配置。

管理地址只能有一套明确的归属。接入前检查 192.168.10.2 没有被其他设备使用;需要 DHCP 保留地址时,读取 AP 的 LAN MAC,不要误用 WAN MAC。

如果电脑采用双网卡调试,一张接现有主网,一张直连新 AP,就继续用原来的独立管理网段访问直连口。新 AP 上预设了目标管理 IP,不代表电脑会自动从正确的网卡访问它。临时管理别名应在正式上联确认后移除,不作为最终配置长期保留。

无线配置:SSID 绑定网络,频段只负责承载

“双 WiFi”在这里指两类逻辑网络,不等于只能建立两个 SSID。可以按需要让多个频段的普通 SSID 接到 lan,多个 IoT SSID 接到 iot。

本例已经启用的 BSS 如下:

无线配置中的 radio 普通网络 IoT 网络
wifi0,2.4GHz Main-24G,现有 wl1 IoT-24G,wl3
wifi1,5GHz Main-5G-L,现有 wl0 本例不新增
wifi2,5GHz Main-5G-H,现有 wl2 IoT-5G,wl4

以本机驱动的实际频段、可用 VAP 数量和接口占用为准。SSID 名称不能证明频段,两个 SSID 名字不同也不能证明网络已隔离。

新增 BSS 时,复制同一 radio 上已有的普通 AP 段落作为模板,保留原厂 QCA 驱动选项,再调整接口名、网络、SSID、密码和启用状态。IoT 段落的核心字段如下:

config wifi-iface 'ap_iot24'
        option device 'wifi0'
        option ifname 'wl3'
        option mode 'ap'
        option network 'iot'
        option ssid 'IoT-24G'
        option encryption 'psk2'
        option key 'REPLACE_WITH_YOUR_LONG_RANDOM_PASSWORD'
        option hidden '0'
        option bsd '0'
        option disabled '0'

config wifi-iface 'ap_iot5'
        option device 'wifi2'
        option ifname 'wl4'
        option mode 'ap'
        option network 'iot'
        option ssid 'IoT-5G'
        option encryption 'psk2'
        option key 'REPLACE_WITH_YOUR_LONG_RANDOM_PASSWORD'
        option hidden '0'
        option bsd '0'
        option disabled '0'

这里展示的是需要理解的字段,不是省略厂商选项后通用于所有 QCA 固件的完整配置。普通 BSS 的 network 保持 lan。新增 BSS 不复制原有 BSS 的 MAC,密码替换成自己的独立口令,接口名必须没有被其他服务占用。

为便于先验收独立 BSS,本例没有使用 MLO:删除 wifi-mld 段落及 BSS 的 mld 引用,关闭厂商合并 SSID 的 bsd,停用未使用的 Mesh 回程 BSS 和原厂隐藏 IoT BSS。不要把属于两个网络的 BSS 放进同一个 MLD;若后续重新启用 MLO,需要重新核对驱动、网络归属和客户端行为。

国家码、功率、信道及带宽保留本机原厂 radio 配置。这一轮不通过改变这些参数扩大改动范围。

让原厂端口服务从一开始就生成正确列表

RP04 的启动流程会重建端口归属:

/etc/init.d/port_service
  → /usr/sbin/port_service restart
  → port_map rebuild map
  → port_map rebuild network

/sbin/port_map 的 pm_rebuild_map() 会先把端口标记为 LAN,pm_rebuild_network() 再生成 network.lan.ifname。因此,需要在生成列表的位置排除已经分给 IoT 网桥的接口。

实际补丁只新增九行,包含注释和空行。其逻辑是:

# 在 pm_rebuild_network() 的局部变量之后增加:
local iot_ifnames=""

# Keep factory defaults unchanged when no custom AP IoT bridge exists.
if [ "$(uci -q get xiaoqiang.common.NETMODE)" = "lanapmode" ] &&
   [ "$(uci -q get network.iot.type)" = "bridge" ]; then
    iot_ifnames=$(uci -q get network.iot.ifname)
fi

# 在循环取得每个端口的 ifname 后增加:
# Ports assigned to the custom IoT bridge must not re-enter br-lan.
list_contains iot_ifnames "$ifname" && continue

这里保留了原厂的交换机、VLAN、内核端口映射和网络重载流程。没有自定义 IoT 网桥时,仍使用原厂生成列表的行为。

在电脑上生成替换文件

先通过 SCP 将路由器的 /sbin/port_map 保存为电脑上的 port_map.stock。下面的 Python 3 脚本在电脑上运行,不要求路由器安装 Python。

脚本只接受这台设备实测的原厂文件校验值;文件不同就停止,避免把行号补丁套到其他固件上。已经装过补丁的设备应先验证现有状态,不要反复覆盖。

from pathlib import Path
import hashlib

src = Path("port_map.stock").read_bytes()
expected = "a803db64c851ed36619b8e88730b70790890532cf1842bffb9095f4116c776d3"
assert hashlib.sha256(src).hexdigest() == expected, "原厂脚本版本不匹配"

text = src.decode("utf-8")
start = text.index("pm_rebuild_network() {")
end = text.index("pm_rebuild_proc() {", start)
part = text[start:end]

anchor = "    local ifname list_ifname_lan port ports\n"
assert part.count(anchor) == 1
part = part.replace(anchor, anchor + '''    local iot_ifnames=""

    # Keep factory defaults unchanged when no custom AP IoT bridge exists.
    if [ "$(uci -q get xiaoqiang.common.NETMODE)" = "lanapmode" ] &&
       [ "$(uci -q get network.iot.type)" = "bridge" ]; then
        iot_ifnames=$(uci -q get network.iot.ifname)
    fi
''', 1)

anchor = '        ifname=$(pm_config_get "$port" ifname)\n'
assert part.count(anchor) == 1
part = part.replace(anchor, anchor + '''        # Ports assigned to the custom IoT bridge must not re-enter br-lan.
        list_contains iot_ifnames "$ifname" && continue
''', 1)

out = (text[:start] + part + text[end:]).encode("utf-8")
expected_out = "150ac5a1b54958541c100e6581c6850d8f987f5ce462a6865cb9a0debb9960a7"
assert hashlib.sha256(out).hexdigest() == expected_out
Path("port_map.patched").write_bytes(out)
print("已生成 port_map.patched:", expected_out)

使用原厂 preinit 热补丁入口加载

本机的 /lib/preinit/91_mount_hotupgrade 会在普通启动服务之前扫描 /data/hotupgrade。状态文件为 0 的条目,会将 mountfile 内的文件绑定到相应系统路径,并将替换挂载设为只读。

利用这个现成入口,补丁布局为:

/etc/crontabs/patches/ap-port-map/
  port_map                         修改版脚本
  status                           内容为 0

/data/hotupgrade/ap-port-map-rp04/
  hotupgrade_status                → 上面的 status
  mountfile/sbin/port_map           → 上面的 port_map

先在路由器上创建私有目录,再用 SCP 上传电脑上生成的文件,保存为该目录下的 port_map:

mkdir -p /etc/crontabs/patches/ap-port-map
chmod 700 /etc/crontabs/patches/ap-port-map

上传后在路由器上执行以下首次安装步骤。若登记目录已经存在,应先检查现有登记,不直接合并其他内容:

set -e
BASE=/etc/crontabs/patches/ap-port-map
REG=/data/hotupgrade/ap-port-map-rp04

test ! -e "$REG"
test "$(sha256sum "$BASE/port_map" | cut -d ' ' -f 1)" = \
  '150ac5a1b54958541c100e6581c6850d8f987f5ce462a6865cb9a0debb9960a7'
sh -n "$BASE/port_map"
chmod 755 "$BASE/port_map"
printf '0\n' > "$BASE/status"
chmod 600 "$BASE/status"

mkdir -p "$REG/mountfile/sbin"
chmod 700 "$REG"
ln -s "$BASE/status" "$REG/hotupgrade_status"
ln -s "$BASE/port_map" "$REG/mountfile/sbin/port_map"

. /lib/miwifi/hotupgrade/hotupgrade_func.sh
hotupgrade_file_mount ap-port-map-rp04
sha256sum /sbin/port_map
grep ' /sbin/port_map ' /proc/mounts
sync

安装过程中没有向 MTD、UBI 固件卷、内核或启动分区写入镜像。原厂文件仍留在只读 SquashFS 中,运行时用配置区里的副本覆盖。

为什么重启保留,恢复出厂清除

本机的 /etc/crontabs 来自持久配置区,普通重启保留,恢复出厂时重建。这里不仅把修改版脚本放进去,还把 热补丁的状态文件放进去。

配置重建后,指向状态文件的符号链接失效。原厂 preinit 发现登记没有有效状态,就会清掉该登记,继续使用原厂文件。即使登记目录所在的数据层没有被同步清空,这个条件也能让它失效。

本次实际验证了普通重启后的挂载和端口列表;也在独立临时目录里调用原厂清理函数,验证“标记存在时保留、标记清除后删除登记”。本轮没有实际执行恢复出厂,不把模拟结果写成完整重置实测。

主路由上的策略,决定 IoT 能访问哪里

AP 接好了两个网络后,主路由需要有独立的 IoT 接口、DHCP 和防火墙 zone。本文不改变读者现有主路由规则,下面列的是需要实现并验收的策略:

流量 常见目标策略
主网 → Internet 保持现有策略
IoT → Internet 按设备需求允许
IoT → 主网 默认拒绝,仅按设备和端口设置必要例外
指定管理设备 → 指定 IoT 服务 显式允许,返回流量由连接跟踪处理
访客 → 主网、IoT、设备管理面 拒绝
访客 → Internet 按访客网络策略允许
IoT/访客 → 主路由自身 仅放行需要的 DHCP、DNS、必要 ICMP/ICMPv6 等服务

INPUT 管到路由器本机的访问,FORWARD 管经过路由器的跨网络流量,二者都需要检查。已有的宽泛 lan ↔ iot 转发也需要收敛,而不是只新增一条看起来更严格的规则。

IPv6 必须一起验收。只拒绝 IPv4 私网目的地址,不能阻止客户端通过 IPv6 访问内网;是否提供 IoT/访客 IPv6,以及如何分配前缀、处理 RA 和必要 ICMPv6,应由主路由统一决定。

本机原厂 AP 模式可能跳过 fw3 启动路径,因此不把小米上的防火墙 include 当作网络隔离成立的前提。摄像头发现、投屏等业务需要跨网发现时,在上游按协议处理,不能为了恢复发现功能就把两个网桥重新合并。

扩展访客网络:还要多一个独立出口

有了 lan 和 iot,扩展 guest 的结构相同,但至少要再落实三件事:

  1. 主路由提供独立的访客网段、地址分配及防火墙策略。
  2. AP 到上游有一条对应的物理上联,或完整配置的 VLAN trunk。
  3. 端口补丁同时排除访客端口,不能只保护 IoT。

例如,把第 2 个 2.5G 口从主网划给访客:

网桥 有线成员
br-lan eth2.2 eth1 eth0
br-iot eth2.3 eth2.5
br-guest eth2.4

guest 接口同样采用桥接、proto 'none'、不在 AP 上提供 DHCP/RA;新访客 BSS 的 network 指向 guest。VAP 名称和数量要按本机驱动确认,不随意占用原厂已有接口。

同时,将前面补丁的排除集合从单独的 IoT 扩展为两个桥。下面是替代逻辑示意,不是往原补丁末尾再追加一次:

local isolated_ifnames=""
if [ "$(uci -q get xiaoqiang.common.NETMODE)" = "lanapmode" ]; then
    for net in iot guest; do
        [ "$(uci -q get network.$net.type)" = "bridge" ] || continue
        append isolated_ifnames "$(uci -q get network.$net.ifname)"
    done
fi

# 在端口循环取得 ifname 之后:
list_contains isolated_ifnames "$ifname" && continue

扩展后替换文件的 SHA256 会改变,不能继续使用前面“双网络版本”的输出校验值。应重新做语法、生成列表和重启验收,再更新热补丁文件。

如果希望访客客户端彼此也受限制,可以评估 BSS 的 isolate 选项;它不能替代访客与主网之间的防火墙,也不能据此保证跨频段、跨 AP 或有线访客之间都隔离。

第三个 SSID 如果仍绑定 lan,不会自动变成访客网络。只有一条普通无标签上联时,也不能凭空承载三个独立广播域;要么增加独立上联,要么另行设计并验证 trunk。本篇不把内部端口映射的 VLAN 编号直接拿来当 trunk 配置。

替换设备与验收顺序

本机已经完成接线上线和无线启用。下面保留可复用的操作顺序,并在末尾按实际记录列出验证范围。

先验收有线,暂不广播同名 WiFi

  1. 记录旧 AP 的接线和管理地址,保留回退方式。
  2. 确认新 AP 管理地址未占用,再断开旧 AP 对应上联。
  3. 新 AP 的主网口接主网上联,IoT 口接 IoT 上联,每组先各一条。
  4. 从主网确认新 AP 的管理地址可达。
  5. 分别在两组有线端口接测试客户端,检查地址、网关、DNS 和可访问范围。

在 AP 上检查配置与实际成员:

uci -q get network.lan.ifname
uci -q get network.iot.ifname
brctl show
ip -4 addr show dev br-lan
ip -4 addr show dev br-iot
sha256sum /sbin/port_map
grep ' /sbin/port_map ' /proc/mounts

无线关闭阶段,预期 br-lan 包含四个主网有线接口,br-iot 包含两个 IoT 有线接口;无线启用后还会加入对应 VAP,不能把这些无线成员误判为多余端口。AP 的 IoT 桥不应出现一套独立网关地址。测试客户端的 DHCP 应来自各自上游。

再启用无线并验证客户端

上联与有线验证通过后,才启用无线:

uci set wireless.wifi0.disabled='0'
uci set wireless.wifi1.disabled='0'
uci set wireless.wifi2.disabled='0'
uci commit wireless
ubus call network reload
/sbin/wifi reload_legacy

本机已经执行上述步骤,并在 hostapd 状态中确认五个 BSS 均为 ENABLED。三个主网 VAP wl0/wl1/wl2 加入 br-lan,两个 IoT VAP wl3/wl4 加入 br-iot。这验证了无线启动和桥接归属;客户端地址、上网和跨网权限仍应按下文分别检查。

正式管理地址确认可达后,删除调试时的临时别名。本机已完成这一步,主网桥仅保留目标管理 IPv4 地址:

uci -q delete network.ap_staging
uci commit network
ubus call network reload

此处假定临时段落名称为 ap_staging,且已经通过正式地址建立管理连接;不要从唯一可用的临时连接直接删除自己的管理入口。

验收不只测 ping:还要测试 IoT/访客能否访问 NAS、路由器管理页和其他受限服务,允许的业务是否可用,以及 IPv6 是否符合相同策略。

必要时观察两个网桥上的 ARP、DHCP 流量:

tcpdump -ni br-lan 'arp or (udp and (port 67 or port 68))'
tcpdump -ni br-iot 'arp or (udp and (port 67 or port 68))'

这能辅助定位,不能单靠 AP 上的抓包或 brctl 输出认定隔离成功。交换芯片硬件转发可能不经过 CPU,最终还需要在两侧终端测试广播是否串网、不同端口是否拿到错误网段地址,以及跨网访问是否受策略约束。

最后再重启一次

重启前后记录 boot_id:

cat /proc/sys/kernel/random/boot_id
uptime

确认确实重启后,再次核对替换挂载、端口列表、实际网桥、地址分配和客户端访问范围。固件升级、重新配置原厂 Mesh 或通过原厂界面大幅修改网络后,也需要重新核对这份定制配置,不能把一次重启成功当成所有状态变更都已覆盖。

文件级 diff:具体改了什么(已脱敏)

这一节以上一篇 Root/SSH 已完成、路由器已初始化,但尚未配置这套 AP 网络时的备份为基线,对照启用五个 SSID、移除临时管理地址后的上线快照(2026-11-01 只读复核)。它不是与“从未 root 的出厂设备”比较,也不重复计算上一篇的 bdata 和 SSH 改动。访客网络尚未部署,不混入实际 diff。

为便于核对,下面保留每份实际变更配置文件的完整原内容,再给出 unified diff;- 是修改前,+ 是修改后,未列入差异的行保留原值。新增文件的原状态是“不存在”。

脱敏约定: 原厂/临时管理网络统一用 192.168.50.0/24 表示,目标主网用 192.168.10.0/24;其他本地网络也映射为示例网段。SSID 替换为 Xiaomi_Default、Main-*、IoT-* 等示例,密码用 <SECRET_BEFORE> / <SECRET_AFTER> 占位,MAC 使用 02:00:00:00:00:xx 示例值,设备名称、标识和位置同样隐藏。占位符不用于判断不同字段的真实密码是否相同。掩码、回环地址和布尔开关保留。

这些内容用于审阅变更,不是可直接恢复到设备的备份。复制配置时仍需填写自己的地址、MAC、SSID、口令,并保留本机板级配置。

改动索引

文件或路径 原状态 本篇最终改动
/etc/config/network 原厂单 LAN 与 WAN 配置 主网端口分组、IoT 纯网桥、管理地址/网关/DNS、禁用 WAN;上线时已移除临时管理别名
/etc/config/wireless 原厂普通 BSS、MLO、Mesh/隐藏 BSS 迁移三个普通 SSID、增加两个 IoT BSS、取消 MLD 引用和 SSID 合并,停用未用 BSS;三个无线电均已开启
/etc/config/dhcp 原厂 LAN 地址分发设置 关闭本机 LAN/IoT/miot 的 DHCP、RA、DHCPv6/NDP 服务
/etc/config/xiaoqiang 原厂路由模式 NETMODE=lanapmode、CAP_MODE=ap
/etc/config/port_service WAN 自动选择开启 关闭 WAN 服务和自动 WAN 选择
/etc/crontabs/root 已包含上一篇的 SSH 保持任务 原厂 AP 模式增加 lanap_mode.sh check_gw;没有增加端口纠正任务
/etc/crontabs/patches/ap-port-map/port_map 不存在 原厂 /sbin/port_map 的副本,仅新增 9 行筛选逻辑
同目录 status 不存在 内容为 0,供原厂 preinit 判断启用状态
同目录 manifest.json、rollback.sh 不存在 版本/校验记录与手动回滚工具,不自动执行
/data/hotupgrade/ap-port-map-rp04/ 下两个链接 不存在 将原厂热补丁登记指向配置区里的状态和替换文件
运行时 /sbin/port_map 只读 ROM 文件 由原厂入口绑定替换;ROM 中的原文件没有被覆写

上线前曾使用 ap_staging 保留直连管理;它已经删除,不出现在最终 diff 的新增项中。三个无线电已恢复 disabled=0,与基线相同的开关不会产生差异;未用的隐藏和 Mesh BSS 仍关闭。

/etc/config/network

这里的接口顺序只表达成员集合。iot 不设置自己的网关地址;临时管理别名已删除。两个 Docker 网桥等原有段落没有被删除。

修改前:完整脱敏原内容 ```uci config device 'eth0_dev' option name 'eth0' config device 'eth1_dev' option name 'eth1' config device 'eth2_dev' option name 'eth2' config interface 'loopback' option ifname 'lo' option proto 'static' option ipaddr '127.0.0.1' option netmask '255.0.0.0' config switch 'switch0' option name 'switch0' config switch 'switch1' option name 'switch1' option enable_vlan '1' config interface 'lan' option ifname 'eth2.2 eth2.4 eth2.3 eth2.5 eth1 eth0' option force_link '1' option type 'bridge' option proto 'static' option ipaddr '192.168.50.1' option netmask '255.255.255.0' option multicast_querier '0' option igmp_snooping '0' option ip6assign '64' option macaddr '02:00:00:00:00:08' config alias 'lan_ipv6_alias' option interface 'lan' option proto 'static' option ip6addr 'fd00:50::1' config interface option ifname 'eth0' option keepup '1' config interface 'eth1' option ifname 'eth1' config interface 'eth2' option ifname 'eth2' config interface 'wan' option proto 'dhcp' option ipv6 '1' option wantype 'eth' option macaddr '02:00:00:00:00:01' config interface 'wan_2' option disabled '1' option proto 'dhcp' option ipv6 '0' option wantype 'eth' option macaddr '02:00:00:00:00:09' config interface 'miot' option ifname 'wl13' option type 'bridge' option bridge_empty '1' option proto 'static' option ipaddr '192.168.60.1' option netmask '255.255.255.0' config switch_vlan 'switch1_vlan1' option device 'switch1' option ports '3 4 5 6 7' option vlan '1' option vid '1' config interface 'docker1' option type 'bridge' option bridge_empty '1' option force_link '1' option proto 'static' option ipaddr '172.22.0.1' option netmask '255.255.0.0' config interface 'docker' option type 'bridge' option bridge_empty '1' option force_link '1' option proto 'static' option ipaddr '172.21.0.1' option netmask '255.255.0.0' config switch_vlan 'vlan2' option device 'switch1' option ports '7 3t' option vlan '2' option vid '2' config interface 'eth2_2' option ifname 'eth2.2' config switch_vlan 'vlan4' option device 'switch1' option ports '5 3t' option vlan '4' option vid '4' config interface 'eth2_4' option ifname 'eth2.4' config switch_vlan 'vlan3' option device 'switch1' option ports '6 3t' option vlan '3' option vid '3' config interface 'eth2_3' option ifname 'eth2.3' config switch_vlan 'vlan5' option device 'switch1' option ports '4 3t' option vlan '5' option vid '5' config interface 'eth2_5' option ifname 'eth2.5' ```
实际变更:脱敏 unified diff ```diff --- before/etc/config/network +++ after/etc/config/network @@ -22,21 +22,17 @@ option enable_vlan '1' config interface 'lan' - option ifname 'eth2.2 eth2.4 eth2.3 eth2.5 eth1 eth0' + option ifname 'eth2.2 eth2.4 eth1 eth0' option force_link '1' option type 'bridge' option proto 'static' - option ipaddr '192.168.50.1' + option ipaddr '192.168.10.2' option netmask '255.255.255.0' option multicast_querier '0' option igmp_snooping '0' - option ip6assign '64' option macaddr '02:00:00:00:00:08' - -config alias 'lan_ipv6_alias' - option interface 'lan' - option proto 'static' - option ip6addr 'fd00:50::1' + option gateway '192.168.10.1' + list dns '192.168.10.1' config interface option ifname 'eth0' @@ -53,6 +49,7 @@ option ipv6 '1' option wantype 'eth' option macaddr '02:00:00:00:00:01' + option disabled '1' config interface 'wan_2' option disabled '1' @@ -127,3 +124,11 @@ config interface 'eth2_5' option ifname 'eth2.5' +config interface 'iot' + option type 'bridge' + option ifname 'eth2.3 eth2.5' + option proto 'none' + option force_link '1' + option bridge_empty '1' + option ipv6 '0' + ```

/etc/config/wireless

原始文件包含原厂隐藏 BSS 和 MLD 配置,所以原内容较长。新增 IoT 段落来自同 radio 的模板;未改动的驱动字段保留。<SECRET_*> 只是脱敏标记,不是实际口令。三个无线电已开启;五个 BSS 的启用状态和网桥归属另列于验收结果,配置 diff 本身不代替客户端隔离测试。

修改前:完整脱敏原内容 ```uci config wifi-device 'wifi0' option type 'qcawificfg80211' option channel 'auto' option macaddr '02:00:00:00:00:0a' option hwmode '11beg' option htmode 'HT40' option country 'CN' option disabled '0' option txpwr 'max' option txbf '3' option ax '1' option bw '0' config wifi-iface option device 'wifi0' option ifname 'wl1' option network 'lan' option mode 'ap' option ssid 'Xiaomi_Default' option encryption 'psk2' option wpsdevicename 'XiaoMiRouter' option he_ul_ofdma '0' option twt_responder '0' option mscs '1' option hlos_tidoverride '1' option amsdu '2' option wnm '1' option rrm '1' option miwifi_mesh '0' option wscconfigstatus '2' option disabled '0' option bsd '1' option key '' option mld 'hostap_mld0' config wifi-device 'wifi1' option type 'qcawificfg80211' option channel 'auto' option macaddr '02:00:00:00:00:0b' option hwmode '11bea' option htmode 'HT80' option country 'CN' option disabled '0' option txpwr 'max' option txbf '3' option ax '1' option bw '80' option CSwOpts '0x31' config wifi-iface option device 'wifi1' option ifname 'wl0' option network 'lan' option mode 'ap' option ssid 'Xiaomi_Default' option encryption 'psk2' option wpsdevicename 'XiaoMiRouter' option he_ul_ofdma '0' option twt_responder '0' option mscs '1' option hlos_tidoverride '1' option channel_block_list '52,56,60,64,100,104,108,112,116,120,124,128,132,136,140' option miwifi_mesh '0' option wnm '1' option rrm '1' option wscconfigstatus '2' option disabled '0' option bsd '1' option key '' option mld 'hostap_mld0' config wifi-iface 'miot_2G' option ifname 'wl13' option network 'miot' option encryption 'none' option device 'wifi0' option mode 'ap' option hidden '1' option maxsta '20' option ssid 'Factory_Hidden_1' option bsd '0' option disabled '0' option ap_isolate '1' option userswitch '1' config wifi-device 'wifi2' option type 'qcawificfg80211' option channel 'auto' option macaddr '02:00:00:00:00:0c' option hwmode '11bea' option htmode 'HT80' option country 'CN' option disabled '0' option txpwr 'max' option txbf '3' option ax '1' option bw '80' option CSwOpts '0x31' config wifi-iface option device 'wifi2' option ifname 'wl2' option network 'lan' option mode 'ap' option ssid 'Xiaomi_Default' option encryption 'psk2' option wpsdevicename 'XiaoMiRouter' option he_ul_ofdma '0' option twt_responder '0' option mscs '1' option hlos_tidoverride '1' option channel_block_list '52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,165' option miwifi_mesh '0' option wnm '1' option rrm '1' option disabled '0' option bsd '1' option key '' option mld 'hostap_mld0' config wifi-mld 'hostap_mld0' option mlo_enable '1' option mld_macaddr '02:00:00:00:00:0d' config wifi-iface 'bh_ap_5g' option device 'wifi1' option ifname 'wl5' option network 'lan' option mode 'ap' option channel_block_list '52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,165' option ssid 'Factory_Hidden_2' option encryption 'psk2' option key '' option hidden '1' option backhaul '1' option backhaul_ap '1' option wds '1' option wps_pbc '1' option wps_pbc_enable '0' option wps_pbc_start_time '0' option wps_pbc_duration '120' option group '0' option athnewind '1' option mesh_apmac '02:00:00:00:00:08' option mesh_aplimit '9' option mesh_ver '4' option miwifi_mesh '0' option sae '1' option sae_password '' option ieee80211w '1' option macaddr '02:00:00:00:00:04' option mld 'bhap_mld0' option disabled '0' config wifi-iface 'bh_ap_5gh' option device 'wifi2' option ifname 'wl7' option network 'lan' option mode 'ap' option channel_block_list '52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,165' option ssid 'Factory_Hidden_2' option encryption 'psk2' option key '' option hidden '1' option backhaul '1' option backhaul_ap '1' option wds '1' option wps_pbc '1' option wps_pbc_enable '0' option wps_pbc_start_time '0' option wps_pbc_duration '120' option group '0' option athnewind '1' option mesh_apmac '02:00:00:00:00:08' option mesh_aplimit '9' option mesh_ver '4' option miwifi_mesh '0' option sae '1' option sae_password '' option ieee80211w '1' option macaddr '02:00:00:00:00:05' option mld 'bhap_mld0' option disabled '0' config wifi-mld 'bhap_mld0' option mld_macaddr '02:00:00:00:00:0e' option mld_ssid 'Factory_Hidden_2' config wifi-mld 'bhsta_mld0' option role 'Non-AP' option mld_macaddr '02:00:00:00:00:02' config wifi-iface 'iot_2g' option device 'wifi0' option ifname 'wl17' option network 'lan' option encryption 'mixed-psk' option mode 'ap' option hidden '0' option disabled '1' option iotwifi5mode '1' option macaddr '02:00:00:00:00:06' config wifi-iface 'iot_5g' option device 'wifi1' option ifname 'wl16' option network 'lan' option encryption 'mixed-psk' option mode 'ap' option hidden '0' option disabled '1' option iotwifi5mode '1' option macaddr '02:00:00:00:00:07' ```
实际变更:脱敏 unified diff ```diff --- before/etc/config/wireless +++ after/etc/config/wireless @@ -17,7 +17,7 @@ option ifname 'wl1' option network 'lan' option mode 'ap' - option ssid 'Xiaomi_Default' + option ssid 'Main-24G' option encryption 'psk2' option wpsdevicename 'XiaoMiRouter' option he_ul_ofdma '0' @@ -30,9 +30,8 @@ option miwifi_mesh '0' option wscconfigstatus '2' option disabled '0' - option bsd '1' - option key '' - option mld 'hostap_mld0' + option bsd '0' + option key '' config wifi-device 'wifi1' option type 'qcawificfg80211' @@ -53,7 +52,7 @@ option ifname 'wl0' option network 'lan' option mode 'ap' - option ssid 'Xiaomi_Default' + option ssid 'Main-5G-L' option encryption 'psk2' option wpsdevicename 'XiaoMiRouter' option he_ul_ofdma '0' @@ -66,9 +65,8 @@ option rrm '1' option wscconfigstatus '2' option disabled '0' - option bsd '1' - option key '' - option mld 'hostap_mld0' + option bsd '0' + option key '' config wifi-iface 'miot_2G' option ifname 'wl13' @@ -80,7 +78,7 @@ option maxsta '20' option ssid 'Factory_Hidden_1' option bsd '0' - option disabled '0' + option disabled '1' option ap_isolate '1' option userswitch '1' @@ -103,25 +101,20 @@ option ifname 'wl2' option network 'lan' option mode 'ap' - option ssid 'Xiaomi_Default' - option encryption 'psk2' - option wpsdevicename 'XiaoMiRouter' - option he_ul_ofdma '0' - option twt_responder '0' - option mscs '1' - option hlos_tidoverride '1' - option channel_block_list '52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,165' - option miwifi_mesh '0' - option wnm '1' - option rrm '1' - option disabled '0' - option bsd '1' - option key '' - option mld 'hostap_mld0' - -config wifi-mld 'hostap_mld0' - option mlo_enable '1' - option mld_macaddr '02:00:00:00:00:0d' + option ssid 'Main-5G-H' + option encryption 'psk2' + option wpsdevicename 'XiaoMiRouter' + option he_ul_ofdma '0' + option twt_responder '0' + option mscs '1' + option hlos_tidoverride '1' + option channel_block_list '52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,165' + option miwifi_mesh '0' + option wnm '1' + option rrm '1' + option disabled '0' + option bsd '0' + option key '' config wifi-iface 'bh_ap_5g' option device 'wifi1' @@ -150,8 +143,7 @@ option sae_password '' option ieee80211w '1' option macaddr '02:00:00:00:00:04' - option mld 'bhap_mld0' - option disabled '0' + option disabled '1' config wifi-iface 'bh_ap_5gh' option device 'wifi2' @@ -180,16 +172,7 @@ option sae_password '' option ieee80211w '1' option macaddr '02:00:00:00:00:05' - option mld 'bhap_mld0' - option disabled '0' - -config wifi-mld 'bhap_mld0' - option mld_macaddr '02:00:00:00:00:0e' - option mld_ssid 'Factory_Hidden_2' - -config wifi-mld 'bhsta_mld0' - option role 'Non-AP' - option mld_macaddr '02:00:00:00:00:02' + option disabled '1' config wifi-iface 'iot_2g' option device 'wifi0' @@ -213,3 +196,46 @@ option iotwifi5mode '1' option macaddr '02:00:00:00:00:07' +config wifi-iface 'ap_iot24' + option device 'wifi0' + option ifname 'wl3' + option network 'iot' + option mode 'ap' + option ssid 'IoT-24G' + option encryption 'psk2' + option wpsdevicename 'XiaoMiRouter' + option he_ul_ofdma '0' + option twt_responder '0' + option mscs '1' + option hlos_tidoverride '1' + option amsdu '2' + option wnm '1' + option rrm '1' + option miwifi_mesh '0' + option wscconfigstatus '2' + option disabled '0' + option bsd '0' + option key '' + option hidden '0' + +config wifi-iface 'ap_iot5' + option device 'wifi2' + option ifname 'wl4' + option network 'iot' + option mode 'ap' + option ssid 'IoT-5G' + option encryption 'psk2' + option wpsdevicename 'XiaoMiRouter' + option he_ul_ofdma '0' + option twt_responder '0' + option mscs '1' + option hlos_tidoverride '1' + option channel_block_list '52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,165' + option miwifi_mesh '0' + option wnm '1' + option rrm '1' + option disabled '0' + option bsd '0' + option key '' + option hidden '0' + ```

/etc/config/dhcp

这是 AP 本机的服务设置;主路由的 DHCP、IPv6 与防火墙规则不在这份 diff 中。

修改前:完整脱敏原内容 ```uci config dnsmasq option domainneeded '1' option boguspriv '1' option filterwin2k '0' option localise_queries '1' option rebind_protection '0' option rebind_localhost '1' option local '/lan/' option expandhosts '1' option nonegcache '0' option authoritative '1' option allservers '1' option readethers '1' option leasefile '/tmp/dhcp.leases' option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto' option nonwildcard '1' option localservice '1' config dhcp 'lan' option interface 'lan' option start '5' option limit '250' option leasetime '12h' option force '1' option ra_default '1' option dhcpv6 'server' option ra 'server' option ra_preference 'high' option ra_maxinterval '20' option ra_lifetime '1800' list ra_flags 'managed-config' list ra_flags 'other-config' config dhcp 'wan' option interface 'wan' option ignore '1' config dhcp 'wan_2' option interface 'wan_2' option ignore '1' config dhcp 'miot' option interface 'miot' option start '10' option limit '200' option leasetime '1h' option force '1' config odhcpd 'odhcpd' option maindhcp '0' option leasefile '/tmp/hosts/odhcpd' option leasetrigger '/usr/sbin/odhcpd-update' option loglevel '4' ```
实际变更:脱敏 unified diff ```diff --- before/etc/config/dhcp +++ after/etc/config/dhcp @@ -1,4 +1,3 @@ - config dnsmasq option domainneeded '1' option boguspriv '1' @@ -24,11 +23,14 @@ option leasetime '12h' option force '1' option ra_default '1' - option dhcpv6 'server' - option ra 'server' + option dhcpv6 'disabled' + option ra 'disabled' option ra_preference 'high' option ra_maxinterval '20' option ra_lifetime '1800' + option ignore '1' + option ndp 'disabled' + option miwifi_force_ignore '1' list ra_flags 'managed-config' list ra_flags 'other-config' @@ -46,6 +48,10 @@ option limit '200' option leasetime '1h' option force '1' + option ignore '1' + option ra 'disabled' + option dhcpv6 'disabled' + option ndp 'disabled' config odhcpd 'odhcpd' option maindhcp '0' @@ -53,3 +59,10 @@ option leasetrigger '/usr/sbin/odhcpd-update' option loglevel '4' +config dhcp 'iot' + option interface 'iot' + option ignore '1' + option ra 'disabled' + option dhcpv6 'disabled' + option ndp 'disabled' + ```

/etc/config/xiaoqiang

只改变工作模式字段;设备身份和位置字段在两侧使用相同占位符,没有借脱敏制造额外变更。

修改前:完整脱敏原内容 ```uci config core 'common' option CONFIGURED 'YES' option bhap_enable '0' option NETWORK_ID '' option NETMODE 'whc_cap' option MESH_VERSION '4' option INITTED 'YES' option ROUTER_NAME '' option ROUTER_NAME_PENDING '1' option ROUTER_LOCALE '' option sp_enable '0' ```
实际变更:脱敏 unified diff ```diff --- before/etc/config/xiaoqiang +++ after/etc/config/xiaoqiang @@ -1,13 +1,13 @@ - config core 'common' option CONFIGURED 'YES' option bhap_enable '0' option NETWORK_ID '' - option NETMODE 'whc_cap' + option NETMODE 'lanapmode' option MESH_VERSION '4' option INITTED 'YES' option ROUTER_NAME '' option ROUTER_NAME_PENDING '1' option ROUTER_LOCALE '' option sp_enable '0' + option CAP_MODE 'ap' ```

/etc/config/port_service

关闭的是 WAN 服务与自动探测,没有删除原厂端口初始化逻辑,也没有改写板级端口映射。

修改前:完整脱敏原内容 ```uci config common 'settings' option router_services 'game lag iptv wan wan_2' option ap_services 'lag' config service 'wan' option enable '1' option wandt '1' option type 'eth' option link_mode '0' config service 'wan_2' option enable '0' option wandt '0' option type 'eth' config service 'lag' option enable '0' config service 'iptv' option enable '0' config service 'game' option enable '0' config attr 'wandt_attr' option log_level '6' option detect_times '-1' option detect_interval '4000' option send_times '2' option send_interval '2000' option ports '1 2 3 4 5 6' option enable '1' option mac '02:00:00:00:00:01' config attr 'iptv_attr' option vid '-1' option priority '-1' option profile '0' option permit_vid '2~4094' option wan_egress_tag '1' option lan_egress_tag '0' config attr 'lag_attr' option mode '2' ```
实际变更:脱敏 unified diff ```diff --- before/etc/config/port_service +++ after/etc/config/port_service @@ -1,11 +1,10 @@ - config common 'settings' option router_services 'game lag iptv wan wan_2' option ap_services 'lag' config service 'wan' - option enable '1' - option wandt '1' + option enable '0' + option wandt '0' option type 'eth' option link_mode '0' @@ -30,7 +29,7 @@ option send_times '2' option send_interval '2000' option ports '1 2 3 4 5 6' - option enable '1' + option enable '0' option mac '02:00:00:00:00:01' config attr 'iptv_attr' ```

/etc/crontabs/root

ssh_patch.sh 在基线里已经存在,来自上一篇。本篇新增的 check_gw 是原厂 AP 网关检查,不是定时把 IoT 端口移出主网的脚本。

修改前:完整脱敏原内容 ```text */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 */6 * * * command -v sec_cfg_bak.sh >/dev/null && sec_cfg_bak.sh * * * * * run-parts -a 1min /etc/periodic */5 * * * * run-parts -a 5min /etc/periodic */10 * * * * run-parts -a 10min /etc/periodic */15 * * * * run-parts -a 15min /etc/periodic 3 * * * * run-parts -a hourly /etc/periodic 6 1 * * * run-parts -a daily /etc/periodic */1 * * * * /etc/crontabs/patches/ssh_patch.sh >/dev/null 2>&1 ```
实际变更:脱敏 unified diff ```diff --- before/etc/crontabs/root +++ after/etc/crontabs/root @@ -13,3 +13,4 @@ 3 * * * * run-parts -a hourly /etc/periodic 6 1 * * * run-parts -a daily /etc/periodic */1 * * * * /etc/crontabs/patches/ssh_patch.sh >/dev/null 2>&1 +*/1 * * * * /usr/sbin/lanap_mode.sh check_gw ```

/sbin/port_map 与新增的替换副本

原厂 /sbin/port_map 的闪存原件未改。新增文件 /etc/crontabs/patches/ap-port-map/port_map 是它的副本,运行时通过只读绑定挂载覆盖原路径。下面给出原函数和完整补丁差异;其余函数逐字保留,不重复整份原厂脚本。替换文件的完整内容可以由前文生成器重建,并核对 SHA256。

原始 pm_rebuild_network():修改前完整函数 ```sh pm_rebuild_network() { local vlan_type last_vlan_type local ifname list_ifname_lan port ports # # vlan type changed, must reconfig network vlan_type=$(pm_config_get settings vlan_type) last_vlan_type=$(pm_config_get settings last_vlan_type) [ -n "$vlan_type" ] && [ "$vlan_type" != "$last_vlan_type" ] && { pm_clean_network "$vlan_type" pm_build_network "$vlan_type" pm_config_set settings last_vlan_type "$vlan_type" } # reconfig network.lan.ifname ports=$(pm_collect_port class lan) for port in $ports; do [ "cpe" = "$(pm_config_get "$port" type)" ] && continue ifname=$(pm_config_get "$port" ifname) if [ "lag" = "$(pm_config_get "$port" service)" ]; then uci batch <<-EOF set network."${ifname//./_}".force_link="1" commit network EOF else list_contains list_ifname_lan "$ifname" || append list_ifname_lan "$ifname" fi done uci batch <<-EOF set network.lan.ifname="$list_ifname_lan" commit network EOF ubus call network reload pm_extra_rebuild_network return } ```
原厂脚本 → 配置区替换副本:全部 9 行增量 ```diff --- ROM/sbin/port_map +++ config/etc/crontabs/patches/ap-port-map/port_map @@ -135,6 +135,13 @@ pm_rebuild_network() { local vlan_type last_vlan_type local ifname list_ifname_lan port ports + local iot_ifnames="" + + # Keep factory defaults unchanged when no custom AP IoT bridge exists. + if [ "$(uci -q get xiaoqiang.common.NETMODE)" = "lanapmode" ] && + [ "$(uci -q get network.iot.type)" = "bridge" ]; then + iot_ifnames=$(uci -q get network.iot.ifname) + fi # # vlan type changed, must reconfig network vlan_type=$(pm_config_get settings vlan_type) @@ -151,6 +158,8 @@ [ "cpe" = "$(pm_config_get "$port" type)" ] && continue ifname=$(pm_config_get "$port" ifname) + # Ports assigned to the custom IoT bridge must not re-enter br-lan. + list_contains iot_ifnames "$ifname" && continue if [ "lag" = "$(pm_config_get "$port" service)" ]; then uci batch <<-EOF set network."${ifname//./_}".force_link="1" ```

其他新增文件:原状态均为不存在

这些文件不包含设备密码。manifest.json 和 rollback.sh 不参与自动启动;真正被原厂入口读取的是 status 和替换脚本。

/etc/crontabs/patches/ap-port-map/status

新增后的完整内容(原文件不存在) ```text 0 ```

/etc/crontabs/patches/ap-port-map/manifest.json

新增后的完整内容(原文件不存在) ```json { "model": "RP04", "firmware": "1.0.70", "factory_sha256": "a803db64c851ed36619b8e88730b70790890532cf1842bffb9095f4116c776d3", "patched_sha256": "150ac5a1b54958541c100e6581c6850d8f987f5ce462a6865cb9a0debb9960a7", "persistent_file": "/etc/crontabs/patches/ap-port-map/port_map", "native_preinit_entry": "/lib/preinit/91_mount_hotupgrade", "factory_reset": "status and replacement reside in resettable crontabs storage; native preinit removes registration if status disappears", "scope": "AP mode with explicit network.iot bridge only" } ```

/etc/crontabs/patches/ap-port-map/rollback.sh

新增后的完整内容(原文件不存在) ```sh #!/bin/sh set -e umount /sbin/port_map 2>/dev/null || true test "$(readlink -f /data/hotupgrade/ap-port-map-rp04)" = /data/hotupgrade/ap-port-map-rp04 rm /data/hotupgrade/ap-port-map-rp04/mountfile/sbin/port_map /data/hotupgrade/ap-port-map-rp04/hotupgrade_status rmdir /data/hotupgrade/ap-port-map-rp04/mountfile/sbin /data/hotupgrade/ap-port-map-rp04/mountfile /data/hotupgrade/ap-port-map-rp04 echo AP_port_map_patch_disabled ```

两个新增登记链接

下面是链接内容,不是把脚本复制进 ROM,也不是新增开机服务:

--- /dev/null
+++ /data/hotupgrade/ap-port-map-rp04/hotupgrade_status (symlink)
+ -> /etc/crontabs/patches/ap-port-map/status
--- /dev/null
+++ /data/hotupgrade/ap-port-map-rp04/mountfile/sbin/port_map (symlink)
+ -> /etc/crontabs/patches/ap-port-map/port_map

没有改动的部分

  • /etc/config/firewall、/etc/config/port_map:与 AP 配置前的基线逐字一致。现有 SSH 防火墙 include 来自前篇,本篇没有再给 AP 添加一套 IoT 路由防火墙。
  • /etc/init.d/port_service、/etc/init.d/dnsmasq、/etc/init.d/firewall、/etc/init.d/network、/etc/rc.local、/etc/dnsmasq.conf:审计时与原厂内容逐字一致,没有新增启动脚本段落。
  • 原厂 preinit、内核、只读 rootfs 和板级 VLAN 配置没有改写;bdata 保持前篇 Root 后的状态,不属于本篇的新增改动。
  • 既有 SSH 保持脚本、主机密钥及 Dropbear 配置沿用前篇,不在此公开密钥或重复安装。
  • 未在主路由、旧 AP 上执行配置写入。访客网络及其补丁扩展仍是前文的后续方案。

“最小改动”限定的是:保留既有 Root 入口,并满足本篇 AP 分网与正式管理需求。九行指的是系统端口生成逻辑的增量,不是声称整套 AP 配置总共只改九行。

回滚与本次验证范围

手动停用本文登记时,先卸载替换挂载,删除本次建立的两个链接和空目录即可。下面不清空 AP 配置,也不执行恢复出厂:

set -e
umount /sbin/port_map
rm /data/hotupgrade/ap-port-map-rp04/mountfile/sbin/port_map \
   /data/hotupgrade/ap-port-map-rp04/hotupgrade_status
rmdir /data/hotupgrade/ap-port-map-rp04/mountfile/sbin \
      /data/hotupgrade/ap-port-map-rp04/mountfile \
      /data/hotupgrade/ap-port-map-rp04

停用后,下次原厂重建端口列表会恢复原逻辑;是否同时恢复旧的 network、wireless 等配置,需要按回退目标决定,不能把停用补丁等同于整机配置回滚。

上线后的实际网桥

2026-11-01 的只读复核与上线记录一致:

br-lan: eth0 eth1 eth2.2 eth2.4 wl0 wl1 wl2
br-iot: eth2.3 eth2.5 wl3 wl4
wifi0/wifi1/wifi2: disabled=0
network.ap_staging: 不存在
/sbin/port_map SHA256:
150ac5a1b54958541c100e6581c6850d8f987f5ce462a6865cb9a0debb9960a7

无线启用记录中,五个 BSS 的状态均为 ENABLED;只读复核也确认五个 VAP 仍存在。万兆口已经分别协商到 10Gbps 和 5Gbps。本文不把这些结果延伸为所有客户端、所有网口和所有访问策略均已验收。

本次的验证结果如下:

项目 状态
原厂端口服务实际重建后保持主网/IoT 分组 已验证
普通重启后原厂 preinit 自动挂载替换文件 已验证
配置列表与实际有线、无线网桥成员一致 已验证:主网四个有线口加三个 VAP,IoT 两个有线口加两个 VAP
有 IoT、无 IoT、出厂模式下的生成逻辑 隔离测试通过
状态文件清除后原厂清理登记 隔离模拟通过
本轮实际恢复出厂 未执行
主网上联与正式地址管理 已验证,主网网关可达,SSH 可登录
三个无线电、五个 BSS 启动 已验证,hostapd 为 ENABLED,VAP 归属正确
临时管理地址清理 已完成,ap_staging 不存在,正式管理 IPv4 保留
万兆口实际链路 实测 10Gbps、5Gbps 全双工,其中 5Gbps 经服务器与 AP 两侧确认;不代表吞吐测试结果
IoT 有线成员链路 检测到 eth2.3 对应物理端口为 1Gbps;这不等同于 IoT DHCP/上网验收
无线客户端 DHCP、Internet 及两侧广播/跨网隔离 尚无完整逐项测试记录,不能由 BSS 启用或链路连通推定
IPv6 隔离策略 尚无完整逐项测试记录
访客网络 扩展方案,未部署验收
其他型号、其他固件版本、固件升级后继续使用 未验证

最终保留的系统逻辑改动,是九行端口筛选和原厂热补丁登记;网络与无线配置负责表达实际拓扑。Root 的建立、保留范围和恢复步骤继续参见上一篇。