Xen

Firewalls Virtuais

por: Djames Suhanko

(djames.suhanko@gmail.com)


Contents

1. Compreendendo o ambiente
de para-virtualização

Para-virtualização e virtualização são dois modos diferentes de atingir um mesmo objetivo - rodar mais de um sistema operacional em uma única máquina. A virtualização implica em emular um hardware para que um dado sistema operacional trabalhe independente da plataforma física em que está hospedado. Com isso, têm-se um custo; o alto consumo de processamento, pois todo um hardware está sendo emulado por um virtualizador, chegando ao esgotamento dos recursos. Cada requisição de hardware feita pelo sistema hospedeiro é entregue ao virtualizador, que se encarrega de fazer a transação com o hardware real. Entre os mais conhecidos, encontra-se o Bochs, Qemu e VMWare. Nesses softwares emuladores de hardware, o sistema operacional deve ser instalado em um arquivo, ou inicializados a partir de um arquivo ISO1.1.

Na para-virtualização, o software trabalha muito mais próximo do hardware real; um sistema operacional usando um kernel modificado gerencia sistemas para-virtualizados, rodando micro-kernels. Com isso, ganha-se em processamento, pois não há uma emulação completa desde a BIOS, possibilitando a execução de muitos sistemas operacionais simultaneamente.

Esse trabalho é feito em Linux pelo Xen, um para-virtualizador com versão free e open. Nesse documento será abordado o uso de Xen rodando em Linux OpenSuSE 10.2, para-virtualizando sistemas instalados em LVM1.2 ,designados à tarefa de firewalls.

2. Do ambiente real ao para-virtualizado

Apresentando uma situação real, na multinacional Uranet2.1, onde viveu-se a limitação de espaço físicos de seu data center, pelo método estratégico adotado.

Por ser uma empresa de telefonia e callcenter, cada cliente possui um ou mais tipos de link com a prestadora do serviço, criando assim uma rede local ou remota onde trabalham os atendentes de telemarketing, ou por onde trafegam dados sigilosos. Afim de garantir a segurança e manter a simplicidade de manutenção, impactando ao mínimo no ambiente de produção e isolando qualquer tipo de problema, essas redes são separadas por firewalls independentes, que controlam o acesso entre o cliente e prestadora.

A solução utilizada seria ideal se não fosse a limitação física - consumo demasiado de espaço, racks, servers-select2.2, e principalmente energia (atingindo o limite de seus geradores e no-breaks). Esse é o caso em que se aplicou a solução descrita nesse documento.

Como toda a tecnologia (ou toda a solução), há prós e contras. Citando imediatamente os contras - perde-se nesse momento a segurança do problema físico isolado (apesar de ser o menos comum dos problemas), pois a paralização de um hardware real implicará na paralização de N firewalls. Por fim, ainda é contra a configuração, que não é complexa ao extremo, nem tão simples como poderia ser e, para disolver essa parte do problema, uma estratégia de geração/restauração está contida nesse documento.

Cada hardware real comportará 4 firewalls para-virtualizados. Assim, conta-se como vantagem a redução do parque de máquinas em 75%, além de racks, servers-select e energia. Também as facilitações; a cada uma porta do server-select se acessa de maneira mais ágil o console de 4 firewalls.

Para contar com um ambiente ideal, as máquinas reais são computadores industriais2.3 e as placas ethernet, 2 quad-port2.4. Ainda deve-se contar com 1 porta da rede onboard, afim de criar a rede das máquinas reais.

Cada firewall virtual terá uma reserva de 256MB de memória, ou seja - (4.256)+X para a dom0. A dom0 Não necessita de muita memória, porém para atingir algum valor acima de 1GB será necessário adquirir 3 pentes de 512MB ou 2 de 1GB.

3. Configurando o Xen

3.1 Conceitos

Existem alguns conceitos a seguir que evitarão confusões posteriores. Inicialmente tratando-se dos sistemas operacionais.

Um sistema para-virtualizador é conhecido como Dominio0, Domain0, Dom0, Xen0. Um sistema para-virtualizado é chamado de DominioU, DomainU, DomU, XenU. O ``U'' significa ``Unprivilegied'' ou, sem previlégios - pois esse sistema não terá acesso direto ao hardware.

A configuração necessária é a preparação da dom0 e da domU. A comunicação entre elas acontecerá através de bridges, que isolarão as interfaces de cada firewall. Nos domUs só serão vistas as interfaces que lhe forem atribuidas, ou seja,só poderia ser farejado através da dom0, onde serão enxergadas. As dom0s por sua vez estarão em uma rede separada por um outro firewall, que só será conectado ao mundo no momento em que houver a necessidade de uma manutenção remota. Assim seria algo como:

