Revista Do Linux
 
  
  
 

  CD do Mês
  Capa
  Entrevista
  Estudo de Caso
  Curso de Java
  Comunidade
  Internacional
  Especial
assinantes
 

Bridges filtradas com FreeBSD

Nos *BSD, a maioria dos quesitos de segurança e serviços auxiliares são nativos, o que torna muito fácil sua utilização. Em nosso caso, estamos usando o FreeBSD 4.7, em máquina Pentium 166 com 48 mB de RAM (Itautec Infoway), e o IPFW.

Em primeiro lugar: pra que haveríamos de querer um treco desses aí? Será que um firewall convencional não atende nossas necessidades? Bem, de fato a Bridge filtrada é medida adicional de segurança, algo que não vai pesar no orçamento e oferece um grau adicional de dificuldade ao eventual script-kiddie ou "hacker", monstros sempre dispostos a tirar nosso sono e (se acessarem nossos servidores) colocar em risco o nosso caviar, as nossas festas anuais em Paris e as viagens mensais ao Epcot Center, coisinhas que todos nós, administradores de rede, nos esforçamos para oferecer às nossas famílias.

Embora a maioria dos colegas já saiba de cor e salteado o que é uma bridge filtrada, permita-me repetir os conceitos: Suponha que temos, de um lado, um link que nos liga (via roteador/modem ADSL/cable modem) à Internet e, de outro, a nossa máquina (o mais simples) OU um firewall fazendo NAT para um número qualquer de máquinas de nossa rede interna. Para efeito de exposição, vou me limitar ao caso mais simples, que consiste de uma conexão ADSL (Speedy), de um lado, e minha própria máquina, de outro, ficando a bridge entre elas. Veja a figura 1.

A rl2 é usada para controle, a partir de um notebook (por exemplo) ou outra máquina. O endereço dessa placa deve ser diferente de qualquer outro eventualmente existente em nossa rede, ou seja, se estamos com uma rede em 192.168.1.0, podemos estabelecer essa placa como estando em rede 192.168.10.0 (ou 172.30.0.0, ou 10.0.0.0). O que importa é que não seja acessível normalmente a partir de nossa própria rede, mesmo que no mesmo switch.

Supondo que há um modem ADSL entre a internet e a bridge. Aqui é que vão começar as diferenças entre um firewall convencional e a bridge filtrada:

roteador: 200.204.151.65/26 (é o modem ADSL)
cliente: 200.204.151.121/26 (máquina interna)

Se tivéssemos um firewall convencional no lugar da bridge, a rl0 deveria ter um endereço IP fixo, válido, enquanto a rl1 teria outro IP fixo, possivelmente um dos relacionados na RFC-1918, não roteável. A máquina cliente teria um IP dessa mesma classe/rede. Veja a figura 2.

Fazendo-se abstração completa do funcionamento disso tudo, vamos ao que interessa: A bridge não tem endereço em qualquer das placas. O conceito é de que tudo o que aparecer em uma delas é copiado para a outra. Contudo, antes de chegar à outra placa, vindo da Internet, o pacote de dados é analisado para saber se pode ou não atingir a máquina cliente. O pacote da máquina cliente poderá (ou não) sair para a Internet, e, se houver expectativa de respostas, será inserido em uma tabela. Isto nos permite montar um sistema de defesa mais sofisticado, como o da figura 3.

Neste caso, o firewall está também fazendo NAT para a(s) máquina(s) cliente(s). Resumo: alguém na Internet já disse que a bridge filtrada é um fio inteligente. E é isso mesmo. Um fio, sem endereços IP, que analisa os pacotes que por ela passam, bloqueando-os ou deixando-os passar, conforme as regras vigentes.

Optamos por um firewall do modelo fechado, ou seja, tudo é bloqueado, salvo aquilo que é expressamente autorizado a trafegar. Pode ser que existam defensores do outro método (tudo aberto, fecho o que não quero), mas prefiro o conceito de tudo fechado, autorizo o que quero. Assim, com certeza, não corro o risco de deixar aberto algum furo que eu não queria, mas que não lembrei de fechar.

Configurando o kernel

Será necessária a reconfiguração do kernel, habilitando a bridge e os itens relativos ao firewall. Veja o Quadro 1

