4481 字
22 分钟
OpenWrt 网段隔离与跨子网通信实战

前言#

家里物联网设备越来越多——智能灯泡、摄像头、扫地机器人、智能插座……这些设备的安全更新频率远低于手机和电脑,一旦被攻破,攻击者就能在你的内网横向移动。把不同信任级别的设备放进不同网段、用防火墙控制互访,是最低成本的防御手段。

本文用 OpenWrt 实现一套完整的网段隔离方案,覆盖 VLAN 创建、防火墙 Zone 划分、跨子网路由、DHCP 分配和 WireGuard 远程接入。

硬件前提:本文基于 OpenWrt One(单 LAN 口)编写。单 LAN 口做 VLAN 需要外接一台支持 802.1q 的网管交换机,通过 Trunk 口承载多个 VLAN 的 tagged 流量。

替代方案

  • 双网口设备(如 x86 软路由、多口硬路由):可以直接把第二个物理网口独立划为一个 zone 并配不同子网,省去 VLAN 和交换机。也可以把 WAN 口加入 br-lan 桥接并启用 VLAN 过滤,将 WAN 口当作第二个 Trunk 口用,节省交换机端口
  • 多网口设备:每个物理口各接一个 VLAN 的 untagged 流量,等同于交换机的 access 口,不需要交换机即可实现网段隔离

无论用哪种硬件方案,本文的防火墙 zone 划分、DHCP 多池和 WireGuard 接入逻辑完全通用。

网络拓扑与子网规划#

物理拓扑#

Internet
[光猫]
[OpenWrt One] (单 LAN 口,做 VLAN Trunk)
│ tagged: VLAN 10, 20, 30
[网管交换机] (802.1q)
├── Port 2 (untagged VLAN 10) ── 管理设备(你的电脑/NAS)
├── Port 3 (untagged VLAN 20) ── IoT 设备
├── Port 4 (untagged VLAN 30) ── 访客 WiFi AP
└── Port 5 (untagged VLAN 10) ── 另一个 AP(家庭用)

子网规划#

VLAN ID名称子网网关用途
10mgmt192.168.10.0/24192.168.10.1管理网络(你的电脑、NAS、服务器)
20iot192.168.20.0/24192.168.20.1IoT 设备(灯泡、摄像头、音箱)
30guest192.168.30.0/24192.168.30.1访客网络(完全隔离)

互通策略#

源 → 目标mgmtiotguestWAN
mgmt
iot
guest
WireGuard

设计思路:管理网络可以访问一切;IoT 设备只能自己玩和上网,不能主动访问管理网段;访客完全隔离,只能上网;远程 WireGuard 拨入后可访问管理和 IoT 网络,但不能进访客网络。

第一步:交换机端 VLAN 配置#

在配置 OpenWrt 之前,先配好交换机。以常见的 TP-Link / Netgear 网管交换机为例。

不同品牌交换机界面不同,但核心概念一致:创建 802.1q VLAN、设置 PVID、指定 tagged/untagged 端口。以下以概念性配置描述。

交换机 VLAN 表#

VLAN ID端口 1(上行,连 OpenWrt)端口 2端口 3端口 4端口 5
10 (mgmt)taggeduntagged (PVID 10)untagged (PVID 10)
20 (iot)taggeduntagged (PVID 20)
30 (guest)taggeduntagged (PVID 30)

要点:

  • 端口 1(上行):所有 VLAN 都打 tagged,这是通向 OpenWrt 的 Trunk 口
  • 其他端口:每个端口只属于一个 VLAN,设 untagged + PVID 为对应 VLAN ID
  • 如果某个 AP 需要同时发多个 VLAN 的 SSID(比如一个 AP 同时发家庭 WiFi 和访客 WiFi),它所在的端口需要对多个 VLAN 打 tagged

PVID 解释#

PVID(Port VLAN ID)决定未打标签的入站帧被分配到哪个 VLAN。对于接普通设备的 access 口,PVID = 该端口所属的 VLAN ID。对于 Trunk 口(上行口),PVID 通常设为管理 VLAN(VLAN 10)或不设置(取决于交换机实现)。