Internet -> Firewall -> Rede Xen0.

O acesso é feito por ssh, sendo derrubado o daemon assim que a conexão é estabelecida. Concluíndo-se a manutenção, o firewall é desconectado fisicamente da rede. Feita a parte paranóica.

3.2 Xen0

A configuração da Xen0 consiste em uma instalação padrão de um SuSE em modo texto, tendo o hd particionado em 3, onde uma partição menor será swap, uma será a raiz e a terceira, uma partição LVM, que abrigará os domUs.

3.2.1 Desabilitando serviços

Após a instalação do sistema, os seguintes daemons foram mantidos:

auditd

cron

dbus

fbset

haldaemon

kbd

microcode

network

nscd

policykitd

powersaved

resmgr

sshd

syslog

xend

xendomain

Para desabilitar os daemons desnecessários, basta rodar o Yast e, em sistema, selecionar ``Serviços do Nível de Execução''.

3.2.2 Instalação dos pacotes necessários.

Os pacotes Xen a serem instalados são:

kernel-xen

xen

xen-libs

xen-tools

Automaticamente será adicionado o pacote bridge-utils, para a configuração da bridge.


3.2.3 Criando a LVM

O script abaixo ajuda a criar o LVM. Basicamente, é criado com pvcreate, posteriormente o grupo com vgcreate e por fim, os volumes.

Não é necessário conhecimento prévio em LVM para a utilização do script.

A função do script a seguir é criar as partições raiz, swap e uma pequena partição para backup, como descrito no capítulo 5.

#!/bin/sh

escolhe_particao(){

PARTICAO=`dialog -stdout -inputbox "Digite a particao a criar LVM" 0 0`

[ $? = 1 ] && exit

dialog -stdout -yesno "Voce escolheu $PARTICAO ?" 0 0

if [ $? = 1 ];then

escolhe_particao

fi

echo $PARTICAO >particao

}

criar_grupo(){

NOME_DO_GRUPO=`dialog -stdout -inputbox "Nome para o grupo:" 0 0 vm`

dialog -stdout -yesno "Correto ($NOME_DO_GRUPO)?" 0 0

if [ $? = 1 ];then

criar_grupo

fi

dialog -stdout -yesno "Grupo: $NOME_DO_GRUPO \n Particao: $PARTICAO \n Correto?" 0 0

if [ $? = 1 ];then

exit 0

fi

pvcreate $(cat particao) ||{

dialog -stdout -infobox "Houve algum erro. \n Verifique se a particao existe e se o pacote para LVM esta instalado." 0 0

exit 1

}

vgcreate $NOME_DO_GRUPO $PARTICAO ||{

dialog -stdout -infobox "Houve algum erro. \n Verifique se a particao existe e se o pacote para LVM esta instalado." 0 0

exit 1

}

}

criar_volume(){

if [ "$1" != "" ];then

NOME_DO_GRUPO="$1"

fi

NOME_DO_VOLUME=`dialog -stdout -inputbox "Nome para o volume:" 0 0 vm1`

dialog -stdout -yesno "Correto ($NOME_DO_VOLUME)?" 0 0

if [ $? = 1 ];then

criar_volume

fi

tamanho(){

TAMANHO_RAIZ=`dialog -stdout -inputbox "Tamanho (512M, 5G...)" 0 0 5G`

dialog -stdout -yesno "Correto ($TAMANHO_RAIZ)?" 0 0

if [ $? = 1 ];then

tamanho

fi

TAMANHO_SWAP=`dialog -stdout -inputbox "Tamanho swap (512M, 5G...)" 0 0 512M`

dialog -stdout -yesno "Correto ($TAMANHO_SWAP)?" 0 0

if [ $? = 1 ];then

tamanho

fi

}

tamanho

lvcreate -L$TAMANHO_RAIZ -n $NOME_DO_VOLUME.raiz $NOME_DO_GRUPO

echo "y"|mkreiserfs /dev/$NOME_DO_GRUPO/$NOME_DO_VOLUME.raiz

lvcreate -L$TAMANHO_SWAP -n $NOME_DO_VOLUME.swap $NOME_DO_GRUPO

mkswap /dev/$NOME_DO_GRUPO/$NOME_DO_VOLUME.swap

}

