[OpenBSD]

[Anterior: Shell de Usuário para Atutenticação em Gateways] [Conteúdo] [Próximo: Firewall para Casa ou Pequeno Escritório]

PF: Redundância de Firewall com CARP e pfsync


Conteúdo


Introdução ao CARP

CARP é o Protocolo de Redundância de Endereço Comum (Common Address Redundancy Protocol). Seu objetivo principal é permitir que múltiplos hosts no mesmo segmento de rede compartilhem um endereço IP. CARP é uma alternativa livre e segura ao Virtual Router Redundancy Protocol (VRRP) e ao Hot Standby Router Protocol (HSRP).

CARP funciona permitindo um grupo de hosts no mesmo segmento de rede compartilhar um endereço IP. Este grupo de hosts é referido como um "grupo de redundância". O grupo de redundância é atribuído a um endereço IP que é compartilhado entre os membros do grupo. Dentro do grupo, um host é designado o "master" e o resto como "backups". O host master é o que atualmente "segura" o IP compartilhado; ele responde a qualquer tráfego ou requisições ARP direcionadas para ele. Cada host pode pertencer a mais que um grupo de redundância por vez.

Um uso comum para o CARP é criar um grupo de firewalls redundantes. O IP virtual que é atribuído ao grupo de redundância é configurado nas máquinas clientes como o gateway padrão (default). Caso o firewall sofra uma falha ou seja desligado, o IP se moverá para um dos firewalls backup e o serviço vai continuar sem ser afetado.

CARP suporta IPv4 e IPv6.

Operação do CARP

O host master no grupo envia regularmente anúncios à rede local assim os hosts backup sabem que ele ainda está ativo. Se os hosts backup não ouvirem um anúncio do master por um período de tempo, então um deles tomará conta dos deveres do master (qualquer host backup que tenha configurado os valores advbase e advskew baixos).

É possível múltiplos grupos CARP existir no mesmo segmento de rede. Os anúncios CARP contém o Virtual Host ID, que permite aos membros do grupo identificar qual grupo de redundância pertence.

Para prevenir que um usuário malicioso no segmento de rede falsifique (spoofing) anúncios CARP, cada grupo pode ser configurado com uma senha. Cada pacote CARP enviado ao grupo é então protegido por um HMAC SHA1.

Como o CARP é seu próprio protocolo ele deve ter uma regra permitida explicitamente nas regras de filtragem:

pass out on $carp_dev proto carp keep state

$carp_dev deve ser a interface física que o CARP está se comunicando.

Configurando o CARP

Cada grupo de redundância é representado por uma interface de rede virtual carp(4). Assim, o CARP é configurado usando ifconfig(8).
ifconfig carpN create

ifconfig carpN vhid vhid [pass senha] [carpdev carpdev] \
   [advbase advbase] [advskew advskew] [state estado] endereço-ip \
   netmask máscara
carpN
O nome da interface virtual carp(4) onde N é um inteiro que representa o número da interface (ex., carp10).
vhid
O Virtual Host ID. Este é um número único que é usado para identificar o grupo de redundância de outros nós na rede. Valores aceitos são 1 à 255.
senha
A senha de autenticação para usar quando estiver conversando com outros hosts CARP neste grupo de redundância. Deve ser a mesma para todos os membros do grupo.
carpdev
Este parâmetro opcional especifica a interface de rede física que pertence a este grupo de redundância. Por padrão, o CARP tentará determinar qual interface usar procurando pela interface física que está na mesma subrede da combinação endereço-ip e máscara dada a interface carp(4).
advbase
Este parâmetro opcional especifica com que frequência, em segundos, anunciar que somos um membro do grupo de redundância. O padrão é 1 segundo. Valores aceitos são 1 à 255.
advskew
Este parâmetro opcional especifica quanto desviar o advbase quando estiver enviando anúncios CARP. Manipulando o advskew, o host CARP master pode ser escolhido. Quanto mais alto o número, menos preferido será o host quando estiver escolhendo um master. O padrão é 0. Valores aceitos são 0 à 254.
estado
Força uma interface carp(4) em um certo estado. Estados válidos são init, backup e master.
endereço-ip
Este é o endereço IP atribuído ao grupo de redundância. Este endereço não tem que estar na mesma subrede que o endereço IP na interface física (se presente). Este endereço, contudo, precisa ser o mesmo em todos os hosts no grupo.
máscara
A máscara de subrede do IP compartilhado.