第二步:OpenWrt VLAN 接口创建#

OpenWrt 24.10 使用 DSA(Distributed Switch Architecture),VLAN 配置在 LuCI 的 网络 → 接口 → 设备 选项卡中完成。

2.1 确认物理接口名#

SSH 到 OpenWrt,查看网络设备:

Terminal window
ip link show
# 或
ls /sys/class/net/

典型情况下单 LAN 口设备会有一个 lan1eth1 设备,它同时桥接在 br-lan 里。我们需要在物理口上创建 VLAN 子接口。

2.2 创建 VLAN 设备#

在 LuCI 中操作(网络 → 接口 → 设备 → 添加设备配置),或直接编辑 /etc/config/network

/etc/config/network
# 在 bridge 上启用 VLAN 过滤,显式声明桥接成员端口
config device
option name 'br-lan'
option type 'bridge'
option vlan_filtering '1'
list ports 'lan1'
# 管理 VLAN 10 —— lan1 端口 tagged 模式(Trunk)
config bridge-vlan
option device 'br-lan'
option vlan '10'
list ports 'lan1:t'
# IoT VLAN 20
config bridge-vlan
option device 'br-lan'
option vlan '20'
list ports 'lan1:t'
# 访客 VLAN 30
config bridge-vlan
option device 'br-lan'
option vlan '30'
list ports 'lan1:t'
# VLAN 10 接口 —— 管理网络
config interface 'mgmt'
option proto 'static'
option device 'br-lan.10'
option ipaddr '192.168.10.1'
option netmask '255.255.255.0'
# VLAN 20 接口 —— IoT 网络
config interface 'iot'
option proto 'static'
option device 'br-lan.20'
option ipaddr '192.168.20.1'
option netmask '255.255.255.0'
# VLAN 30 接口 —— 访客网络
config interface 'guest'
option proto 'static'
option device 'br-lan.30'
option ipaddr '192.168.30.1'
option netmask '255.255.255.0'

lan1:t 表示该端口在此 VLAN 中为 tagged 模式。因为是单 LAN 口做 router-on-a-stick,所有 bridge-vlan 条目中的 lan1 都设为 tagged(Trunk),不设 untagged 成员端口——untagged 流量由下游网管交换机的 access 口处理。

注意:如果原来的 config interface 'lan' 还在且指向裸 br-lan 设备,启用 VLAN 过滤后会断连。需要把原有 lan 接口的 option device 改为 br-lan.10(管理 VLAN),或删除原有 lan 接口、用 mgmt 替代。建议保留一个已建立的 SSH 会话,不要只依赖 LuCI。

配置完成后重启网络:

Terminal window
service network restart

第三步:DHCP 多池分配#

每个子网需要独立的 DHCP 池,让连接到对应交换机端口的设备自动获取正确 IP。

编辑 /etc/config/dhcp

/etc/config/dhcp
config dhcp
option domainneeded '1'
option authoritative '1'
option local '/lan/'
option domain 'lan'
option leasefile '/tmp/dhcp.leases'
option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
option ednspacket_max '1232'
# 管理网络 DHCP
config dhcp 'mgmt'
option interface 'mgmt'
option start '100'
option limit '150'
option leasetime '12h'
# option dhcpv4 'server' 可省略,OpenWrt 24.10 默认即为 DHCP 服务器模式
# IoT 网络 DHCP
config dhcp 'iot'
option interface 'iot'
option start '100'
option limit '150'
option leasetime '24h'
# 访客网络 DHCP
config dhcp 'guest'
option interface 'guest'
option start '100'
option limit '150'
option leasetime '2h'

关键参数说明:

参数说明
interface必须匹配 /etc/config/networkconfig interface 的名称
startDHCP 池起始偏移,100 表示从 192.168.x.100 开始分配
limit最大租约数量,150 表示到 192.168.x.249
leasetime租约时长,访客网络设短一些

.2.99 预留给静态分配设备(NAS、打印机、摄像头),DHCP 池从 .100 起步。

如需为特定子网指定不同 DNS 或网关:

config dhcp 'guest'
option interface 'guest'
list dhcp_option '6,1.1.1.1' # 访客走不同 DNS
...

重启 dnsmasq 使配置生效:

Terminal window
service dnsmasq restart

第四步:防火墙 Zone 划分与跨网段路由#

每个 VLAN 对应一个防火墙 zone,zone 之间通过 forwarding 规则控制互访。这是整个隔离方案的核心。

4.1 Zone 定义#

编辑 /etc/config/firewall

/etc/config/firewall
# === 默认策略 ===
config defaults
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'REJECT'
option synflood_protect '1'
# === Zone 定义 ===
# WAN — 互联网侧
config zone
option name 'wan'
list network 'wan'
list network 'wan6'
option input 'DROP'
option output 'ACCEPT'
option forward 'DROP'
option masq '1'
option mtu_fix '1'
# 管理网络 — 可信
config zone
option name 'mgmt'
list network 'mgmt'
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'ACCEPT'
# IoT — 不可信(设备不能访问路由器本身,除 DHCP/DNS)
config zone
option name 'iot'
list network 'iot'
option input 'REJECT'
option output 'ACCEPT'
option forward 'REJECT'
# 访客 — 完全隔离
config zone
option name 'guest'
list network 'guest'
option input 'REJECT'
option output 'ACCEPT'
option forward 'REJECT'
# === 跨 Zone 转发规则 ===
# mgmt → WAN(管理设备上网)
config forwarding
option src 'mgmt'
option dest 'wan'
# iot → WAN(IoT 设备上网)
config forwarding
option src 'iot'
option dest 'wan'
# guest → WAN(访客上网)
config forwarding
option src 'guest'
option dest 'wan'
# mgmt → iot(从管理网络访问 IoT 设备)
config forwarding
option src 'mgmt'
option dest 'iot'
# mgmt → guest(从管理网络访问访客网络,调试用)
config forwarding
option src 'mgmt'
option dest 'guest'
# === 为不可信 Zone 开放 DHCP 和 DNS ===
config rule
option name 'Allow-IoT-DHCP'
option src 'iot'
option dest_port '67'
option proto 'udp'
option target 'ACCEPT'
option family 'ipv4'
config rule
option name 'Allow-IoT-DHCP-Reply'
option dest 'iot'
option dest_port '68'
option proto 'udp'
option target 'ACCEPT'
option family 'ipv4'
config rule
option name 'Allow-IoT-DNS'
option src 'iot'
option dest_port '53'
option proto 'tcp udp'
option target 'ACCEPT'
config rule
option name 'Allow-Guest-DHCP'
option src 'guest'
option dest_port '67'
option proto 'udp'
option target 'ACCEPT'
option family 'ipv4'
config rule
option name 'Allow-Guest-DHCP-Reply'
option dest 'guest'
option dest_port '68'
option proto 'udp'
option target 'ACCEPT'
option family 'ipv4'
config rule
option name 'Allow-Guest-DNS'
option src 'guest'
option dest_port '53'
option proto 'tcp udp'
option target 'ACCEPT'

4.2 Zone 策略解读#

Zoneinputforward含义
mgmtACCEPTACCEPT管理设备可以访问路由器(SSH/LuCI)和跨子网通信
iotREJECTREJECTIoT 设备不能访问路由器(除 DHCP/DNS),不能跨子网发起连接
guestREJECTREJECT同上,访客完全隔离
wanDROPDROP互联网侧,最严格

mgmt zone 安全建议:当前 option input 'ACCEPT' 允许管理网段内所有设备直接访问路由器(SSH / LuCI)。为简化演示,此处设为 ACCEPT。生产环境建议按需收紧:将 input 改为 REJECT,再单独添加规则仅允许特定管理 IP(如 192.168.10.10)访问 SSH(端口 22)和 HTTPS(端口 443)。

