Vários troncos VLAN diferentes para convidados KVM (Linux)

5

Eu encontrei um obstáculo na estrada com um desafio arquitetônico. Eu tenho um servidor rodando KVM - que contará com um número de convidados, alguns executando firewalls virtualizados e outros, apenas servidores web simples.

  • Os servidores da web precisam de uma única interface VLAN não marcada
  • Os firewalls precisam de um tronco de VLAN marcado

Agora, normalmente, isso seria simples, basta adicionar uma ponte com eth0 , adicionar algumas VLANs na ponte ( vmbr0.1 etc.) e alocar uma interface com uma VLAN não marcada para cada convidado (ou seus múltiplos).

                             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)     

Agora, isso funciona bem se você tiver apenas algumas interfaces necessárias para passar a um convidado. Mas o que acontece quando você precisa colocar 500 VLANs em um firewall. É impraticável.

Então, o que não consigo descobrir é como criar um número de troncos (com VLANs comuns e diferentes VLANs) e alocá-los a um convidado.

A solução mais próxima que encontrei até agora é criar as VLANs na ponte principal e, em seguida, para os servidores, apenas alocar uma única VLAN a partir dela.

Em seguida, para os firewalls, crie uma ponte para cada um deles, com apenas a interface tap do convidado, crie a interface vlan não identificada para essa respectiva ponte e adicione-a à% principal vmbr0 bridge. / p>

O único problema é que o tráfego que sai da interface não marcada é, naturalmente, não marcado.

É possível marcar o tráfego ao sair de uma interface?

-

Caso contrário, como é possível obter troncos diferentes para convidados KVM, que podem ter VLANs comuns e VLANs diferentes (mas nunca TODAS as vlans) - e conseguir atribuir interfaces vlan únicas e não identificadas

    
por choco-loo 03.10.2013 / 00:31

1 resposta

6

Uma solução demorada ...

Então, ando por aí com conceitos diferentes e acho que fiz uma solução viável. Basicamente, há um tronco de ponte principal ( bt ) ao qual eth0 pertence. Então, para cada firewall, a VM tem sua própria ponte.

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

Nesse momento, o tráfego marcado das VMs de firewall entrará em sua própria ponte para o tráfego entrar.

Eu, então, criei VLANs para cada interface que precisa de tráfego marcado - e a respectiva VLAN na ponte principal para tráfego não marcado.

VLANs 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

Em seguida, para cada VLAN, é criada uma ponte que combina todas as respectivas VLANs de cada interface para permitir a comunicação não marcada entre a ponte principal e as pontes da 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

Isso agora permite interfaces troncalizadas para as VMs de firewall, com apenas as VLANs que eu quero nelas.

Qualquer convidado futuro que precise apenas de uma única VLAN não marcada, pode ser adicionado apenas à respectiva bt.X bridge.

Adicionar interfaces IP de host é tão fácil quanto adicionar o IP à respectiva VLAN bridge

Por exemplo.

ip addr add 192.168.100.1/24 dev bt.v4005

Um script auxiliar

Como meu arquivo /etc/network/interfaces pode rapidamente acabar sendo enorme, eu escrevi um pequeno script que permite uma configuração mínima - mas com o mesmo resultado final desejado.

No arquivo /etc/network/interfaces que contém

# 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

Em seguida, no script de post-up, /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

Espero que isso ajude outra pessoa. Passei DIAS lendo e testando e essa parece ser a solução mais elegante e fácil de gerenciar.

Há uma boa leitura aqui também link

    
por 03.10.2013 / 23:49