O arquivo rc.conf também deverá ser modificado. Veja o Quadro 2.

O script de firewall (/etc/rc.firewall.bridge) não é o padrão da instalação, mas sim um script nosso (seguindo muitas sugestões de outros colegas). Note o fato de que as placas de rede rl0 e rl1 são ativadas, mas não recebem qualquer número IP, ao contrário de rl2, que recebe um endereço IP convencional, dos relacionados na RFC-1918.

Ufa, estamos quase lá! Crie um arquivo chamado sysctl.conf em /etc. Ou, caso o mesmo já exista, acrescente o conteúdo do Quadro 3. E veja no Quadro 4 nossas regras para o IPFW.

Os colegas podem notar que algumas dessas regras foram tomadas 'emprestadas' do rc.firewall original, existente em /etc. A idéia é manter tudo simples, sempre que for possível. As demais regras são bem simples, uma vez que o propósito desta bridge é ser uma plataforma de testes, para ampliarmos nosso conhecimento em filtragem de pacotes aplicada a bridges. Lógico, essas regras devem ser revisadas e estabelecidas de acordo com o melhor conhecimento de cada um dos colegas quanto às suas próprias necessidades, caso a Bridge venha a ser colocada em produção.

Há várias possibilidades de uso, como entre um roteador qualquer e um cliente qualquer. Em topologia mais sofisticada, a bridge ficaria entre o roteador e um firewall qualquer, ou ainda entre um firewall qualquer e uma rede qualquer. Sugiro que experimentem à vontade.

Para acessar a máquina que serve como bridge, basta estabelecer um 'alias' para sua placa convencional de rede, para a mesma rede 192.168.10.0 de rl2. Exemplo: ifconfig eth0:0 192.168.10.1 up (sintaxe Linux). Depois de terminado o trabalho, basta remover o alias e pronto, novamente invisível.

Todos já puderam perceber que a bridge é completamente inacessível (ou não?) a partir das interfaces rl0 e rl1, uma vez que não há um IP agregado a elas. Isso torna bastante difícil que ela seja 'invadida'. Contudo, o impossível é apenas algo que ainda não descobrimos como fazer. Tenha em mente que não existe nada seguro sob o sol, exceto a Morte.

Notas

  1. Supõe-se que o leitor já tenha o FreeBSD instalado e funcionando ou que saiba fazê-lo. Este artigo não é voltado ao completo leigo em FreeBSD.
  2. O autor não se responsabiliza por quaisquer danos ou perda de dados decorrentes das instruções contidas neste artigo. O leitor deve seguir estas instruções por sua própria conta e risco.
  3. O autor não oferece suporte a qualquer instalação que siga estas instruções como base, mesmo tendo tomado todo o cuidado para oferecer uma 'quase receita' que é perfeitamente reprodutível. Foram feitas diversas reinstalações, sempre com os mesmos resultados, portanto tudo deverá funcionar sem problemas.

Quadro 1

:============= begin
options         IPFIREWALL              #firewall
options         IPFIREWALL_VERBOSE      #print information about
#options        IPFIREWALL_FORWARD      #enable transparent proxy support
options         IPFIREWALL_VERBOSE_LIMIT=250    #limit verbosity
options RANDOM_IP_ID #-> vide LINT ;-)
# TCP_DROP_SYNFIN adds support for ignoring TCP packets with SYN+FIN. This
# prevents nmap et al. from identifying the TCP/IP stack, but breaks support
# for RFC1644 extensions and is not recommended for web servers.
#
options         TCP_DROP_SYNFIN         #drop TCP packets with SYN+FIN

# ICMP_BANDLIM enables icmp error response bandwidth limiting.   You
# typically want this option as it will help protect the machine from
# D.O.S. packet attacks.
#
options         ICMP_BANDLIM
# BRIDGE enables bridging between ethernet cards - see bridge(4).
# You can use IPFIREWALL and DUMMYNET together with bridging.
#
options         BRIDGE
:============= end

Quadro 2