Além disso comportamentos CARP podem ser controlados via sysctl(8).

net.inet.carp.allow
Aceita entrada de pacotes CARP ou não. Padrão é 1 (sim).
net.inet.carp.preempt
Permite hosts dentro de um grupo de redundância ter um melhor advbase e advskew para tomar o lugar (preempt) do master. Adicionalmente, esta opção habilita failing over em todas as interfaces caso uma interface caia (down). Se uma interface física CARP cair, o CARP trocará o advskew para 240 em todas as outras interfaces CARP, em essência o failing termina por si mesmo. Esta opção é 0 (desabilitada) por padrão.
net.inet.carp.log
Loga pacotes CARP. O padrão é 0 (desabilitado).
net.inet.carp.arpbalance
Carrega balanceamento de tráfego entre múltiplos hosts no grupo de redundância. O padrão é 0 (desabilitado). Veja carp(4) para mais informações.

Exemplo do CARP

Aqui tem um exemplo de configuração do CARP.
# sysctl -w net.inet.carp.allow=1
# ifconfig carp1 create
# ifconfig carp1 vhid 1 pass mekmitasdigoat carpdev em0 \
    advskew 100 10.0.0.1 netmask 255.255.255.0

Isto configura o seguinte:

Rodando ifconfig na carp1 mostra o status da interface.

# ifconfig carp1
carp1: flags=8802<UP,BROADCAST,SIMPLEX,MULTICAST> mtu 1500
     carp: BACKUP carpdev em0 vhid 1 advbase 1 advskew 100
     groups: carp
     inet 10.0.0.1 netmask 0xffffff00 broadcast 10.0.0.255

Introdução ao pfsync

A interface de rede pfsync(4) expõe certas alterações feitas na tabela de estados pf(4). Monitorando este dispositivo usando tcpdump(8), alterações na tabela de estados podem ser observadas em tempo real. Além disso, a interface pfsync(4) pode enviar estas mensagens de alterações de estado para a rede de modo que outros nós rodando PF possam unir as alterações em suas próprias tabelas de estado. Da mesma forma, o pfsync(4) também pode ouvir a rede por mensagens que chegam.

Operação do pfsync

Por padrão, o pfsync(4) não envia ou recebe atualizações da tabela de estados na rede; entretanto, atualizações ainda podem ser monitoradas usando o tcpdump(8) ou outras ferramentas na máquina local.

Quando o pfsync(4) está configurado para enviar e receber atualizações na rede, o comportamento padrão é enviar atualizações multicast na rede local. Todas as atualizações são enviadas sem autenticação. Prática mais comum é:

  1. Conectar os dois nós que estarão trocando atualizações usando um cabo crossover e usar a interface como syncdev (veja abaixo).
  2. Usar a opção ifconfig(8) syncpeer (veja abaixo) assim atualizações são direcionadas com unicast para o nó, então configure o ipsec(4) entre os hosts para proteger o tráfego pfsync(4).

Quando as atualizações estão sendo enviadas e recebidas na rede, os pacotes pfsync devem ser aceitos nas regras de filtragem.

pass on $sync_if proto pfsync

$sync_if deve ser a interface física que o pfsync(4) esta se comunicando.

Configurando o pfsync

Visto que o pfsync(4) é uma interface de rede virtual, é configurado usando ifconfig(8).
ifconfig pfsyncN syncdev syncdev [syncpeer syncpeer]
pfsyncN
O nome da interface pfsync(4). pfsync0 existe por padrão quando estiver usando o kernel GENERIC.
syncdev
O nome da interface física usada para enviar atualizações pfsync.
syncpeer
Este parâmetro opcional específica o endereço IP de um host para trocar atualizações pfsync. Por padrão atualizações pfsync são multicast na rede local. Esta opção cancela este comportamento e em vez disso envia atualizações unicasts para o syncpeer especificado.

