NewsGeneration: um serviço oferecido pela RNP desde 1997


ISSN 1518-5974
Boletim bimestral sobre tecnologia de redes
produzido e publicado pela  RNP – Rede Nacional de Ensino e Pesquisa
13 de novembro de 1998 | volume 2, número 8

volta à página inicial de NewsGeneration

Nesta edição:

NewsGeneration:



IPFW no Linux

Antonio Paulo Salgado Forster <>

Rede Nacional de Ensino e Pesquisa (RNP)

Introdução ao IPFW
Preparação
Inclusão de regras
Configuração do SYSLOGD
Conclusão
Sites relacionados

IPFW é um filtro de pacotes nativo no kernel de alguns sistemas operacionais - entre eles, o Linux e o FreeBSD, - sistemas abertos bem conhecidos.
Um administrador pode elevar o nível de proteção de sua rede interna, caso o IPFW seja instalado no gateway da mesma. Até mesmo um usuário preocupado com segurança pode utilizá-lo para proteger seu próprio PC, rodando Linux, de conexões indesejáveis.
Por ser parte de pacotes de software de livre distribuição, nenhum dos dois terá algum ônus financeiro por utilizar este filtro.
O Linux tem sido amplamente utilizado e, diga-se de passagem, de forma bastante inconseqüente; muitos administradores costumam deixá-lo totalmente aberto, sem nenhum tipo de proteção, fazendo com que o sistema fique vulnerável a possíveis ataques. O intuito deste artigo é mostrar como instalar e configurar o IPFW neste sistema operacional pode ser fácil.

^

Introdução ao IPFW

Por ser um filtro de pacotes, o IPFW só pode decidir aceitar um determinado pacote ou rejeitá-lo baseando-se nos dados a que tem acesso - os cabeçalhos dos protocolos da família TCP/IP. O IPFW não pode, por exemplo, perceber a passagem de um applet maligno em Java, ou detectar que uma conexão IMAP está normal enquanto outra está sendo feita pra explorar um bug do servidor. Ele apenas analisa os dados presentes no cabeçalho dos pacotes, e não a sua área de dados.

Tendo feito a análise dos dados do pacote, o IPFW decide, baseado nas regras inseridas pelo administrador, se o pacote será aceito, rejeitado, aceito e "logado" ou rejeitado e "logado". Se a opção de log estiver ativada, uma mensagem será enviada ao syslogd, registrando os dados do pacote.

Um detalhe importante é que, ao contrário do TCP Wrapper, que só registra conexões que foram iniciadas corretamente, o IPFW registra qualquer tentativa, mesmo que o TCP 3-Way Handshake não tenha sido completado. Desta forma, mesmo os famosos Stealth Scans podem ser detectados. Outra vantagem é que o IPFW, estando corretamente configurado, registrará pacotes de qualquer protocolo direcionados a qualquer porta, e não somente a serviços controlados pelo inetd. A desvantagem é que ele só fornecerá informações sobre os pacotes "logados" de forma independente.

^

Preparação

O IPFW age no kernel e, portanto, deverá ser ativado no próprio núcleo do Linux. Para tal, o mesmo deverá ser re-compilado. Este é o assunto desta seção.

Já que a recompilação do kernel deverá ser feita, não há por que não utilizar a última versão, atualmente a 2.0.35. Ela pode ser encotrada em vários Sunsite's pelo mundo afora.

Tendo o novo kernel (linux-2.0.35.tar.gz), ele deve ser descomprimido no diretório /usr/src, "lado a lado" com o antigo. O usuário deverá, então, entrar no diretório desse novo kernel e configurá-lo com as opções necessárias para sua máquina (tipos de discos, interfaces, filesystems, etc.) e com as opções para que o IPFW esteja ativo nesse novo kernel. A configuração pode ser feita de três formas: em modo texto, através do modo gráfico, ou em modo texto com o uso de menus. Para fazer a configuração com a interface gráfica, o usuário deverá ter um servidor X rodando, além do interpretador TK chamado wish (normalmente localizado em /usr/bin/wish). Já para montar a configuração em modo texto com uso de menus, o sistema deverá contar com a biblioteca de rotinas ncurses(3).

