Linux

多個不同的 VLAN 中繼到 KVM 來賓 (Linux)

  • October 10, 2013

我遇到了建築挑戰的各種障礙。我有一個執行 KVM 的伺服器——它將包含許多來賓,一些執行虛擬化防火牆和其他,只是普通的 Web 伺服器。

  • Web 伺服器需要一個未標記的 VLAN 介面
  • 防火牆需要一個標記的 VLAN 中繼

現在通常,這很簡單,只需在其中添加一個網橋,eth0在網橋上添加幾個 VLAN(vmbr0.1等等) - 然後為每個訪客(或多個訪客)分配一個帶有未標記 VLAN 的介面。

                            firewall1 (vlan 1,2,3,4)
switch ===== eth0  vmbr0     firewall2 (vlan 1,2,5,6)
                  (eth0)    server1 (vlan 7)
                            server2 (vlan 8)
    vlan trunk
(1,2,3,4,5,6,7,8)     

現在,如果您只有幾個需要傳遞給來賓的介面,則此方法可以正常工作。但是當您需要將 500 個 VLAN 放入防火牆時會發生什麼。它不切實際。

所以我想不通的是如何創建一個號碼中繼(具有常見的 VLAN 和不同的 VLAN),並將它們分配給客人。

到目前為止,我發現的最接近的解決方案是在主橋上創建 VLAN,然後對於伺服器,只需從中分配一個 VLAN。

然後對於防火牆,為每個防火牆創建一個網橋,其中只有來賓的tap介面,然後vlan為相應的網橋創建未標記的介面,並將其添加到主vmbr0網橋。

唯一的問題是離開未標記介面的流量當然是未標記的。

是否可以標記退出介面的流量?

否則,如何實現到 KVM 來賓的不同中繼,可能具有公共 VLAN 和不同 VLAN(但絕不是所有 VLAN) - 並且能夠分配單個未標記的 VLAN 介面

一個冗長的解決方案…

所以我一直在玩弄不同的概念,我認為我已經提出了一個可行的解決方案。基本上,有一個主橋主幹 ( bt)eth0屬於。然後對於每個防火牆 VM 都有自己的網橋。

bridge name     bridge id               STP enabled     interfaces
bt              8000.002618895a72       no              eth0
bt-fw1          8000.000000000000       no              tap100i0
bt-fw2          8000.000000000000       no              tap101i0

此時,來自防火牆 VM 的標記流量將進入它們自己的網橋以供流量進入。

然後,我為需要標記流量的每個介面創建了 VLAN,並在主橋上為未標記流量創建了相應的 VLAN。

例如。VLAN 1、4000-4005

bt-fw1.1       | 1  | bt-fw1
bt-fw1.4000    | 4000  | bt-fw1
bt-fw1.4001    | 4001  | bt-fw1
bt-fw1.4002    | 4002  | bt-fw1
bt-fw1.4003    | 4003  | bt-fw1
bt-fw1.4004    | 4004  | bt-fw1
bt-fw1.4005    | 4005  | bt-fw1
bt-fw2.1       | 1  | bt-fw2
bt-fw2.4000    | 4000  | bt-fw2
bt-fw2.4001    | 4001  | bt-fw2
bt-fw2.4002    | 4002  | bt-fw2
bt-fw2.4003    | 4003  | bt-fw2
bt-fw2.4004    | 4004  | bt-fw2
bt-fw2.4005    | 4005  | bt-fw2
bt.1           | 1  | bt
bt.4000        | 4000  | bt
bt.4001        | 4001  | bt
bt.4002        | 4002  | bt
bt.4003        | 4003  | bt
bt.4004        | 4004  | bt
bt.4005        | 4005  | bt

然後為每個 VLAN 創建一個網橋,將每個介面的所有相應 VLAN 組合起來,以允許主網橋和 VM 網橋之間的無標記通信。

bt.v1                   8000.2a8c73ad057d       no      bt-fw1.1
                                                       bt-fw2.1
                                                       bt.1
bt.v4000                8000.2a8c73ad057d       no      bt-fw1.4000
                                                       bt-fw2.4000
                                                       bt.4000
bt.v4001                8000.2a8c73ad057d       no      bt-fw1.4001
                                                       bt-fw2.4001
                                                       bt.4001
bt.v4002                8000.2a8c73ad057d       no      bt-fw1.4002
                                                       bt-fw2.4002
                                                       bt.4002