Exemplo de pfsync

Aqui tem um exemplo de configuração do pfsync.
# ifconfig pfsync0 syncdev em1
Isto habilita o pfsync na interface em1. Atualizações serão enviadas via multicast na rede, permitindo que qualquer outro host rodando pfsync recebê-las.

Combinando CARP e pfsync Para Failover

Combinando as características do CARP e pfsync, um grupo de dois ou mais firewalls podem ser usados para criar um cluster de firewall completamente redundante e com alta disponibilidade.
CARP:
Trata o failover automático de um firewall para outro.
pfsync:
Sincroniza a tabela de estados entre todos os firewalls. Caso aconteça um failover, o tráfego pode fluir ininterrupto através do novo firewall master.

Um exemplo. Dois firewalls, fw1 e fw2. +----| WAN/Internet |----+ | | em2| |em2 +-----+ +-----+ | fw1 |-em1----------em1-| fw2 | +-----+ +-----+ em0| |em0 | | ---+-------Shared LAN-------+---

Os firewalls estão conectados diretamente usando um cabo crossover em em1. Ambos estão conectados a LAN em em0 e a uma conexão WAN/Internet em em2. Endereços IP são como seguem:

A política de rede é que fw1 será o master preferido.

Configura o fw1:

! habilita preemption e grupo de interface failover # sysctl -w net.inet.carp.preempt=1 ! configura pfsync # ifconfig em1 10.10.10.1 netmask 255.255.255.0 # ifconfig pfsync0 syncdev em1 # ifconfig pfsync0 up ! configura CARP no lado LAN # ifconfig carp1 create # ifconfig carp1 vhid 1 carpdev em0 pass lanpasswd \ 172.16.0.100 netmask 255.255.255.0 ! configura CARP no lado WAN/Internet # ifconfig carp2 create # ifconfig carp2 vhid 2 carpdev em2 pass netpasswd \ 192.0.2.100 netmask 255.255.255.0

Configura o fw2:

! habilita preemption e grupo de interface failover # sysctl -w net.inet.carp.preempt=1 ! configura pfsync # ifconfig em1 10.10.10.2 netmask 255.255.255.0 # ifconfig pfsync0 syncdev em1 # ifconfig pfsync0 up ! configura CARP no lado LAN # ifconfig carp1 create # ifconfig carp1 vhid 1 carpdev em0 pass lanpasswd \ advskew 128 172.16.0.100 netmask 255.255.255.0 ! configura CARP no lado WAN/Internet # ifconfig carp2 create # ifconfig carp2 vhid 2 carpdev em2 pass netpasswd \ advskew 128 192.0.2.100 netmask 255.255.255.0

Assuntos Operacionais

Alguns assuntos operacionais comuns encontrados com CARP/pfsync.

Configurando o CARP e pfsync Durante o Boot

Visto que carp(4) e pfsync(4) são ambos tipos de interfaces de rede, eles podem ser configurados durante a inicialização criando-se um arquivo hostname.if(5). O script de inicialização netstart cuidará de criar as interfaces e configurá-las.

Exemplos:

/etc/hostname.carp1
inet 172.16.0.100 255.255.255.0 172.16.0.255 vhid 1 carpdev em0 \
    pass lanpasswd

/etc/hostname.pfsync0
up syncdev em1

Forçando Failover do Master

Podem existir algumas vezes que seja necessário o failover ou derrubar o nó master de propósito. Exemplos incluem derrubar o nó master para manutenção ou quando estiver resolvendo um problema. O objetivo aqui é elegantemente passar (fail over) o tráfego para um dos hosts backups de modo que os usuários não observem nenhum impacto.

Para failover de um grupo CARP em particular, derrube a interface carp(4) no nó master. Isto fará o master anunciar a si mesmo com um advbase e advskew "infinito". O(s) host(s) backup verá isto e imediatamente tomará o lugar do master.