Na seção Networking Options, as opções devem ser configuradas conforme abaixo (não cobriremos, neste artigo, o processo completo de recompilação do kernel - somente os aspectos que dizem respeito diretamente ao IPFW):

Yes

Network firewalls

Yes

TCP/IP networking

Yes

IP: firewalling

Yes

IP: firewall packet logging

Yes

IP: accounting

Yes

IP: Drop source routed frames

Feita a configuração, o núcleo deve ser compilado da seguinte forma:

Observação: os passos assinalados acima só devem ser executados se a opção de módulos no kernel foi utilizada.

Caso o usuário tenha gerado o novo núcleo com o comando make bzImage install, ele deverá executar /sbin/lilo para que o próximo boot seja feito com o novo kernel.

^

Inclusão de regras

A inclusão de regras no IPFW do Linux é normalmente feita através de um software chamado ipfwadm, incluído na distribuição do Linux. Abaixo explicamos sua utilização através de um exemplo de configuração do IPFW para proteger uma máquina que seja utilizada somente como desktop e servidora de correio eletrônico.

O ipfwadm, como o próprio nome diz, faz a administração do IPFW. Este software permite que regras de entrada, saída, forwarding (com ou sem masquerading) e accounting sejam inseridas, removidas e verificadas. O ipfwadm pode ser utilizado em linha de comando, mas normalmente várias linhas são agrupadas em um arquivo batch que é executado durante a inicialização da máquina. Sua sintaxe, apesar de parecer complexa, pode ser facilmente entendida após uma leitura das páginas de manuais (manpage), que explicam detalhadamente seus parâmetros e combinações. É aconselhável que o administrador leia tais páginas para uma boa compreensão do exemplo abaixo.


# Executa um flush (apaga) regras anteriores de entrada, accounting e saida ativas
/sbin/ipfwadm -I -f
/sbin/ipfwadm -A -f
/sbin/ipfwadm -O -f

# Configura a política default de entrada de pacotes como deny.
/sbin/ipfwadm  -I -p deny

# Faz o accouting de todo o trafego
/sbin/ipfwadm -A -i        -P all  -S 0.0.0.0/0   -D 0.0.0.0/0 

# Permite a entrada pacotes com endereco origem 127.0.0.1 somente pela interface de loopback
/sbin/ipfwadm -I -i accept -P all  -S 127.0.0.1   -D 127.0.0.1                -W lo0  
/sbin/ipfwadm -I -a deny   -P all  -S 127.0.0.1    D 127.0.0.1                -W eth0

# Permite a entrada de pacotes ICMP com somente mensagens de Echo Reply, 
# Destination Unreachable, e Echo, gerando logs dos pacotes rejeitados.
/sbin/ipfwadm -I -i accept -P icmp -S 0.0.0.0/0 0   -D 0.0.0.0/0              -W eth0
/sbin/ipfwadm -I -a accept -P icmp -S 0.0.0.0/0 3   -D 0.0.0.0/0              -W eth0
/sbin/ipfwadm -I -a accept -P icmp -S 0.0.0.0/0 8   -D 0.0.0.0/0              -W eth0
/sbin/ipfwadm -I -a deny   -P icmp -S 0.0.0.0/0     -D 0.0.0.0/0           -o -W eth0 

# Permite a entrada de pacotes TCP com o bit ACK ativo - melhora a performance do filtro
# (Pode nao ser uma boa ideia por permitir certos tipos de stealth scans)
/sbin/ipfwadm -I -a accept -P tcp  -S 0.0.0.0/0     -D 0.0.0.0/0              -W eth0 -k

