![多个不同的 VLAN 中继到 KVM 客户机 (Linux)](https://linux22.com/image/804534/%E5%A4%9A%E4%B8%AA%E4%B8%8D%E5%90%8C%E7%9A%84%20VLAN%20%E4%B8%AD%E7%BB%A7%E5%88%B0%20KVM%20%E5%AE%A2%E6%88%B7%E6%9C%BA%20(Linux).png)
我在架构挑战方面遇到了一些障碍。我有一台运行 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 接口
答案1
一个漫长的解决方案...
所以我一直在尝试不同的概念,我想我已经找到了一个可行的解决方案。基本上,有一个属于的主桥中继(bt
)eth0
。然后每个防火墙虚拟机都有自己的桥。
bridge name bridge id STP enabled interfaces
bt 8000.002618895a72 no eth0
bt-fw1 8000.000000000000 no tap100i0
bt-fw2 8000.000000000000 no tap101i0
此时,来自防火墙虚拟机的标记流量将进入其自己的网桥以供流量进入。
然后,我为每个需要标记流量的接口创建了 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
现在,这允许中继接口到防火墙虚拟机,并且只有我想要的 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
我希望这对其他人有所帮助,我花了好几天的时间阅读和测试,这似乎是最优雅、最易于管理的解决方案。
这里也有一些不错的读物http://blog.davidvassallo.me/2012/05/05/kvm-brctl-in-linux-bringing-vlans-to-the-guests/