# ifconfig carp1 down

Uma alternativa é aumentar o advskew para um valor mais alto que o advskew no(s) host(s) backup. Isto causará failover mas ainda permite o master participar no grupo CARP.

Um outro método para failover é ajustar o contador CARP demotion. O contador demotion é uma medida de como "pronto" um host esta para se tornar o master do grupo CARP. Por exemplo, enquanto um host esta no meio do processo de boot é uma má idéia para ele se tornar um master CARP até que todas as interfaces estejam configuradas, todos os serviços de rede estejam iniciados, etc. Hosts anunciando um valor demotion alto terão menos preferência como master.

Um contador demotion é armazenado em cada grupo de interface que a interface CARP pertence. Por padrão, todas a interfaces CARP são membros do grupo de interface "carp". O valor atual de um contador demotion pode ser visto usando o ifconfig(8):

# ifconfig -g carp
carp: carp demote count 0

Neste exemplo o contador associado com o grupo de interface "carp" é mostrado. Quando um host CARP anuncia a si mesmo na rede, ele pega a soma dos contadores demotion para cada grupo de interface que a interface carp(4) pertence e anuncia este valor como seu valor demotion.

Agora assuma o seguinte exemplo. Dois firewalls rodando CARP com as seguintes interfaces CARP:

O objetivo é apenas fazer failover dos grupos carp1 e carp2 para o firewall secundário.

Primeiro, associe cada grupo a um novo grupo de interface, neste caso chamado "internal":

# ifconfig carp1 group internal
# ifconfig carp2 group internal
# ifconfig internal
carp1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
     carp: MASTER carpdev em0 vhid 1 advbase 1 advskew 100
     groups: carp internal
     inet 10.0.0.1 netmask 0xffffff00 broadcast 10.0.0.255
carp2: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
     carp: MASTER carpdev em1 vhid 2 advbase 1 advskew 100
     groups: carp internal
     inet 10.0.1.1 netmask 0xffffff00 broadcast 10.0.1.255

Agora aumente o contador demotion para o grupo "internal" usando o ifconfig(8):

# ifconfig -g internal
internal: carp demote count 0
# ifconfig -g internal carpdemote 50
# ifconfig -g internal
internal: carp demote count 50

O firewall fará elegantemente o failover nos grupos carp1 e carp2 para o outro firewall no cluster, enquanto ainda se mantém como master nos grupos carp3 e carp4. Se o outro firewall começar a anunciar um valor demotion maior do que 50 ou se parar de anunciar completamente, então este firewall fará novamente o takeover do master nos grupos carp1 e carp2.

Para voltar (fail back) para o firewall primário, reverta as mudanças:

# ifconfig -g internal -carpdemote 50
# ifconfig -g internal
internal: carp demote count 0

Serviços de rede como OpenBGPD e sasyncd(8) fazem uso do contador demotion para garantir que o firewall não se torne master até que as sessões BGP estejam estabelecidas e SAs IPsec estejam sincronizados.

Dicas de Regras

Filtre a interface física. Até o ponto que o PF se interessa o tráfego da rede vem da interface física, não da interface virtual CARP (isto é, carp0). Assim, escreva seu conjunto de regras de acordo. Não se esqueça de que um nome de uma interface em uma regra do PF pode ser tanto o nome da interface física ou um endereço associado com esta interface. Por exemplo, esta regra poderia estar correta:
pass in on fxp0 inet proto tcp from any to carp0 port 22
mas substituindo o fxp0 por carp0 não funcionaria como você deseja.

NÃO se esqueça de uma regra pass para proto carp e proto pfsync!

Outras Referências

Por favor veja estas outras fontes para mais informação:

[Anterior: Shell de Usuário para Atutenticação em Gateways] [Conteúdo] [Próximo: Firewall para Casa ou Pequeno Escritório]


[back] www@openbsd.org
$OpenBSD: carp.html,v 1.10 2007/12/16 17:18:35 tobias Exp $