iptables本身不识别vlan id,physdev模块仅用于桥接场景中匹配物理端口,无法匹配vlan标签;真正匹配vlan id需用ebtables,三层隔离应通过vlan子接口配合iptables的-i/-o及路由控制实现。

iptables 本身不识别 VLAN ID,physdev 模块也不是用来匹配 VLAN 标签的工具。想用 -m physdev 配合 VLAN-ID 实现跨虚拟网络访问隔离,这条路走不通——它既不符合 physdev 的设计目的,也绕过了 VLAN 流量在内核中的真实处理路径。
physdev 模块的真实作用
physdev 只用于桥接(bridge)场景,判断数据包“物理上”进出哪个桥端口(如 veth0、tap1),和 VLAN ID 完全无关。它不解析 802.1Q 标签,也不感知子接口(如 eth0.100)。即使你在桥上绑了带 VLAN 的设备,physdev 规则看到的仍是底层物理口或 veth 对儿,不是 VLAN ID。
- 典型用法:
iptables -m physdev --physdev-in veth10 -j DROP(限制从 veth10 进来的包) - 错误写法:
iptables -m physdev --physdev-in eth0.100 -j DROP(eth0.100 是逻辑子接口,physdev 不认) - 无效写法:
iptables -m physdev --physdev-vlan-id 100 -j DROP(physdev 没有 vlan-id 参数)
真正能匹配 VLAN ID 的方式是 ebtables
VLAN 标签在二层帧头,Linux 中只有 ebtables(工作在 bridge netfilter 层)能直接读取并匹配 802.1Q 字段。这是唯一标准、可靠、内核原生支持的 VLAN ID 过滤手段。
- 允许带 VLAN 100 的帧进入:
ebtables -A INPUT -i eth0 --vlan-id 100 -j ACCEPT - 拒绝其他所有 VLAN 帧:
ebtables -A INPUT -i eth0 -j DROP - 注意:需确保
br_netfilter模块已加载,且net.bridge.bridge-nf-call-iptables=1已启用(否则 iptables 看不到桥接流量)
三层隔离应依赖子接口 + 路由 + iptables
当 VLAN 子接口(如 eth0.100、eth0.200)已正确配置 IP 并启用后,真正的跨 VLAN 访问控制应在三层完成:
- 默认关闭跨子接口路由:
echo 0 > /proc/sys/net/ipv4/conf/eth0.100/forwarding(每个子接口单独关) - 用 iptables 的
-i和-o明确指定入/出接口:iptables -A FORWARD -i eth0.100 -o eth0.200 -j DROP - 禁止源地址伪造:
iptables -A INPUT -i eth0.100 ! -s 192.168.100.0/24 -j DROP
关键前提不能漏
以上所有规则生效的前提是基础环境正确:
- 内核
8021q模块已加载,子接口存在且 UP - 交换机端口设为 Trunk,并明确允许对应 VLAN ID 通过
- 禁用反向路径过滤:
sysctl -w net.ipv4.conf.all.rp_filter=0(避免因回程路径不对称丢包) - 确认管理工具(NetworkManager、systemd-networkd)未覆盖你的手动配置











