[Anterior: Redundância de Firewall com CARP e pfsync] [Conteúdo]
[ COMP1 ] [ COMP3 ] | | ADSL ---+------+-----+------- fxp0 [ OpenBSD ] ep0 -------- ( Internet ) | [ COMP2 ]
Existem vários computadores na rede interna; o diagrama mostra apenas três, mas o número real é irrelevante. Estes computadores são estações de trabalho usadas para navegar na Internet, ler email, chat, etc., exceto COMP3 que também roda um pequeno servidor web. A rede interna usa a faixa de ips 192.168.0.0 / 255.255.255.0.
O roteador OpenBSD é um Pentium 100 com duas placas de rede: uma 3com 3c509B (ep0) e uma Intel EtherExpress Pro/100 (fxp0). O roteador possui uma conexão ADSL para a Internet e faz NAT para compartilhar sua conexão com a rede interna. O endereço IP na interface externa é atribuído dinamicamente pelo Provedor de Acesso Internet.
int_if = "fxp0"
ext_if = "ep0"
tcp_services = "{ 22, 113 }"
icmp_types = "echoreq"
priv_nets = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }"
comp3 = "192.168.0.3"
As primeiras duas linhas definem a interface de rede onde a filtragem acontecerá. A terceira e quarta linhas listam os números de portas TCP dos serviços que serão abertos para a internet (SSH e ident/auth) e os tipos de pacotes ICMP que terão permissão de alcançar a máquina do firewall. A quinta linha define os endereços de loopback e blocos de endereçamento descritos na RFC 1918. Finalmente, a última linha define o endereço IP de COMP3.
Nota: Caso a conexão ADSL com a Internet necessite PPPoE, então, filtragem e NAT devem acontecer na interface tun0 não em ep0.
set block-policy return
set loginterface $ext_if
scrub in all
nat on $ext_if from $int_if:network to any -> ($ext_if)
Já que o endereço IP da interface externa é atribuído dinamicamente, parênteses devem ser colocados em volta da interface, assim o PF notará qualquer alteração no endereço.
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021
Note que esta regra funcionará apenas com conexões destinadas à porta 21. Caso usuários se conectem a servidores FTP em outras portas, então uma lista deve ser utilizada para especificar as portas de destino, por exemplo: from any to any port { 21, 2121 }.
A segunda regra de redirecionamento pega qualquer tentativa de conexão vinda da Internet em direção à porta 80 TCP no firewall. Tentativas de conexões legítimas nesta porta serão de usuários tentando acessar o servidor web da rede. Estas conexões devem ser redirecionadas para COMP3:
rdr on $ext_if proto tcp from any to any port 80 -> $comp3
block all
Neste ponto nada passará através do firewall, nem mesmo da rede interna. As regras seguintes abrem o firewall de acordo com os objetivos acima descritos, bem como quaisquer interfaces virtuais que se façam necessárias.
Todo sistema Unix possui uma interface de "loopback". É uma interface de rede virtual utilizada por aplicações para se comunicarem entre si dentro do sistema. Em geral, todo tráfego na interface loopback deve ser aceito. No OpenBSD a interface de loopback é lo(4).
pass quick on lo0 all
Depois, os endereços RFC 1918 serão bloqueados, tanto para entrada quanto saída na interface externa. Estes endereços nunca devem aparecer na Internet, portanto, filtra-los nos certificará de que o roteador não deixará "escapar" estes endereços para fora da rede interna e também bloqueará qualquer pacote vindo da Internet com qualquer desses endereços de origem.
block drop in quick on $ext_if from $priv_nets to any
block drop out quick on $ext_if from any to $priv_nets
Note que block drop é usado, dizendo ao PF para não responder com um pacote TCP RST ou ICMP Unreachable. Já que endereços da RFC 1918 não existem na Internet, quaisquer pacotes enviados para estes endereços nunca alcançarão seu destino. A opçao quick é utilizada, informando ao PF para não se preocupar em avaliar o restante das regras de filtragem caso uma das regras acima case com o pacote; pacotes de ou para as redes $priv_nets serão descartados imediatamente.
Agora abrimos as portas usadas pelos serviços que estarão disponíveis para a Internet:
pass in on $ext_if inet proto tcp from any to ($ext_if) \
port $tcp_services flags S/SA keep state
Especificando as portas na macro $tcp_services torna-se simples abrir mais portas para a Internet caso necessário, editando simplesmente a macro e recarregando as regras. Serviços UDP também podem ser abertos criando-se uma macro $udp_services e adicionando uma regra de filtragem similar à regra acima, que especifique proto udp.
Além de ter uma regra rdr que redireciona o tráfego para COMP3, DEVEMOS também autorizar esse tráfego através do firewall:
pass in on $ext_if proto tcp from any to $comp3 port 80 \
flags S/SA synproxy state
Para aumentar um pouco a segurança, faremos uso de TCP SYN Proxy para proteger ainda mais o servidor web.
Para que conexões FTP ativas funcionem fora da LAN, a seguinte regra deve existir, passando a conexão ftp-data iniciada pelo servidor FTP de volta para o cliente. Como as conexões FTP estão utilizando ftp-proxy, ele mesmo terá o trabalho de aceitar as conexões ftp-data e repassa-las para o cliente na LAN.
pass in on $ext_if inet proto tcp from port 20 to ($ext_if) \
user proxy flags S/SA keep state
Agora tráfego ICMP deve ser permitido:
pass in inet proto icmp all icmp-type $icmp_types keep state
Similar à macro $tcp_services, a macro $icmp_types pode ser facilmente editada para alterar os tipos de pacotes ICMP que terão permissão de alcançar o firewall. Note que esta regra se aplica a todas interfaces de rede.
Tráfego de e para a rede interna deve ser permitido. Assumiremos que usuários da rede interna sabem o que estão fazendo e não nos causarão problemas. Esta não é necessariamente uma suposição válida; um conjunto de regras bem mais restritivas é apropriado para a maioria dos ambientes computacionais.
pass in on $int_if from $int_if:network to any keep state
As regras acima permitem a qualquer máquina interna enviar pacotes através do firewall, contudo, não permite que o próprio firewall inicie qualquer conexão com uma máquina da rede interna. Isso é uma boa idéia? Depende dos detalhes precisos de configuração da rede. Caso o firewall seja também um servidor DHCP, ele precisa "pingar" um endereço para verificar sua disponibilidade antes de atribuí-lo a uma máquina. Permitir ao firewall se conectar à rede interna também dá permissão a alguém com uma conexão ssh no firewall pela Internet para acessar máquinas da rede interna. Tenha em mente que não permitir ao firewall se comunicar com a rede interna não traz um grande benefício em segurança; de qualquer modo, caso alguém consiga acesso ao firewall, essa pessoa provavelmente pode alterar as regras de filtragem. Adicionando a regra a seguir, o firewall poderá iniciar conexões com a rede interna.
pass out on $int_if from any to $int_if:network keep state
Note que se ambas as linhas estiverem presentes, a opção keep state não se faz necessária; todos pacotes passarão pela interface interna, isso porquê existem regras para passar os pacotes em ambas as direções. Contudo caso a linha pass out não exista a linha pass in deve incluir keep state. Existe além disso um ganho de performance mantendo-se o estado da conexão: as tabelas de estado (State tables) são verificadas antes das regras serem avaliadas, e caso um pacote combine com alguma entrada na tabela, o mesmo passa pelo firewall sem ser avalidado pelas regras. Isso oferece ganho de performance num firewall muito carregado, mas num sistema simples como este não trará benefícios visíveis.
Finalmente, permitimos tráfego na interface externa:
pass out on $ext_if proto tcp all modulate state flags S/SA
pass out on $ext_if proto { udp, icmp } all keep state
Tráfego TCP, UDP e ICMP é permitido sair do firewall em direção à Internet. Informação de estado das conexões é mantido para que os pacotes de retorno passem direto pelo firewall.
# macros int_if = "fxp0" ext_if = "ep0" tcp_services = "{ 22, 113 }" icmp_types = "echoreq" priv_nets = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }" comp3 = "192.168.0.3" # opções set block-policy return set loginterface $ext_if # scrub scrub in all # nat/rdr nat on $ext_if from $int_if:network to any -> ($ext_if) rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 \ port 8021 rdr on $ext_if proto tcp from any to any port 80 -> $comp3 # regras de filtragem block all pass quick on lo0 all block drop in quick on $ext_if from $priv_nets to any block drop out quick on $ext_if from any to $priv_nets pass in on $ext_if inet proto tcp from any to ($ext_if) \ port $tcp_services flags S/SA keep state pass in on $ext_if proto tcp from any to $comp3 port 80 \ flags S/SA synproxy state pass in on $ext_if inet proto tcp from port 20 to ($ext_if) \ user proxy flags S/SA keep state pass in inet proto icmp all icmp-type $icmp_types keep state pass in on $int_if from $int_if:network to any keep state pass out on $int_if from any to $int_if:network keep state pass out on $ext_if proto tcp all modulate state flags S/SA pass out on $ext_if proto { udp, icmp } all keep state |
[Anterior: Redundância de Firewall com CARP e pfsync] [Conteúdo]