# Permite a entrada de pacotes TCP destinados aos seguintes servicos
# FTP, SSH, SMTP e AUTH, gerando logs de pacotes destinados a qualquer outra porta
# privilegiada abaixo de 1021.
/sbin/ipfwadm -I -a accept -P tcp  -S 0.0.0.0/0     -D 0.0.0.0/0 20           -W eth0
/sbin/ipfwadm -I -a accept -P tcp  -S 0.0.0.0/0     -D 0.0.0.0/0 21           -W eth0
/sbin/ipfwadm -I -a accept -P tcp  -S 0.0.0.0/0     -D 0.0.0.0/0 22           -W eth0
/sbin/ipfwadm -I -a accept -P tcp  -S 0.0.0.0/0     -D 0.0.0.0/0 25           -W eth0
/sbin/ipfwadm -I -a accept -P tcp  -S 0.0.0.0/0     -D 0.0.0.0/0 113          -W eth0
/sbin/ipfwadm -I -a deny   -P tcp  -S 0.0.0.0/0     -D 0.0.0.0/0 0:1021    -o -W eth0

# Bloqueia conexoes as portas TCP 2049 (NFS), 2766 (System V Listener), e de
# 6000 ate 6010 (Xwindows), gerando logs dos pacotes rejeitados.
/sbin/ipfwadm -I -a deny   -P tcp  -S 0.0.0.0/0     -D 0.0.0.0/0 2049      -o -W eth0
/sbin/ipfwadm -I -a deny   -P tcp  -S 0.0.0.0/0     -D 0.0.0.0/0 2766      -o -W eth0
/sbin/ipfwadm -I -a deny   -P tcp  -S 0.0.0.0/0     -D 0.0.0.0/0 6000:6010 -o -W eth0

# Permite pacotes UDP com origem na porta 53 (DNS), pacotes com origem e destino na
# porta 123 (NTP) e pacotes com destino a porta 7070 (Real Audio), gerando logs de
# qualquer pacote fora dessas caracteristicas.
/sbin/ipfwadm -I -a accept -P udp  -S 0.0.0.0/0 53  -D 0.0.0.0/0              -W eth0
/sbin/ipfwadm -I -a accept -P udp  -S 0.0.0.0/0 123 -D 0.0.0.0/0 123          -W eth0
/sbin/ipfwadm -I -a accept -P udp  -S 0.0.0.0/0     -D 0.0.0.0/0 7070         -W eth0
/sbin/ipfwadm -I -a deny   -P udp  -S 0.0.0.0/0     -D 0.0.0.0/0           -o -W eth0


Conforme constatado no exemplo acima, o flag -o indica que a regra deverá gerar logs de pacotes bloqueados ou permitidos por ela. Já o flag -W determina em qual interface a regra deve ser aplicada.

É importante citar que, assim como nas Access Lists de roteadores Cisco, as regras mais genéricas - como deny all - devem ficar por último, enquanto as mais particulares devem ser as primeiras.

^

Configuração do SYSLOGD

Como foi visto acima, o IPFW possui a capacidade de gerar logs de pacotes rejeitados ou aceitos. Nesta seção, mostraremos como receber essas mensagens corretamente, além de alguns exemplos.

Já que o IPFW trabalha no kernel do Linux, é de se esperar que as mensagens enviadas sejam do tipo "kern.XxXx". E, realmente, são: kern.info. Portanto, o recebimento correto dessas mensagens dependerá de uma entrada no arquivo de configuração do syslogd, o /etc/syslog.conf, apontando para onde mensagens com essa prioridade deverão ser direcionadas.

 
kern.info                               /var/log/ipfw

Essas mensagens poderiam também ser direcionadas a um programa que já faria a análise dos logs, direcionando-os para um e-mail, outro arquivo, ou separando o que é relevante do que não é.

 
kern.info                               |/usr/local/bin/ipfw-log-parser 

No caso de versões do syslog que não aceitem jogar as mensagens diretamente em um pipe, através do comando mkfifo (1) pode-se criar um arquivo que nada mais é que um pipe; um script leria o output desse pipe, recebendo as mensagens.

 
kern.info                               /etc/ipfw-pipe