bt.v4003                8000.2a8c73ad057d       no      bt-fw1.4003
                                                       bt-fw2.4003
                                                       bt.4003
bt.v4004                8000.2a8c73ad057d       no      bt-fw1.4004
                                                       bt-fw2.4004
                                                       bt.4004
bt.v4005                8000.2a8c73ad057d       no      bt-fw1.4005
                                                       bt-fw2.4005
                                                       bt.4005

現在,這允許將中繼介面連接到防火牆 VM,其中只有我想要的 VLAN。

未來任何只需要一個未標記 VLAN 的來賓,只能添加到相應的bt.X網橋。

添加主機 IP 介面就像將 IP 添加到相應的 VLAN 網橋一樣簡單

例如。

ip addr add 192.168.100.1/24 dev bt.v4005

輔助腳本

由於我的/etc/network/interfaces文件可能很快就會變得龐大,因此我編寫了一個小腳本,允許進行最少的配置 - 但具有相同的預期最終結果。

/etc/network/interfaces它包含的文件中

# bridge bt-c0-fw1 vlan 1 4000-4005 interfaces tap100i0
# bridge bt-c0-fw2 vlan 1 4000-4005 interfaces tap101i0
# bridge bt vlan 1 4000-4005 interfaces eth0
# bridge-vlan bt vlan 1 4000-4005 interfaces bt-fw1 bt-fw2 bt

auto eth0
iface eth0 inet manual
 post-up /scripts/build-bridges.sh || /bin/true

然後在後期腳本中,/scripts/build-bridges.sh

#!/bin/bash

CONFIG="/etc/network/interfaces"
DEFINERS="vlan|interfaces"
DEBUG=0

# Tear down all interfaces
modprobe -r 8021q
modprobe 8021q

brctl show | awk 'NR>1{print $1}' | while read BRIDGE; do
 ifconfig "$BRIDGE" down
 brctl delbr "$BRIDGE"
done

function run()
{
 if [ $DEBUG -eq 1 ]; then
   echo "$@"
 else
   eval "$@"
 fi
}

function get_vars()
{
 DATA=( $(echo "$2" | grep -Eoh "$1.+?" | sed -E "s/^$1 //g;s/($DEFINERS).+//g") )
 for VAL in ${DATA[@]}; do
   echo $VAL | grep -qE "[0-9]+-[0-9]+"
   if [ $? -eq 0 ]; then
     LOWER=$(echo $VAL | cut -f1 -d"-")
     UPPER=$(echo $VAL | cut -f2 -d"-")
     for i in $(seq $LOWER $UPPER); do
       echo $i
     done
   else
     echo $VAL
   fi
 done
}

# Build bridges
while read LINE; do
 BRIDGE=$(get_vars bridge "$LINE")
 if [[ ! "$BRIDGE" == "" ]]; then
   run brctl addbr $BRIDGE
   run ifconfig $BRIDGE up
   for INTERFACE in $(get_vars interfaces "$LINE"); do
     ifconfig $INTERFACE >/dev/null 2>&1
     if [ $? -eq 0 ]; then
       run brctl addif $BRIDGE $INTERFACE
     fi
   done
   run ifconfig $BRIDGE up
   for VLAN in $(get_vars vlan "$LINE"); do
     run vconfig add $BRIDGE $VLAN 2>&1 | grep -vE "(VLAN 1 does not work|consider another number)"
     run ifconfig $BRIDGE.$VLAN up
   done
 fi
done < <(grep -E "^# bridge " $CONFIG)

# Build vlan bridges
while read LINE; do
 BRIDGE=$(get_vars "bridge-vlan" "$LINE")
 for VLAN in $(get_vars " vlan" "$LINE"); do
   run brctl addbr $BRIDGE.v$VLAN
   run ifconfig $BRIDGE.v$VLAN up
   for INTERFACE in $(get_vars interfaces "$LINE"); do
     ifconfig $INTERFACE.$VLAN >/dev/null 2>&1
     if [ $? -eq 0 ]; then
       run brctl addif $BRIDGE.v$VLAN $INTERFACE.$VLAN
     fi
   done
 done
done < <(grep -E "^# bridge-vlan " $CONFIG)

exit 0

我希望這對其他人有所幫助,我已經花了 DAYS 時間閱讀和測試,這似乎是最優雅、最易於管理的解決方案。

這裡也有一些很好的閱讀http://blog.davidvassallo.me/2012/05/05/kvm-brctl-in-linux-bringing-vlans-to-the-guests/

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