我想用不同的 VLAN 标签标记来自启用双栈的连接传入的 IPv4 和 IPv6 数据包,例如 IPv4 数据包应进入 VLAN4,IPv6 数据包应进入 VLAN6。更一般地说,我想将混合了 IPv4 和 IPv6 数据包的双栈 IP 流拆分为两个干净的单栈网络,这样您就不会在 IPv6 网络上找到任何 IPv4 数据包,反之亦然。我需要这个来测试和支持仅 IPv6 的网络。当然,我仍然需要 IPv4 数据。它不能简单地被丢弃。
Linux Box
Debian Bullseye
untagged ┏━━━━━━━━━━━┓ tagged (trunk)
════════════════════════┫eth0 vlan4┣═╦══════════════════════
IPv4 and IPv6 ┃ vlan6┣═╝eth1 IPv4 with VLAN4 tag
dual stack ┗━━━━━━━━━━━┛ IPv6 with VLAN6 tag
我查看了 Linux 桥接器,nftables
但找不到解决方案。我该如何实现这种选择性标记?
答案1
虽然您的答案对您来说似乎有用,但它似乎过于复杂。但我怀疑它是否能满足您的要求,因为给定的输出中没有任何 IPv4 地址(lo 除外)。
创建 2 个标记接口(例如名为 vlan4 和 vlan6),为它们分配 IPv4 和 IPv6 地址 + 网关,并使用 sysctl 禁用 IPv4 的 SLAAC 就足够了。
除了需要在 eth0 和 eth1 之间启用流动之外,不需要桥接,也不需要处理 nftables。
答案2
我找到了一个解决方案。因为我想操作 VLAN,所以我必须使用网桥。VLAN 在 OSI 第 2 层上工作,网桥是可以处理第 2 层协议的设备。所以我首先在物理接口上添加了两个 VLAN 接口eth1.然后添加所有接口eth0,VLAN4和VLAN6到桥上。剩下的工作由nftables。
IPv4 和 IPv6 在第 3 层定义,在第 2 层上没有不同含义。因此nftables可以将它们视为具有不同“标记”的数据包,即 IP 报头中的协议类型。幸运的是nftables可以使用 来选择它们meta protocol {}
。它将传入的未标记的 IPv4 和 IPv6 数据包定向到相应的 VLAN 接口。标记由接口像往常一样自动完成。我使用systemd-networkd以下是详细配置。
首先创建网络设备vlan4、vlan6和网桥br0:
~$ sudo -Es
~# cat > /etc/systemd/network/01-vlan4.netdev <<EOF
[NetDev]
Name=vlan4
Kind=vlan
[VLAN]
Id=4
EOF
~# cat > /etc/systemd/network/02-vlan6.netdev <<EOF
[NetDev]
Name=vlan6
Kind=vlan
[VLAN]
Id=6
EOF
~# cat > /etc/systemd/network/03-br0.netdev <<EOF
[NetDev]
Name=br0
Kind=bridge
[Bridge]
DefaultPVID=6
VLANProtocol=802.1q
STP=no
EOF
然后将接口连接到 eth1 和网桥:
~# cat > /etc/systemd/network/12-eth1_attach-vlans.network <<EOF
[Match]
Name=eth1
[Network]
LLMNR=no
LinkLocalAddressing=no
VLAN=vlan4
VLAN=vlan6
EOF
~# cat > /etc/systemd/network/16-ifs_add_to_br0.network <<EOF
[Match]
Name=eth0 vlan4 vlan6
[Network]
Bridge=br0
LLMNR=no
LinkLocalAddressing=no
EOF
现在只需提起桥梁:
~# cat > /etc/systemd/network/20-br0-up.network <<EOF
[Match]
Name=br0
[Network]
LLMNR=no
MulticastDNS=yes
EOF
重启后你将得到:
~$ ip -brief address
lo UNKNOWN 127.0.0.1/8 ::1/128
eth0 UP
br0 UP 2003:d5:2721:900:9012:fdff:fef0:ea7f/64 fe80::9012:fdff:fef0:ea7f/64
vlan6@eth1 UP
vlan4@eth1 UP
eth1 UP
# these are the slave interfaces of the bridge
~$ sudo bridge link show
4: vlan6@eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 4
5: vlan4@eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 4
6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 4
还值得检查一下resolvectl
。现在我们必须执行最后一步,并使用nftables使用这些规则:
~$ cat /etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table bridge filter {
chain forward {
type filter hook forward priority 0; policy accept;
meta protocol { ip6 } iifname "vlan4" drop
meta protocol { ip6 } oifname "vlan4" drop
meta protocol { ip6 } iifname "vlan6" accept
meta protocol { ip6 } oifname "vlan6" accept
iifname "vlan6" drop
oifname "vlan6" drop
}
chain output {
type filter hook output priority 0; policy drop;
meta protocol { ip6 } iifname "vlan6" accept
meta protocol { ip6 } oifname "vlan6" accept
}
}
在正向链中,这将丢弃所有往返于接口的 IPv6VLAN4并且只允许在界面上VLAN6. 所有其他内容都放在界面上VLAN6,但根据链上接口接受的默认策略VLAN4.这确保所有旧的东西,如ARP和其他广播也进入接口VLAN4。
输出链只是为了避免网桥本身将数据包发送到错误的 VLAN。在我的配置中,它仅使用 IPv6(单栈),因此链默认策略将丢弃除 IPv6 之外的所有内容VLAN6。