Temos, abaixo, alguns exemplos de logs gerados pelo IPFW do Linux:

 
Oct 13 16:01:23 host kernel: IP fw-in acc eth0 TCP 172.16.18.5:51328 10.5.19.26:113
        L=44 S=0x00 I=52191 F=0x0040 T=254 
Oct 13 17:01:23 host kernel: IP fw-in acc eth0 TCP 172.16.18.5:51331 10.5.19.26:113 
        L=44 S=0x00 I=47511 F=0x0040 T=254 
Oct 13 17:10:51 host kernel: IP fw-in deny eth0 TCP 172.16.18.5:51332 10.5.19.26:23 
        L=44 S=0x00 I=43295 F=0x0040 T=254 
Oct 13 17:11:04 host kernel: IP fw-in deny eth0 TCP 172.16.18.5:51333 10.5.19.26:23 
        L=44 S=0x00 I=43297 F=0x0040 T=254 
Oct 19 09:45:23 host kernel: IP fw-in deny eth0 UDP 10.81.57.124:34031 10.5.19.26:6979 
        L=520 S=0x00 I=65367 F=0x0040 T=246
Oct 19 09:49:23 host kernel: IP fw-in deny eth0 UDP 10.81.57.124:34038 10.5.19.26:7000 
        L=530 S=0x00 I=7124 F=0x0040 T=246 
Oct 19 09:49:23 host kernel: IP fw-in deny eth0 UDP 10.81.57.124:34038 10.5.19.26:7000 
        L=520 S=0x00 I=7125 F=0x0040 T=246 

Nos exemplos acima, podemos perceber que houve duas conexões originadas na máquina 172.16.18.5 com destino à porta 113/tcp (auth), que foram permitidas e logadas. Depois disso, mais duas conexões partindo da mesma máquina com destino à porta 23/tcp (telnet) que foram bloqueadas. E por último, três pacotes UDP com destino às portas 6979 e 7000 de 10.81.57.124 que foram bloqueados.

Abaixo, temos um exemplo bem primitivo de um sistema em Perl que faria a análise dos logs, tentando separar registros importantes daqueles de menor importância. Os logs de conexões negadas a certas portas serão enviados. por e-mail, ao administrador da rede.

Script 1
Deve ser executado como daemon, lendo os dados enviados pelo IPFW ao syslogd, que os redireciona a um pipe em /etc/ipfw-log-pipe.


#!/bin/perl -T

# Script que sera executado como daemon para capturar as mensagens do IPFW 
# enviadas pelo syslogd ao pipe criado com o comando mkfifo(1) 

# Localizacao do arquivo de spool
$denies = "/tmp/denies";

# Abre o pipe para leitura
open PIPE, "/etc/ipfw-log-pipe";

# Abre arquivo de log para escrita
open IPFW, ">/var/log/ipfw";

# Abre o spool de mensagens de deny para escrita
open DENIES, ">$denies";

# Entra em loop infinito
while (1) {

        # Le mensagem
        $log=<PIPE>;

        # Verifica se a mensagem vem do IPFW  
        if ($log=~/IP\sfw-/g) {

           # Testa mensagem: Se "deny", enviar para ipfw e para spool
           if ($log=~/deny/) {print DENIES $log; print IPFW $log;}

           # Se "permit", envia somente para ipfw
           else      {print IPFW $log;}

           }
        }

Script 2
Deve ser executado pelo crontab do root periodicamente (10 em 10 minutos, por exemplo). Esse script fará a análise dos logs, enviando e-mail para o administrador no caso de encontrar conexões consideradas perigosas.


#!/bin/perl -T

# Localizacao do arquivo de spool
$denies = "/tmp/denies";

# Abre arquivo para leitura
open DENIES, $denies;

# Invalida PATH do UID do processo
undef $ENV{'PATH'};

# Carrega logs no array @logs;
@logs = <DENIES>;