auto_volume(){

NUM=`dialog -stdout -inputbox "Quantas maquinas deseja?" 0 0`

if [ $? = 1 ];then

exit

fi

NOME_DO_VOLUME=`dialog -stdout -inputbox "Nome para o volume:" 0 0 vm`

TAMANHO_RAIZ=`dialog -stdout -inputbox "tamanho da Raiz" 0 0 5G`

TAMANHO_SWAP=`dialog -stdout -inputbox "Tamanho da Swap" 0 0 512M`

for i in `seq 1 $NUM`;do

lvcreate -L$TAMANHO_RAIZ -n $NOME_DO_VOLUME$i.raiz $NOME_DO_GRUPO

echo "y"| mkreiserfs /dev/$NOME_DO_GRUPO/$NOME_DO_VOLUME$i.raiz

lvcreate -L$TAMANHO_SWAP -n $NOME_DO_VOLUME$i.swap $NOME_DO_GRUPO

mkswap /dev/$NOME_DO_GRUPO/$NOME_DO_VOLUME$i.swap

done

dialog -stdout -infobox "Verifique abaixo se foram criadas" 0 0

ls /dev/vm/*

}

dialog -stdout -yesno "Deseja colocar maquinas a um grupo existente?" 0 0

if [ $? = 0 ];then

NOME_DO_GRUPO=`dialog -stdout -inputbox "Nome do grupo existente" 0 0`

criar_volume $NOME_DO_GRUPO

exit 0

fi

escolhe_particao

criar_grupo

dialog -stdout -yesno "Gostaria de criar varios volumes \n passando apenas nome, tamanho raiz e swap?" 0 0

if [ $? = 1 ];then

criar_volume

else

auto_volume

fi

for i in `seq 1 4`;do

ls -l /dev/$NOME_DO_GRUPO/vm$i\.bkp ||{

lvcreate -L64M -n vm$i\.bkp $NOME_DO_GRUPO

echo "y"| mkreiserfs /dev/$NOME_DO_GRUPO/vm$i\.bkp

}

done

3.2.4 Configuração da bridge

A bridge é normalmente configurada em /etc/xen/scripts/network-bridge. Para esse modelo de configuração, o script foi criado com o seguinte conteúdo:

#!/bin/sh

#Djames Suhanko

#source /etc/xen/scripts/bridges.so

if [ "$1" = "" ];then

echo "Usage: Stop or Start"

echo " "

exit 0

fi

if [ "$1" = "start" ];then

for i in `seq 0 7`;do

#Cria bridge e adiciona interface

/sbin/brctl addbr br$i 2>/dev/null

/sbin/brctl addif br$i eth$i 2>/dev/null

#Configura interface

/sbin/ifconfig eth$i 0 0.0.0.0 2>/dev/null

#IP na ponte

/sbin/ifconfig br$i 192.168.10.$i netmask 255.255.0.0 2>/dev/null

done

elif [ "$1" = "stop" ];then

for i in `seq 0 7`;do

/sbin/brctl delbr br$i 2>/dev/null

/sbin/brctl delif br$i eth$i 2>/dev/null

/sbin/ifconfig br$i down 2>/dev/null

/sbin/ifconfig eth$i down

done

fi

Desse modo, cada bridge recebe uma interface ethernet, fazendo (a grosso modo) a conexão entre a máquina virtual e a interface ethernet real.

A interface 8, correspondente à placa de rede onboard deverá ser configurada normalmente na dom0, afim de permitir a rede local dom0. Recomenda-se que a configuração dessa interface seja feita em /etc/init.d/after.local (esse arquivo deverá ser criado e ajustado como executável). Algo como:

/sbin/ifconfig eth8 10.0.0.1 netmask 255.255.0.0 up.

3.2.5 Script inicializador da DomU

Para iniciar uma máquina virtual, pode-se passar com o comando xm todos os parâmetros necessários ou através de um script, como descrito a seguir:

kernel="/boot/vmlinuz-2.6.18.2-34-xen"

ramdisk="/boot/initrd-2.6.18.2.34.xen"

memory=256

root="/dev/hda1 ro"

disk=['phy:/dev/vm/vm1.raiz,hda1,w','phy:/dev/vm/vm1.swap,hda2,w','phy:/dev/vm/vm1.bkp,hda3,w']

vif=['mac=ac:de:48:00:00:01,bridge=br0','mac=ac:de:48:00:00:02,bridge=br1',]

A primeira linha se refere ao kernel, contido no diretório boot da dom0. Da mesma forma para o initrd, na segunda linha. Seguidamente, a quantidade de memória reservada para essa máquina. Aí está mais uma grande vantagem da para-virtualização sobre uma vlan, por exemplo, pois a domU pode ser atacada ou por algum outro motivo, ter seu desempenho prejudicado. A domU está limitada à sua porção de recursos; sua quantidade de CPU e, como especificado aqui, a memória. Com isso, mantém-se isolado qualquer problema.

A linha seguinte à memória indica a partição raiz da domU. Deve-se notar que, mesmo que o HD da dom0 seja SATA, na domU aparecerá como IDE e nesse primeiro momento, como read-only.

A linha disk informará a raiz, swap e uma partição para o backup, descrito no capítulo 5. O parâmetro phy indica que as partições são físicas. Somente o que for especificado nesse arquivo será visível para a domU.

A linha vif indica as bridges que cada interface ethernet atuará. Especificar o mac de cada interface é opcional, porém para validar o sistema de restauração, é necessário fazê-lo.

O spoofing do MAC deve obedecer a ordem da reserva ac:de:48, podendo modificar todos os demais campos. Também deve-se tomar cuidado para não repetir um MAC ou IP na mesma rede. Caso não seja especificado um MAC, será gerado um aleatoriamente, dentro da reserva do Xen (00:16:3e:...).

Esse arquivo pode receber qualquer nome, porém para validar o backup é necessário que se chame vmX.nome, onde X representa o número da máquina virtual (que deverá ter relação com a partição LVM vmX.raiz, como mostra o script na seção 3.2.3 e deve ser armazenado preferencialmente em /etc/xen/.

3.2.6 Ajustes importantes

Uma alteração de extrema importância deve ser feita em /boot/grub/menu.lst. Na linha ``module'', adicione o parâmetro dom0_mem=196. Isso evitará travamentos aleatórios nas interfaces de rede.

3.3 XenU

Para preparar uma XenU, basta uma instalação limpa de um firewall antes de receber rotas e regra. Instalar o sistema nomeando-o como ``generico'' ajudará a não se confundir posteriormente; uma imagem chamada ``generico'' que esteja rodando, certamente não possuirá nenhuma configuração.

Após o sistema devidamente instalado, deve ser feita uma cópia com os parâmetros ``-av'' para um diretório chamado genérico:

mkdir /generico

cd /

ls -l /|egrep -v 'proc|generico|<outro>' |awk '{print $NF}'|while read line; do cp -av $line generico/;done

tar cjvf generico.tbz2 generico

Esse arquivo deve ser transportado para a Xen0 e descomprimido em /, posteriormente criando os diretórios que foram excluídos na geração do pacote genérico:

tar xvjf generico.tbz2

A raiz do sistema agora deve ser a imagem genérica. Para isso, usa-se o comando:

chroot /generico

Monta-se /proc:

mount /proc

A senha deve ser convertida para shadow:

pwconv

O arquivo /etc/udev/rules.d/30-net_persistent_names.rules deve ser editado e a linha contendo os MACs das placas reais do firewall modelo devem ser removidas. As linhas possuirão informações do tipo:

SUBSYSTEM=="net", ACTION=="add", SYSFS{address}=="00:15:c5:35:df:c8", IMPORT="/lib/udev/rename_netiface %k eth0"

É importante remover essa linha, caso contrário, ao iniciar o sistema novas entradas serão criadas para as interfaces virtuais e conseqüentemente as interfaces iniciarão a partir de eth2.

Os serviços desnecessários devem ser removidos, incluindo dessa vez splash e kdb3.1. Basta rodar o Yast, uma vez que a raiz do sistema passou a ser /generico.

Deve-se remover também os arquivos relacionados à configuração da interface no boot. Algo como ``ifcfg-eth-00:0F...''. Estes arquivos estarão em /etc/sysconfig/network/.

O nome de host pode ser mudado através do Yast, na opção ``Serviços de Rede'' -> ``DNS e Nome de Host'', ou editando os arquivos /etc/HOSTNAME e /etc/hosts.

Na máquina real, para se acessar consoles usa-se Alt+[F1-F6]. As domUs também serão acessadas pelo console e esse suporte a múltiplas ttys é conflitante. Deve-se então desabilitar os consoles de 2 a 6, em /etc/inittab (do sistema genérico somente), comentado as linhas:

2:2345:respawn:/sbin/mingetty tty2

3:2345:respawn:/sbin/mingetty tty3

4:2345:respawn:/sbin/mingetty tty4

5:2345:respawn:/sbin/mingetty tty5

6:2345:respawn:/sbin/mingetty tty6

A tabela de sistemas de arquivos deve ser modificada, deixando apenas as entradas correspondentes a raiz, swap, proc e partição de backup , que será citado mais adiante. Essa partição existirá apenas na máquina virtualizada, não sendo necessário criá-la na máquina de geração do sistema genérico.

Modelo do fstab:

/dev/hda1 / reiserfs acl,user_xattr 1 1
/dev/hda2

O diretório /bkp deve ser criado no sistema genérico.

Concluídas as configurações, desmonta-se /proc e finaliza-se a jaula:

umount /proc

exit

Para concluir, as libs do Xen devem ser copiadas para o sistema genérico:

cp -av /lib/modules/*xen /generico/lib/modules/

Terminada a configuração, a genérica pode ser copiada para a partição do firewall que será virtualizado, montando o LVM em /mnt, exemplificando o primeiro firewall, chamado frwexemplo:

mount /dev/vm/vm1.raiz /mnt

cp -av /generico/* /mnt/

As configurações poderiam ser feitas nesse momento usando-se da jaula, ou após o primeiro boot, como no exemplo deste documento.

4. Controle das domUs

No console da máquina real, facilita-se a inicialização de um sistema virtual estando em /etc/xen, onde ficarão armazenados os scripts inicializadores dos sistemas virtuais, contando com a ajuda de auto-complete, porém todos os comandos podem ser executados de qualquer nível de diretório, indicando o caminho absoluto.

4.1 Iniciando um firewall

De dentro de /etc/xen:

xm create -c vm1.frwexemplo

A flag ``-c'' diz para iniciar o sistema em primeiro plano. O prefixo ``vm1'' é útil nesse momento, pois indica em que local do LVM se localiza o sistema.

A inicialização deve ocorrer normalmente, apresentando falha apenas no clock do hardware, que em nada influenciará nesse modelo.

Após efetuar o login no sistema, configura-se as interfaces de rede, que apresentarão uma mensagem de ``modulo não encontrado'', bastando ignorar a mensagem.

4.2 Comandos do Xen

Para retornar ao console da máquina real, basta usar Ctrl+].

Para retornar a um console, usa-se xm console vmX.nome, exemplificando com o modelo criado:

xm console vm1.frwexemplo

Seguido de Enter.

Para saber quais firewalls estão rodando, usa-se xm list. A lista apresentará o estado das máquinas, ou estado nenhum.

-r: indica processamento

-c: indica crash. A máquina virtual certamente não está rodando.

-b: Se a máquina virtual não estiver processando, entrará em estado de bloqueio até que seja requisitado processamento.

-p: Indica que dado domU foi pausado.

Quando uma domU sofre um crash (por uma configuração que não permitiu o boot correto, por exemplo), será necessário destruí-la. Para tal, usa-se o comando:

xm destroy vm1.frwexemplo

Têm-se a possibilidade de pausar um domU em execução. Isso interromperá o processamento, mas não livrará recursos em uso. Para pausar:

xm pause vm1.frwexemplo

E para retomar:

xm unpause vm1.frwexemplo

Pode-se desligar uma domU com:

xm shutdown vmX.nome

Mais detalhes podem ser observados no manual do xm.


5. Backups

Todos os script estão no pacote bkp.tbz2 em www.phantomsystem.com.br, no link superior à esquerda.

5.1 Backup das domUs

Um firewall normalmente roda um pequeno conjunto de serviços; regras de iptables, rotas e dhcp. As informações necessárias estão contidas em um conjunto de arquivos como nome de máquina, interfaces de rede, script pós-boot etc. Se estas informações forem acrescidas a um sistema genérico, tais configurações serão assumidas em um boot posterior, portanto, o script de backup a seguir reunirá os dados necessárias para reconstruir as domUs, caso a máquina real sofra algum dano irrecuperável.

#!/bin/bash

[ -d /bkp ] || mkdir /bkp

if [ -f /bkp/$(date +%Y-%m-%d) ];then

exit

fi

rm -rf /bkp/* 2>/dev/null

DIR=/bkp/`hostname -s`

rm -rfv $DIR

mkdir -p $DIR

cp -rfv -parents /etc/HOSTNAME $DIR

cp -rfv -parents /etc/dhcpd.conf $DIR

cp -rfv -parents /root/* $DIR

cp -rfv -parents /etc/host* $DIR

cp -rfv -parents /etc/resolv.conf $DIR

cp -rfv -parents /etc/rc.d/after.local $DIR

cp -rfv -parents /etc/rc.d/frw* $DIR

cp -rfv -parents /etc/sysconfig/network $DIR

cp -rfv -parents /var/spool/cron/tabs/* $DIR

echo "1" >/bkp/$(echo `date +%Y-%m-%d`)

O script inicia verificando se há o diretório de backup e a data do backup. Se a data do backup for inferior ao último, ele não será executado. Se for necessário rodar o backup manualmente, basta remover o conteúdo de /bkp.

Nesse script, a regra de firewall receberá o mesmo nome do firewall (ambos não devem conter o prefixo vmX). Desse modo, o backup se tornará genérico, dispensando a criação de um script para cada firewall. Se necessário for, basta adicionar ao script outros niveis de arquivos e diretórios.

O script finaliza adicionando a data do último backup. Dessa forma, mesmo que agendado no cron com intervalos curtos, a execução será breve.

O script after.local é apenas um arquivo executável (chmod 755) que, se existir, será executado após o rc - o último a rodar antes do login.

Quando o script roda e os arquivos são copiados, o domU compreende que está armazenando os dados em /dev/hda3, de poucos megas, apenas para armazenar os arquivos de configuração do sistema virtual em execução. Para o Dom0, essa partição é compreendida como um volume do LVM, contido em /dev/vm/vm1.bkp.

Todo esse bkp seria inútil se não pudesse ser armazenado remotamente, porém a máquina virtual não tem acesso à máquina real de forma alguma. A solução é recolher o backup a partir da Dom0, por ser ela a controladora de todo o conjunto.

A partição que corresponde ao bkp estará constantemente montada na domU em execução, sendo inapropriado acessar uma partição montada mesmo que a partir da dom0. Para que seja possível copiar os dados seguramente, o script que recolhe os backups tomará providências - sincronizará o conteúdo do backup na máquina virtual, enviando um sinal para sincronísmo dos dados, descarregando o buffer do dispositivo e posteriormente espelhando o conteúdo do volume LVM para um arquivo. Finalizará copiando o conteúdo desse arquivo espelhado para o respectivo diretório de backup, que será /firewalls/vmX.nome, replicando o backup na rede dom0 através de uma leitura no arquivo defaults.rfs, contido no diretório /root/bkp. Concluído, o arquivo de imagem é removido do sistema. Dá-se a esse fato a importância de criar um volume vmX.bkp de 16 ou 32 megabytes apenas, pois a imagem é gerada bit a bit com um dump do dispositivo e poderia acarretar em consumo de recursos excessivos. Não há como evitar o primeiro passo, que é o espelhamento, mas a data do backup é verificada da mesma forma que é feito na domU. A replicação na rede é feita por ssh usando-se de troca de chaves, que dispensará a senha. O script da dom0 que recolhe esse backup:

#!/bin/sh

#Djames Suhanko

#Esse script monta a particao de bkp e copia para /firewalls e rede

source /root/bkp/defaults.rfs

[ ! -f /root/bkp/bkp.lock ] || exit 1

echo "1" >/root/bkp/bkp.lock

roda_bkp(){

[ -d /mnt/bkp ] || mkdir /mnt/bkp

/usr/sbin/flushb /dev/vm/$1\.bkp

dd if=/dev/vm/$1\.bkp of=/mnt/$1\.bkp

mount -o loop /mnt/$1\.bkp /mnt/bkp

MAQUINA_LOCAL="/mnt/bkp"

ARQUIVO=`date +%Y-%m-%d`

[ -f /mnt/bkp/$ARQUIVO ] && {

DIR=`basename $(ls -d /mnt/bkp/*/|sed -e 's/\///')`

cp -r /mnt/bkp/$DIR /mnt/$1\.$DIR

DOMU_BKP=$1\.$DIR

cp -rf /mnt/$DOMU_BKP /firewalls/

cp -f /etc/xen/vm[1-4].* /firewalls/files/

echo $GRUPO|sed -e 's/,/\n/g; s/ //g'|while read line;do

if [ ! "$GRUPO" = "" ];then

ping -c1 $line >/dev/null || ESTADO="no"

if [ ! "$ESTADO" = "no" ];then

scp -r /mnt/$DOMU_BKP root@$line\:/firewalls/

scp /firewalls/files/* root@$line:/firewalls/files/

ESTADO="ok"

fi

fi

if [ ! "$ESTADO" = "ok" ] ;then

echo "$1 $line" >>/root/bkp/nao_copiado_para_rede.err

fi

done

rm -rf /mnt/$DOMU_BKP

umount /mnt/bkp || echo "no umount $1" >>/root/bkp/umount_bkp.err

rm -f /mnt/$1\.bkp

} || umount /mnt/bkp

}

/usr/sbin/xm list|egrep vm|cut -f1 -d.|while read line; do

roda_bkp $line

done

rm -f /root/bkp/bkp.lock

Dessa forma, todas as máquinas da rede dom0 terão em /firewalls uma cópia dos arquivos dos firewalls virtualizados em sí e nas outras dom0s. Para restaurar um conjunto de domUs, é necessário saber quais domUs rodavam em que dom0. Essa informação está no arquivo defaultfs.rfs em /root/bkp. Por exemplo, as dom0s chamadas de mfXX (mf01, mf02,...), estariam no defaults.rfs como:

MF01=''vm1.frwexemplo,vm2.frwxxx,vm3.frwxxxxx,vm4.xxxxxxx''

MF02=''...''

5.2 Backup das Dom0s

Supõe-se que a restauração de um conjunto será necessário no momento em que um dom0 tiver um problema físico, logo, o hardware deverá ser substituido. Para tal, o modelo de backup descrito neste documento sugere que haja uma dom0 de backup em rede, recebendo a replicação dos arquivos de backup. Assim, se houver a ``morte'' de uma dom0, a substituição poderá ser feita em alguns poucos minutos, rodando o script restaura_mf.sh na dom0 de backup:

#!/bin/sh

#Djames Suhanko - djames.suhanko@gmail.com

#Restaurador de grupos

source /root/bkp/defaults.rfs

TODAS=""

if [ "$1" = "remover" ];then

LISTA=`cat /root/bkp/defaults.rfs|egrep MFG|awk -F"=" '{print $1" "$1}'`

REMOVA=`dialog -stdout -title "Remover grupo" -menu "Selecione o grupo" 0 0 0 $LISTA`

if [ $? = 1 ];then

exit

fi

egrep -v "$REMOVA" /root/bkp/defaults.rfs >>/root/bkp/defaults.bkp

mv -f /root/bkp/defaults.bkp /root/bkp/defaults.rfs

exit

fi

if [ "$1" = "adicionar" ];then

NUMERO_DE_MAQUINAS=`dialog -stdout -title "Adicionar Grupo" -inputbox "Entre com o numero de maquinas desejadas" 0 0`

if [ $? = 1 ];then

exit

fi

for i in `seq 1 $NUMERO_DE_MAQUINAS`;do

NOME_DA_MAQUINA=`dialog -stdout -title "Nomes" -inputbox "Entre com o nome da maquina:" 0 0`

if [ $? = 1 ];then

exit

fi

TODAS_VIRGULA=$TODAS_VIRGULA$NOME_DA_MAQUINA","

done

TODAS=`echo $TODAS_VIRGULA|sed -e 's/,$//'`

for i in `seq 1 100`;do

A=`egrep "MFG$i" /root/bkp/defaults.rfs` ||{

echo "MFG$i=\"$TODAS\""

break

}

done

exit

fi

dialog -stdout -title "Maquina Despreparada" -yesno "Deseja selecionar um grupo?" 0 0

if [ $? = 1 ];then

exit

fi

egrep MFG /root/bkp/defaults.rfs >/tmp/grupos

dialog -stdout -textbox /tmp/grupos 0 0

rm -f /tmp/grupos

OPC=$(dialog -stdout -title "Selecione o MF" -menu "Restaurar Grupo" 0 0 0 \

MF01 "MF01" \

MF02 "MF02" \

MF03 "MF03")

[ $? = 1 ] && exit

VMRUNNING=`xm list|egrep vm|wc -l`

if [ $VMRUNNING -gt 0 ];then

dialog -stdout -title "Ops" -msgbox "Maquina virtual rodando. Pare-a primeiro" 0 0

exit

fi

case "$OPC" in

MF01)

[ -d /root/logs ] || mkdir -p /root/logs

GRUPO_SELECIONADO=$MFG1

cp -rf /firewalls/dom0/mf01/* / 2>>/root/logs/copia_dom0

;;

MF02)

[ -d /root/logs ] || mkdir -p /root/logs

GRUPO_SELECIONADO=$MFG2

cp -rf /firewalls/dom0/mf02/* / 2>>/root/logs/copia_dom0

;;

MF03)

exit

#cp -rf /firewalls/dom0/mf03/* / 2>>/root/logs/copia_dom0

#GRUPO_SELECIONADO=$MFG3

;;

esac

echo $GRUPO_SELECIONADO|sed -e 's/,/\n/g; s/\"//g '|while read line; do

mount /dev/vm/$(echo $line|cut -f1 -d.).raiz /mnt

[ -d /mnt/root ] ||{

cp -av /generico/* /mnt

#dialog -stdout -msgbox "Generico copiado para o diretorio" 0 0

}

cp -rv /firewalls/$line/* /mnt/

#servicos

chroot /mnt/ chkconfig -add $(echo $line|cut -f2 -d.)

if [ -f /mnt/etc/dhcpd.conf ];then

chroot /mnt chkconfig -add dhcpd

fi

umount /mnt

ln -sf /etc/xen/$line /etc/xen/auto/$line

done

dialog -stdout -title "Finalizado" -msgbox "Reiniciarei o computador" 0 0

/sbin/reboot

Também é permitido incluir ou remover um grupo no arquivo defaults.rfs, mas novos grupos no menu devem ser incluídos reeditando esse script.

O defaults.rfs deve ser replicado a cada modificação. Como esse é um arquivo comum em todas as dom0s, a replicação é feita manualmente, para evitar desatualizações ou sobrescrições inoportunas. O script que replicará o defaults.rfs contém:

#!/bin/sh

source /root/bkp/defaults.rfs

echo $GRUPO|sed -e 's/^$//g; s/ //g; s/,/\n/g'|while read line;do

scp /root/bkp/defaults.rfs root@$line:/root/bkp/

done

Não apenas os backups das domUs são replicados, mas os da dom0 também, pois a máquina real possui algumas características especificas como seu nome, configuração de rede, etc.

O script que faz o backup da dom0:

#!/bin/bash

[ -d /firewalls/dom0 ] || mkdir -p /firewalls/dom0

rm -rf /firewalls/dom0/$(hostname -s) 2>/dev/null

DIR=/firewalls/dom0/`hostname -s`

rm -rfv $DIR

mkdir -p $DIR

cp -rfv -parents /etc/HOSTNAME $DIR

cp -rfv -parents /root/* $DIR

cp -rfv -parents /etc/host* $DIR

cp -rfv -parents /etc/resolv.conf $DIR

cp -rfv -parents /etc/rc.d/after.local $DIR

cp -rfv -parents /etc/sysconfig/network $DIR

cp -rfv -parents /var/spool/cron/tabs/* $DIR

cp -rfv -parents /etc/xen/{vm[1-4]*,scripts/network-bridge} $DIR

source /root/bkp/defaults.rfs

echo $GRUPO|sed -e 's/^$//g; s/ //g; s/,/\n/g'|while read line;do

scp -r /firewalls/dom0/$(hostname -s) root@$line:/firewalls/dom0/

done

Acontecendo o crash, a dom0 de backup substituirá facilmente qualquer dom0 problemática, porém será necessário preparar uma substituta, que fará o papel de backup da rede novamente.

Afim de evitar o processo de configuração manual, gerar uma imagem da dom0 genérica sem a construção do LVM é a solução. Para tal, sugere-se o uso do Phantom, disponibilizado livremente em www.phantomsystem.com.br. Tendo uma imagem armazenada em qualquer ponto dessa rede, basta agora restaurá-la para um novo hardware (que desempenhará o papel de dom0 genérica) e reconstruir o LVM.

6. Considerações finais

O ambiente descrito nesse documento foi testado também em desktops Dell Optiplex 740, onde foi possível rodar 2 firewalls simultaneamente.

A solução apresentou alto desempenho e estabilidade, tendo todo o tempo dedicado à configuração.

Foi usado como referência o documento do site www.eriberto.pro.br.

Um canal de consultas no iRC - canal ##xen, no servidor FreeNode, onde pode-se encontrar ajuda (em inglês).

Todas as características de um firewall estão configuradas nas domUs, tendo a dom0 como única função, gerenciar os sistemas virtualizados.

Esse documento foi editado em LYX, front-end para o LATEX

About this document ...

Xen

This document was generated using the LaTeX2HTML translator Version 2002-2-1 (1.70)

Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The command line arguments were:
latex2html -no_subdir -split 0 -show_section_numbers /tmp/lyx_tmpdir13143GSP9Hu/lyx_tmpbuf0/xen-final.tex

The translation was initiated by viking on 2007-08-16


Footnotes

... ISO1.1
BIN,CUE, iso8859 - formato binário para ser gravado em algum tipo de mídia como CD ou DVD.
... LVM1.2
Linux Volume Manager
... Uranet2.1
www.uranet.com.br
... servers-select2.2
Monitor centralizador de acesso às máquinas, para que cada uma não precise de teclado e monitor independente e evitando ``passeios'' com mesa, teclado e mouse.
... industriais2.3
computadores com mais recursos, onde a placa-mãe é colocada em um slot ISA/PCI, em uma placa chamada ``backplane''.
... quad-port2.4
ethernets de quatro portas
... kdb3.1
Não haverá danos ao sistema, apesar da informação do Yast de que esse serviço não deve ser desabilitado.

viking 2007-08-16