Debian

如何在 Linux 機器上用不同的 VLAN 標籤標記 IPv4 和 IPv6 數據包?

  • February 14, 2021

我想用不同的 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但無法找到解決方案。我怎樣才能實現這種選擇性標記?

我找到了解決方案。因為我想操作 VLAN,所以我必須使用網橋。VLAN 在 OSI 第 2 層上工作,網​​橋是可以處理第 2 層協議的設備。所以首先我將兩個 VLAN 介面添加到物理介面eth1。然後將所有介面eth0vlan4vlan6 添加到網橋。其餘的由nftables完成。

IPv4 和 IPv6 在 layer3 上定義,在 layer 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
   }
}

在轉發鏈上,這將丟棄所有 IPv6 到/從介面vlan4並且只允許它在介面vlan6上。所有其他的東西都被丟棄在介面vlan6上,但是通過介面**vlan4上接受的鏈預設策略。這確保了所有舊的東西,如 ARP 和其他廣播也進入介面vlan4

輸對外連結只是為了避免網橋本身將數據包發送到錯誤的 VLAN。在我的配置中,它僅使用 IPv6(單堆棧),因此鏈預設策略將刪除所有內容,除了 IPv6 到vlan6

雖然您的答案顯然對您有用,但它似乎過於復雜。我懷疑它是否可以滿足您的要求,因為它在給定的輸出中缺少任何 IPv4 地址(除了 lo)。

創建 2 個標記介面(例如命名為 vlan4 和 vlan6),為它們分配 IPv4 和 IPv6 地址 + 網關,並使用 sysctl 為 IPv4 禁用 SLAAC 就足夠了。

除了啟用 eth0 和 eth1 之間的流動所需的東西之外,不需要橋接或弄亂 nftables。

引用自:https://serverfault.com/questions/1053095