foreach $log (@logs) {

   # Se TCP ou UDP
   if ($log!~/ICMP/g) {

      # Obtem IP origem, protocolo e Porta destino
      ($prot, $src, $dst) = (split /\s+/, $log)[9,10,11];
      ($src_host) = $src =~ /([\d+|\.]+):/;
      ($dst_port) = $dst =~ /:(\d+)/;
      $dst_port=" ".$dst_port." /".$prot;

      # Se a porta destino for 23, 110, 111, 119, 143, 513, 514, 31337, 
      # 12345, ou de 6000 a 6009, armazena dados da conexao.
      if ($dst_port=~/\s(23|110|111|119|143|513|514|31337|12345|600\d)\s/g) {
                $dst_port=~s/\s//g;
                $$src_host{$dst_port}++;
                $hosts{$src_host}=1;
                }
      }

   else {

      # Se ICMP armazena IP de origem e tipo de ICMP
      ($type, $src) = (split /\s+/, $log)[9,10];
      $$src_host{$type}++;
      }

  }

# Reset no array contendo os logs
undef (@logs);

# Apaga spool
unlink $denies;

# Abre pipe para sendmail
open MAIL, "| /usr/lib/sendmail -t";

print MAIL "To: root\n";
print MAIL "Subject: Tentativas de acesso negadas\n\n";

# Inicia loop, selecionando todos os host registrados como "perigosos"
foreach $host (keys %hosts) {

   $total = 0;

   # Inicia loop selecionando os servicos buscados por cada host
   foreach $serv (keys %$host) {

      # Imprime linha na mensagem, discriminando a tentativa
      print MAIL $host." -> ($serv) $$host{$serv} tentativas\n";

      # Incrementa o total de conexoes desse host
      $total+=$$host{$serv};
      }

     # Imprime na mensagem o total de tentativas do host
   print MAIL $host." TOTAL: $total tentativas negadas\n\n";

   }

# Envia mensagem
close MAIL;

# Fim
exit;

Os scripts acima enviarão mensagens como a transcrita abaixo, caso conexões perigosas sejam detectadas:


Date: Mon, 9 Nov 1998 21:04:19 -0200
From: root@cais.rnp.br
To: root@cais.rnp.br
Subject: Tentativas de acesso negadas

123.45.67.89 -> (143/TCP) 1 tentativa(s)
123.45.67.89 TOTAL: 1 tentativa(s) negada(s)

234.56.78.90 -> (ICMP/8) 38 tentativa(s)
234.56.78.90 -> (23/TCP) 4 tentativa(s)
234.56.78.90 TOTAL: 42 tentativa(s) negada(s)

135.24.67.89 -> (31337/UDP) 2 tentativa(s)
135.24.67.89 TOTAL: 2 tentativa(s) negada(s)

AVISO: O administrador poderá sofrer um mail-bombing de seu próprio sistema no caso de um ataque muito longo. Por isso, alguns administradores preferem não utilizar esse tipo de sistema de alerta.

^

Conclusão

O IPFW pode auxiliar bastante na proteção de máquinas rodando Linux, mas não executará tarefa alguma sozinho. É necessário que o administrador mantenha sempre a atenção voltada à análise dos logs para detectar qualquer tentativa de intrusão, assim como verificar se os filtros estão desempenhando seu papel corretamente. No caso da máquina ser um application level gateway, é interessante que algum sistema de procuradores (proxies), como o TIS , seja instalado, em vez de simplesmente permitir o repasse de pacotes. Nesse caso, seria interessante que esta máquina não fosse um dos roteadores, e sim, um servidor bastião que estivesse dentro da DMZ (Rede Desmilitarizada).

[Servidor Bastiao] | | Internet--[Roteador Externo]--+--[Roteador Interno]--Rede Interna

^

Sites relacionados

  Linux Firewall-HOWTO
TIS - Trusted Information Systems
PERL.COM

^

NewsGeneration, um serviço oferecido pela RNP – Rede Nacional de Ensino e Pesquisa
Copyright © RNP, 1997 – 2004