[OpenBSD]

[Anterior: Shell de Usuário para Gateways de Autenticação] [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últiplas máquinas no mesmo segmento de rede compartilhem um endereço IP. CARP é uma alternativa livre e segura ao Protocolo de Redundância de Roteador Virtual (VRRP - "Virtual Router Redundancy Protocol") e ao Protocolo de Roteador de Espera a Quente (HSRP - "Hot Standby Router Protocol").

CARP funciona permitindo a um grupo de máquinas no mesmo segmento de rede compartilhar um endereço IP. Esse grupo de máquinas é referido como um "grupo de redundância". Ao grupo de redundância é atribuído um endereço IP que é compartilhado entre os membros do grupo. Dentro do grupo, uma máquina é designada como "mestre" e o resto como "backups". A máquina mestre é a que atualmente "segura" o IP compartilhado; ela responde a qualquer tráfego ou requisições ARP direcionadas a ele. Cada máquina pode pertencer a mais de 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. Caso o firewall mestre 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.

Funcionamento do CARP

A máquina mestre no grupo envia regularmente anúncios à rede local, assim as máquinas backup sabem que ela ainda está ativa. Se as máquinas backup não ouvirem um anúncio do mestre por um período de tempo, então uma delas tomará conta dos deveres do mestre (qualquer máquina backup com os valores mais baixos definidos para advbase e advskew).

É possível que múltiplos grupos CARP existam no mesmo segmento de rede. Anúncios CARP contêm o ID de Máquina Virtual (VHID - "Virtual Host ID") que permite aos membros do grupo identificar a que grupo de redundância pertencem.

Para prevenir que um usuário malicioso no segmento de rede falsifique 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 de permissão explícita no conjunto de regras de filtragem:

pass out on $carp_dev proto carp keep state

$carp_dev deve ser a interface física por onde o CARP se comunica.

Configuração do CARP

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

ifconfig carpN vhid vhid [pass senha] [carpdev carpdev] \
   [advbase advbase] [advskew advskew] [state estado] [group|-group grupo] \
   endereço_ip netmask máscara
carpN
O nome da interface virtual carp(4), onde N é um número inteiro que representa o número da interface (por exemplo, carp10).
vhid
O ID de Host Virtual. Esse é um número único que é usado para identificar o grupo de redundância aos outros nós no grupo e distingui-lo entre grupos numa mesma rede. Valores aceitos são de 1 a 255. Este valor deve ser o mesmo para todos os hosts percentes ao grupo.
senha
A senha de autenticação a usar quando estiver conversando com outras máquinas CARP nesse grupo de redundância. Deve ser a mesma para todos os membros do grupo.
carpdev
Esse parâmetro opcional especifica a interface de rede física que pertence a esse grupo de redundância. Por padrão, o CARP tenta determinar qual interface usar procurando pela interface física que está na mesma sub-rede da combinação endereço_ip e máscara dada à interface carp(4).
advbase
Esse 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 de 1 a 255.
advskew
Esse parâmetro opcional especifica o quanto desviar o advbase ao enviar anúncios CARP. Ao manipular o advskew, a máquina CARP mestre pode ser escolhida. Quanto mais alto o número, menos preferida será a máquina durante a escolha do mestre. O padrão é 0. Valores aceitos são de 0 a 254.
estado
Força uma interface carp(4) em um certo estado. Estados válidos são init, backup e master.
grupo
Adiciona ou remove uma interface carp(4) a um determinado grupo. Por padrão, todas as interfaces carp(4) são adicionadas ao grupo carp. Cada grupo tem um contador carpdemote englobando todas as interfaces daquele grupo. Como descrito abaixo, isso pode ser útil para agrupar determinadas interfaces juntas com propósito de utilizar failover.
endereço_ip
Esse é o endereço IP compartilhado atribuído ao grupo de redundância. Esse endereço não tem que estar na mesma sub-rede que o endereço IP na interface física (se presente). Esse endereço, contudo, precisa ser o mesmo em todas as máquinas no grupo.
máscara
A máscara de sub-rede do IP compartilhado.

Além disso, o comportamento do CARP pode ser controlado via sysctl(8).

net.inet.carp.allow
Aceita ou não a entrada de pacotes CARP. O padrão é 1 (sim).
net.inet.carp.preempt
Permite à máquinas dentro de um grupo de redundância que tenham melhores advbase e advskew tomarem o lugar do mestre. Adicionalmente, essa opção habilita "failing over" em um grupo de interfaces caso uma das interfaces venha a entrar em estado de shutdown. Se uma interface física CARP cair, o CARP incrementa o contador (carpdemote) nos grupos cuja interface física faz parte em 1, fazendo com que todas as outras interfaces possam assumir o failover juntas. Por padrão, net.inet.carp.preempt é 0 (desabilitada).
net.inet.carp.log
Registra mudanças de estado, pacotes mal formados e outros erros. O valor pode variar de 0 até 7, de acordo com propriedades do syslog(3). Por padrão, o valor usado é 2 (registra apenas mudanças de estado).

Exemplo de configuração do CARP

Este é 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

Isso configura o seguinte:

Executar o 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 do pf(4). Ao monitorar esse dispositivo usando o tcpdump(8), alterações na tabela de estados podem ser observadas em tempo real. Além disso, a interface pfsync(4) pode enviar essas mensagens de alterações de estados para a rede, de modo que outros nós executando o PF possam mesclar as alterações em suas próprias tabelas de estados. Da mesma forma, o pfsync(4) também pode ouvir a rede por mensagens que chegam.

Funcionamento 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. A prática mais comum é:

  1. Conectar os dois nós que trocarão atualizações com um cabo cruzado e usar a interface como o syncdev (veja abaixo).
  2. Usar a opção syncpeer do ifconfig(8) (veja abaixo), assim as atualizações são direcionadas com "unicast" para o nó, e então configurar o ipsec(4) entre as máquinas 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 no conjunto de regras de filtragem.

pass on $sync_if proto pfsync

$sync_if deve ser a interface física por onde o pfsync(4) se comunica.

Configuração do pfsync

Visto que pfsync(4) é uma interface de rede virtual, ela é configurada usando o ifconfig(8).
ifconfig pfsyncN syncdev syncdev [syncpeer syncpeer] [defer|-defer]
pfsyncN
O nome da interface pfsync(4). A 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
Esse parâmetro opcional especifica o endereço IP de uma máquina para trocar atualizações pfsync. Por padrão as atualizações pfsync são "multicast" na rede local. Essa opção cancela esse comportamento e, em vez disso, envia atualizações "unicasts" para o syncpeer especificado.
defer
Se a flag de defer for usada, o pacote inicial de uma nova conexão que passe através da firewall não será transmitido até que outro sistema com pfsync(4) reconheça sua adição na tabela de estados ou o tempo limite expire. Isto adiciona pequenos atrasos, mas permite ao tráfego fluir quando mais de um firewall pode estar, ativamente, manipulando pacotes ("ativo/ativo"). Por exemplo, em certos cenários e configurações com ospfd(8), bgpd(8) ou carp(4).

Exemplo de configuração do pfsync

Este é um exemplo de configuração do pfsync.
# ifconfig pfsync0 syncdev em1 up
Isso habilita o pfsync na interface em1. As atualizações enviadas serão "multicast" na rede, permitindo que qualquer outra máquina executando o pfsync possa recebê-las.

Combinando CARP e pfsync Para Failover

Ao combinar os recursos do CARP e do pfsync, um grupo de dois ou mais firewalls pode ser usado para criar um cluster de firewalls completamente redundante e de 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 mestre.

Um cenário de exemplo. Dois firewalls, fw1 e fw2.

         +----| WAN/Internet |----+
         |                        |
      em2|                        |em2
      +-----+                  +-----+
      | fw1 |-em1----------em1-| fw2 |
      +-----+                  +-----+
      em0|                        |em0
         |                        |
      ---+----LAN Compartilhada---+---

Os firewalls estão conectados diretamente com um cabo cruzado em em1. Ambos estão conectados à LAN em em0 e a uma conexão WAN/Internet em em2. Os endereços IP são os seguintes:

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

Configuração do fw1:
! Habilita a função de tomar o lugar e o failover de interface de grupo
# sysctl -w net.inet.carp.preempt=1

! Configura o pfsync
# ifconfig em1 10.10.10.1 netmask 255.255.255.0
# ifconfig pfsync0 syncdev em1
# ifconfig pfsync0 up

! Configura o 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 o 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 do fw2:
! Habilita a função de tomar o lugar e o failover de interface de grupo
# sysctl -w net.inet.carp.preempt=1

! Configura o pfsync
# ifconfig em1 10.10.10.2 netmask 255.255.255.0
# ifconfig pfsync0 syncdev em1
# ifconfig pfsync0 up

! Configura o 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 o 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

Problemas Operacionais

Alguns problemas operacionais comuns encontrados com CARP/pfsync.

Configuração do CARP e pfsync Durante a Inicialização

Visto que carp(4) e pfsync(4) são ambos tipos de interfaces de rede, elas podem ser configuradas 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 Mestre

De tempos em tempos é necessário fazer o "failover" ou derrubar o nó mestre de propósito. Exemplos incluem derrubar o nó mestre para manutenção ou quando estiver resolvendo um problema. O objetivo aqui é elegantemente passar ("fail over") o tráfego para uma das máquinas 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ó mestre. Isso faz com que o mestre anuncie a si mesmo com um advbase e advskew "infinito". A(s) máquina(s) backup vê(eem) isso e imediatamente toma(m) o lugar da máquina mestre.

# ifconfig carp1 down

Uma alternativa é aumentar o advskew para um valor mais alto que o advskew na(s) máquina(s) backup. Isso causa um failover, mas ainda permite ao mestre participar no grupo CARP.

Um outro método para failover é ajustar o contador demotion do CARP. O contador demotion é uma medida de como "pronta" uma máquina está para se tornar o mestre do grupo CARP. Por exemplo, enquanto uma máquina está no meio do processo de inicialização é uma má ideia para ela tornar-se um mestre CARP até que todas as interfaces estejam configuradas, todos os serviços de rede estejam iniciados, etc. Máquinas anunciando um valor demotion alto terão menos preferência como mestre.

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

# ifconfig -g carp
carp: carp demote count 0

Nesse exemplo o contador associado com o grupo de interface "carp" é mostrado. Quando uma máquina CARP anuncia a si mesma na rede, ela pega a soma dos contadores demotion para cada grupo de interfaces que a interface carp(4) pertence e anuncia esse valor como seu valor demotion.

Agora assuma o seguinte exemplo. Dois firewalls executando 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 interfaces, neste caso nomeado como "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 agora faz elegantemente o failover nos grupos carp1 e carp2 para o outro firewall no cluster, enquanto ainda se mantém como mestre 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 esse firewall tomaria novamente a liderança do mestre 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

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

Dicas de Conjunto de Regras

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

NÃO se esqueça de uma regra de permissão de tráfego para proto carp e proto pfsync!

Outras Referências

Por favor veja estas outras fontes para obter mais informações:

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


[voltar] www@openbsd.org
$OpenBSD: carp.html,v 1.15 2013/01/18 07:15:55 ajacoutot Exp $