关键认知:OpenWrt 的 forward 控制的是 zone 之间的转发,不是 zone 内部的。同一 zone 内(比如同一个 VLAN)设备之间的通信不受 forward 限制——因为它们在同一个广播域,走交换机的二层转发,根本不过路由器。要想隔离同一个 VLAN 内的设备,需要用 无线 AP 的客户端隔离 或交换机的 端口隔离 功能。

4.3 跨 VLAN 通信原理#

192.168.10.100(管理网络)ping 192.168.20.100(IoT 设备)时:

  1. 管理设备的网关是 192.168.10.1(OpenWrt br-lan.10 接口),设备发现目标不在本子网,将包发给网关
  2. OpenWrt 收到包,查询路由表:192.168.20.0/24 直连在 br-lan.20 接口上
  3. OpenWrt 检查防火墙:mgmt → iot 的 forwarding 规则存在,放行
  4. 包从 br-lan.20 发出,到达 IoT 设备
  5. IoT 设备回包时,conntrack 识别这是已有连接的回复,自动放行(不需要反向 forwarding 规则)

OpenWrt 的 fw4(nftables)防火墙是有状态的。config forwarding 只需配单向(发起方向),回复流量会被 conntrack 自动匹配 ct state established,related 规则放行。

4.4 应用防火墙#

Terminal window
service firewall restart

或者直接重载全部配置:

Terminal window
/etc/init.d/firewall reload

IPv6 兼容提示:本文防火墙规则以 IPv4 为例(option family 'ipv4')。如果你的网络同时启用 IPv6,需要为每个 DHCP 和 DNS 规则创建对应的 IPv6 版本(或删除 option family 限制),并额外放行 DHCPv6 端口(客户端 UDP 546,服务器 UDP 547)和 ICMPv6(IPv6 依赖 ICMPv6 做邻居发现和路由通告,阻止会导致 SLAAC 和 DHCPv6 均不可用)。基本规则示例:

config rule
option name 'Allow-IoT-DHCPv6'
option src 'iot'
option dest_port '547'
option proto 'udp'
option target 'ACCEPT'
option family 'ipv6'
config rule
option name 'Allow-IoT-ICMPv6'
option src 'iot'
option proto 'icmp'
option target 'ACCEPT'
option family 'ipv6'

以上示例以 IoT 区域为例,guest 区域也需要复制对应的 ICMPv6 和 DHCPv6 放行规则,否则访客网络的 IPv6 将不可用。

第五步:WireGuard 远程子网接入#

配好本地 VLAN 隔离后,加上远程接入能力:当你不在家时,通过 WireGuard 拨入 OpenWrt,能访问管理网络和 IoT 网络。

5.1 创建 WireGuard 接口#

编辑 /etc/config/network,追加:

# WireGuard 隧道接口
config interface 'wg_remote'
option proto 'wireguard'
option private_key '<OpenWrt 私钥>'
option listen_port '51820'
list addresses '10.99.88.1/24'
# 远程终端 Peer
config wireguard_wg_remote
option description 'my_phone'
option public_key '<终端公钥>'
option preshared_key '<PSK>'
option persistent_keepalive '25'
option route_allowed_ips '1' # 重要:务必显式设置,其默认值为 1
list allowed_ips '10.99.88.10/32' # 终端隧道 IP
list allowed_ips '192.168.10.0/24' # 允许访问管理网络
list allowed_ips '192.168.20.0/24' # 允许访问 IoT 网络
# 注意:不包含 192.168.30.0/24(访客网络)

生成密钥:

Terminal window
# 在 OpenWrt 上
wg genkey | tee /tmp/private.key | wg pubkey > /tmp/public.key
cat /tmp/private.key # 填入 option private_key
cat /tmp/public.key # 用于终端 Peer 配置

关于 route_allowed_ips:此选项默认即为 1,OpenWrt 会自动将 peer 中 allowed_ips 声明的子网路由安装到主路由表。作为 WireGuard 服务端时,请务必保留 option route_allowed_ips '1'(或显式声明为 1)。若 OpenWrt 未来作为客户端连接 VPN 服务商,必须将其设为 0 并手动添加路由,否则 0.0.0.0/0 的路由会覆盖默认网关,导致所有流量被劫持。