:==== begin
### Basic network and firewall/security options: ###
firewall_enable="yes"  # Set to YES to enable firewall
# functionality
firewall_flags=""  # Flags passed to ipfw when type is
# a file
firewall_logging="yes"  # Set to YES to enable events
# logging
firewall_quiet="NO"  # Set to YES to suppress rule
# display
firewall_script="/etc/rc.firewall.bridge"  # Which script
# to run to set up the firewall
ifconfig_rl0="up"
ifconfig_rl1="up"
ifconfig_rl2="inet 192.168.10.10  netmask 255.255.255.0"
sshd_enable="YES"
:==== end

Quadro 3

#enablesbridge
net.link.ether.bridge=1
#tells bridge togo through the firewall
net.link.ether.bridge_ipfw=1
#tells bridge what interfaces are bridged
net.link.ether.bridge_cfg=rl0:1,rl1:1
#---finetunning  -> recolhido da internet

net.inet.tcp.sendspace=32768
net.inet.tcp.recvspace=32768
kern.ipc.somaxconn=1024
net.inet.icmp.drop_redirect=1
net.inet.icmp.log_redirect=1
net.inet.ip.redirect=0
net.inet6.ip6.redirect=0
net.inet.ip.sourceroute=0
net.inet.ip.accept_sourceroute=0
net.link.ether.inet.max_age=1200
net.inet.icmp.bmcastecho=0

Quadro 4

:=================== begin

#
# Setup system for firewall service.
#

# Suck in the configuration variables.
if [ -r /etc/defaults/rc.conf ]; then
        . /etc/defaults/rc.conf
        source_rc_confs
elif [ -r /etc/rc.conf ]; then
        . /etc/rc.conf
fi

############
# Set quiet mode if requested
#
case ${firewall_quiet} in
[Yy][Ee][Ss])
        fwcmd=»/sbin/ipfw -q»
        ;;
*)
        fwcmd=»/sbin/ipfw»
        ;;
esac

############
# Flush out the list before we begin.
#
${fwcmd} -f flush


############
# Only in rare cases do you want to change these rules
#
${fwcmd} add 100 pass all from any to any via lo0
${fwcmd} add 200 deny all from any to 127.0.0.0/8
${fwcmd} add 300 deny ip from 127.0.0.0/8 to any
# If you're using 'options BRIDGE', uncomment the following line to pass ARP
${fwcmd} add 400 pass udp from 0.0.0.0 2054 to 0.0.0.0
#----->
oif=rl0
iif=rl1
iic=rl2
        ${fwcmd} add check-state
        ${fwcmd} add deny log ip from 10.0.0.0/8 to any via ${oif}
        ${fwcmd} add deny log ip from 172.16.0.0/12 to any via ${oif}
        ${fwcmd} add deny log ip from 192.168.0.0/16 to any via ${oif}
        ${fwcmd} add pass udp from 200.204.151.121 to any keep-state
        ${fwcmd} add reject log all from 200.221.6.0/32 to any in via rl0
        ${fwcmd} add pass udp from any to any in via ${iif} keep-state
        ${fwcmd} add pass ip from any to any in via ${iif}
        ${fwcmd} add pass icmp from any to any
        ${fwcmd} add pass tcp from any to any established
        ${fwcmd} add pass tcp from any to any 49152-65535 in via ${oif}
        ${fwcmd} add pass tcp from any to any 113 in via ${oif}
        ${fwcmd} add pass tcp from any to any 22 in via ${oif}
        ${fwcmd} add pass tcp from any to any 22 via ${iic}
        ${fwcmd} add pass tcp from any to any 53 in via ${oif}
        ${fwcmd} add pass log tcp from any to any 25 in via ${oif}
#       ${fwcmd} add pass tcp from any to any 110 in via ${oif}
        ${fwcmd} add pass udp from any to any 49152-65535 in via ${oif}
#       ${fwcmd} add pass udp from any to any 53 in via ${oif}
        ${fwcmd} add deny log ip from any to any
#-->
:=================== end

Irado Furioso com Tudo - irado@nettaxi.com
Consultor autônomo para a segurança de redes, projeto e implementação de redes corporativas, servidores FreeBSD e Linux para alta demanda (web/mail), provedores Internet, intranet e extranet, Samba (substituição de servidores PDC Windows), firewalls e proxies

A Revista do Linux é editada pela Conectiva S/A
Todos os Direitos Reservados.

Política de Privacidade
Anuncie na Revista do Linux