5.2 创建 WireGuard 防火墙 Zone#

/etc/config/firewall 中添加:

# WireGuard 远程接入 zone
config zone
option name 'wg_remote'
list network 'wg_remote'
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'ACCEPT'
# 允许 WAN 访问 WireGuard 端口
config rule
option name 'Allow-WireGuard'
option src 'wan'
option dest_port '51820'
option proto 'udp'
option target 'ACCEPT'
# WG remote → 管理网络
config forwarding
option src 'wg_remote'
option dest 'mgmt'
# WG remote → IoT 网络
config forwarding
option src 'wg_remote'
option dest 'iot'
# 双向:管理网络也能主动访问远程终端(可选)
config forwarding
option src 'mgmt'
option dest 'wg_remote'
# WG remote → WAN(远程终端通过家里网络上网,可选)
config forwarding
option src 'wg_remote'
option dest 'wan'

安全提示list allowed_ips 控制的是路由层面——WireGuard 只接受这些目标子网的流量。但真正的访问控制在防火墙 zone 的 forwarding 规则——你的最后一道防线。allowed_ips 只是”允许路由”,forwarding 规则才是”允许通过”。两者缺一不可。

5.3 终端 WireGuard 配置#

以手机 WireGuard 客户端为例:

[Interface]
PrivateKey = <终端私钥>
Address = 10.99.88.10/32
DNS = 192.168.10.1
[Peer]
PublicKey = <OpenWrt 公钥>
PresharedKey = <PSK>
Endpoint = <你的公网IP或DDNS>:51820
AllowedIPs = 10.99.88.0/24, 192.168.10.0/24, 192.168.20.0/24
PersistentKeepalive = 25

AllowedIPs 在终端侧控制的是哪些流量走隧道。这里只把家里子网的流量送入隧道,其余流量(比如刷网页)走终端的正常网络,即 split tunneling。

第六步:验证测试#

每改完一层配置就验证一层,不要全部配完再测——出了问题很难定位。

6.1 VLAN 与 DHCP 验证#

Terminal window
# 检查 VLAN 设备是否创建成功
ip -d link show br-lan.10
ip -d link show br-lan.20
ip -d link show br-lan.30
# 检查接口状态
ip addr show | grep "192.168"
# 检查 DHCP 服务是否在监听(优先使用 ss)
ss -tuln | grep ':67\b'
# 备选:netstat -tuln | grep ':67 '
# 查看 DHCP 租约
cat /tmp/dhcp.leases

在对应交换机端口上接入设备,确认获取到正确的 IP(管理设备应拿到 192.168.10.x,IoT 设备应拿到 192.168.20.x)。

6.2 跨子网通信验证#

从管理网络(192.168.10.x)测试:

Terminal window
# Ping IoT 子网网关
ping -c 3 192.168.20.1
# Ping IoT 子网中的设备
ping -c 3 192.168.20.100
# Ping 访客子网网关
ping -c 3 192.168.30.1
# Traceroute 查看路径
traceroute 192.168.20.100

从 IoT 网络(192.168.20.x)测试:

Terminal window
# 应失败 — IoT 不能主动访问管理网络
ping -c 3 192.168.10.1
ping -c 3 192.168.10.100

从访客网络(192.168.30.x)测试:

Terminal window
# 都应失败 — 访客完全隔离
ping -c 3 192.168.10.1
ping -c 3 192.168.20.1

6.3 端口扫描验证#

用 nmap 从管理网络扫 IoT 子网:

Terminal window
# 从 192.168.10.x 执行
nmap -sn 192.168.20.0/24

应该能看到 IoT 子网中的在线设备。

从 IoT 网络扫管理子网(应失败):

Terminal window
nmap -sn 192.168.10.0/24
# 预期:所有 host down(ping 被防火墙阻挡)

6.4 WireGuard 验证#

在远程终端连上 WireGuard 后:

Terminal window
# 在 OpenWrt 上检查握手
wg show
# 应看到:
# latest handshake: <几秒前>
# transfer: <有数据传输>
# 从远程终端 ping OpenWrt 隧道 IP
ping -c 3 10.99.88.1
# 从远程终端 ping 管理网络设备
ping -c 3 192.168.10.100
# 从远程终端 ping IoT 设备
ping -c 3 192.168.20.100
# 从远程终端 ping 访客网络(应失败)
ping -c 3 192.168.30.1

6.5 防火墙规则检查#

Terminal window
# 查看当前生效的 nftables 规则
nft list ruleset
# 只看转发规则
nft list chain inet fw4 forward
# 检查 zone 配置
uci show firewall | grep forwarding

常见问题#

Q:配置 VLAN 后把自己锁在外面了,LuCI 和 SSH 都连不上

通常是改错了管理 VLAN 的接口配置。用网线直连 OpenWrt 的 LAN 口(不走交换机),如果 OpenWrt 的 LAN 口还有 untagged 的默认 VLAN 配置,应该还能连上。紧急恢复:OpenWrt 的 failsafe 模式或重置配置。

预防:改 VLAN 配置前,先用 reload 而非 restart,并保持一个已建立的 SSH 会话不要断开。如果 reload 后新会话连不上,在旧会话里回滚配置。

Q:同一 VLAN 内的设备可以互访,防火墙挡不住

这是预期行为。同一个 VLAN 内的设备在同一个二层广播域,它们的通信走交换机直接转发,不经过 OpenWrt 的三层路由。要隔离同一 VLAN 的设备:

  • 无线隔离:在 /etc/config/wireless 中对应 SSID 的 config wifi-iface 段添加 option isolate '1',阻止连接同一 SSID 的客户端互访
  • 有线端口隔离:在网管交换机上启用 Port Isolation(不同品牌叫法不同:TP-Link 叫”端口隔离”、Netgear 叫”Port Protection”、Cisco 叫”Private VLAN Edge”),将同一 VLAN 内的端口彼此隔离,仅允许与上联口通信

Q:IoT 设备获取不到 IP 地址

三步排查:

  1. DHCP 服务是否在对应接口上监听:ss -tuln | grep ':67\b'
  2. 防火墙是否允许 DHCP 请求和回复(UDP 67 和 68):nft list chain inet fw4 input_iot | grep -E '67|68'
  3. 交换机 VLAN 配置是否正确:检查对应端口的 PVID 和 untagged VLAN 是否匹配

Q:跨 VLAN 能 ping 通网关但 ping 不通设备

检查目标设备的防火墙。Windows 防火墙默认阻止来自其他子网的 ICMP,Linux 的 ufw 也可能 drop。这和 OpenWrt 没关系——网关能通说明路由和 forwarding 都正常,问题在目标设备自身。

Q:WireGuard 握手成功但 ping 不通内网

常见原因:

  1. 防火墙 zone 的 forwarding 规则漏配——检查 wg_remote → mgmt 的 forwarding 是否存在
  2. route_allowed_ips 未设置为 1——内核没有安装到内网子网的路由
  3. 终端侧的 AllowedIPs 不包含内网子网——WireGuard 不会把该流量封装进隧道

总结与扩展思路#

本文搭了一套基础的 VLAN 隔离方案。在此基础上可以扩展:

  • 策略路由:让 IoT 子网的流量单独走 VPN 出口(适合某些需要特定地区 IP 的智能家居设备),用 ip rule + ip route 配合 mwan3 或 pbr 包实现
  • mDNS 跨子网转发:IoT 设备如打印机、音箱依赖 mDNS 做发现,跨 VLAN 后失效。用 Avahi 做 mDNS reflector 或重分发可以解决
  • IPv6 隔离:本文配的是 IPv4,IPv6 的 VLAN 隔离逻辑类似,但需要额外处理 SLAAC 和 DHCPv6,且防火墙规则要同时覆盖 IPv4 和 IPv6
  • Guest Captive Portal:对访客网络加认证门户

参考资源#

OpenWrt 网段隔离与跨子网通信实战
https://blog.syomega.top/posts/openwrt-vlan-isolation-guide/
作者
酱w
发布于
2026-05-26
许可协议
CC BY-NC-SA 4.0