Criando firewalls dinâmicos com Iptables Recent

Não seria interessante montar um firewall com regras dinâmicas que permitisse por exemplo, bloquear algum IP por ter tentado acessar o serviço de SSH mais de 3 vezes em menos de 1 minuto? Ou ainda criar alguma logística de batidas de porta e só assim permitir a entrada da conexão ao IP que acertou a combinação de portas!? Tudo isso e muito mais é possível com o módulo recent do Netfilter.

[ Hits: 33.518 ]

Por: Marcelo Moreira de Mello em 19/12/2009 | Blog: http://tchellomello.blogspot.com


Introdução



Não seria interessante montar um firewall com regras dinâmicas que permitisse por exemplo, bloquear algum IP por ter tentado acessar o serviço de SSH mais de 3 vezes em menos de 1 minuto? Ou ainda criar alguma logística de batidas de porta (é!!! igual ao famoso tãn tãn rãn rãn tãn... tãntãn) e só assim permitir a entrada da conexão ao IP que acertou a combinação de portas!? Tudo isso e muito mais é possível com o módulo recent do Netfilter.

Para começarmos, criei uma máquina virtual chamada guardiao.home onde iremos utilizar como cenário para demonstrar a utilização do módulo recent.

# hostname
guardiao.home
# ifconfig eth0 | grep "inet addr"
inet addr:192.168.122.97 Bcast:192.168.122.255 Mask:255.255.255.0

Objetivo: Permitir apenas 1 conexão via SSH no período de 2 minutos por origem.

Para iniciarmos, criaremos uma regra que permite tudo que for de entrada para a interface de loopback, uma segunda regra para permitir todas conexões estabelecidas ou originadas pela própria máquina guardiao.home, uma terceira que cria a cadeia chamada SSH para direcionarmos todas as conexões SSH e por fim a própria regra que irá direcionar as conexões SSH para a cadeia recém criada.

# iptables -A INPUT -i lo -j ACCEPT
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -N SSH
# iptables -A INPUT -p tcp --dport 22 -j SSH
# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source        destination        
ACCEPT     all  --  0.0.0.0/0     0.0.0.0/0          
ACCEPT     all  --  0.0.0.0/0     0.0.0.0/0      state RELATED,ESTABLISHED
SSH         tcp  --  0.0.0.0/0    0.0.0.0/0      tcp dpt:22
Chain FORWARD (policy ACCEPT)
target     prot opt source        destination         
Chain OUTPUT (policy ACCEPT)
target     prot opt source        destination        
Chain SSH (1 references)
target     prot opt source        destination        

Com o setup inicial do firewall pronto, podemos agora chamar o módulo recent para tornar nossas regras dinâmicas. Para facilitar o entendimento das próximas regras que iremos trabalhar, vejamos algumas opções do recent:
  • --name: seta o nome da lista que iremos trabalhar. Obs.: quando não informado, é utilizado DEFAULT;
  • --set: irá adicionar o endereço de origem do pacote na lista. Se o endereço já estiver na lista, então irá atualizar o registro;
  • --rcheck: verifica se o endereço de origem do pacote está atualmente na lista;
  • --update: verifica e atualiza o timestamp do campo "last seen" se o endereço de origem do pacote já estiver na lista;
  • --seconds: especifica se a regra terá validade somente se o endereço de origem do pacote estiver dentro do valor especificado;
  • --hitcount: verifica se o endereço de origem do pacote esta na lista e se o número de pacotes recebido desse endereço é igual ou maior do valor estipulado.

Com essas opções explicadas (para maiores informações man 8 iptables), podemos criar nossa primeira regra para cadastrar todas as tentativas de conexões via SSH para uma tabela que será criada pelo recent chamada de conexoes_ssh.

# iptables -A SSH -m recent --set --name conexoes_ssh
# iptables -L SSH -n

Chain SSH (1 references)
target     prot opt source        destination
           all  --  0.0.0.0/0     0.0.0.0/0      recent: SET name: conexoes_ssh side: source

Com a regra "iptables -A SSH -m recent --set --name conexoes_ssh" criamos a tabela conexoes_ssh que será alimentada com todas as conexões direcionadas para a cadeia SSH. O que precisamos fazer agora é permitir apenas 1 conexão no intervalo de 2 minutos por vez em nosso servidor. Para isso iremos usar os parâmetros --seconds 120 e --hitcount 2, pois queremos determinar 120 segundos e quando o contador for maior ou igual a 2.

# iptables -A SSH -m recent --name conexoes_ssh --update --seconds 120 --hitcount 2 -j REJECT
# iptables -vnL SSH
Chain SSH (1 references)
pkts bytes target     prot opt in     out     source               destination
    0     0            all  --  *      *       0.0.0.0/0            0.0.0.0/0           recent: SET name: conexoes_ssh side: source
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           recent: UPDATE seconds: 120 hit_count: 2 name: conexoes_ssh side: source reject-with icmp-port-unreachable

Após a execução da regra, nosso firewall já esta monitorando tentativas de conexão via SSH e irá permitir a primeira tentativa de cada IP de origem. Vejamos:

Máquina externa - primeira conexão:

date ; ssh root@guardiao
Wed Dec 9 01:34:11 BRST 2009
root@guardiao's password:
Last login: Wed Dec 9 01:30:24 2009 from 192.168.122.1

# iptables -nvL SSH
Chain SSH (1 references)
pkts bytes target     prot opt in     out     source               destination
    1    60            all  --  *      *       0.0.0.0/0            0.0.0.0/0           recent: SET name: conexoes_ssh side: source
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           recent: UPDATE seconds: 120 hit_count: 2 name: conexoes_ssh side: source reject-with icmp-port-unreachable
# cat /proc/net/xt_recent/conexoes_ssh
src=192.168.122.1 ttl: 64 last_seen: 6084651 oldest_pkt: 1 6084651

Máquina externa - segunda conexão:

date ; ssh root@guardiao
Wed Dec 9 01:34:45 BRST 2009
ssh: connect to host guardiao port 22: Connection refused

# iptables -nvL SSH
Chain SSH (1 references)
pkts bytes target     prot opt in     out     source               destination
    2   120            all  --  *      *       0.0.0.0/0            0.0.0.0/0           recent: SET name: conexoes_ssh side: source
    1    60 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           recent: UPDATE seconds: 120 hit_count: 2 name: conexoes_ssh side: source reject-with icmp-port-unreachable
# cat /proc/net/xt_recent/conexoes_ssh

src=192.168.122.1 ttl: 64 last_seen: 6119177 oldest_pkt: 3 6084651, 6119177, 6119177

Máquina externa - terceira conexão (depois de 3 minutos):

date ; ssh root@guardiao
Wed Dec 9 01:37:19 BRST 2009
root@guardiao's password:
Last login: Wed Dec 9 01:34:11 2009 from 192.168.122.1

Como podem perceber, o recent cria um arquivo dentro do diretório /proc/net/xt_recent chamado conexoes_ssh (que é o nome de nossa tabela) para controle das conexões. Se tivéssemos criado outras tabelas, também seriam criados outros arquivos respectivos. O interessante é que podemos manipular esses arquivos e consequentemente manipular as tabelas. Perceba também que a cada conexão que fizemos, o campo last seen foi modificado, informando para a regra que houve uma nova tentativa. Para manipularmos as tabelas podemos:
  • echo +192.168.122.15 > /proc/net/xt_recent/conexoes_ssh - para adicionarmos um endereço na tabela
  • echo -192.168.122.1 > /proc/net/xt_recent/conexoes_ssh - para removermos um endereço da tabela
  • echo / > /proc/net/xt_recent/conexoes_ssh - para limparmos a tabela

# cat /proc/net/xt_recent/conexoes_ssh
src=192.168.122.1 ttl: 64 last_seen: 6273353 oldest_pkt: 4 6084651, 6119177, 6119177, 6273353
# echo +192.168.122.15 > /proc/net/xt_recent/conexoes_ssh
# cat /proc/net/xt_recent/conexoes_ssh

src=192.168.122.1 ttl: 64 last_seen: 6273353 oldest_pkt: 4 6084651, 6119177, 6119177, 6273353
src=192.168.122.15 ttl: 0 last_seen: 6847221 oldest_pkt: 1 6847221
# echo -192.168.122.1 > /proc/net/xt_recent/conexoes_ssh
# cat /proc/net/xt_recent/conexoes_ssh

src=192.168.122.15 ttl: 0 last_seen: 6847221 oldest_pkt: 1 6847221
# echo /> /proc/net/xt_recent/conexoes_ssh
# cat /proc/net/xt_recent/conexoes_ssh


E finalizando, um ponto importante que precisa ser colocado é que se você for trabalhar com um firewall com grande número de conexões, por padrão o recent irá armazenar apenas 100 endereços nas tabelas criadas. Para alterar esse valor por exemplo para 1024, precisamos passar para o módulo xt_recent algumas flags:

# modinfo xt_recent
filename:       /lib/modules/2.6.29.4-167.fc11.i686.PAE/kernel/net/netfilter/xt_recent.ko
alias:          ip6t_recent
alias:          ipt_recent
license:        GPL
description:    Xtables: "recently-seen" host matching for IPv4
author:         Jan Engelhardt
author:         Patrick McHardy
srcversion:     0CA8710587603DFF5C5923B
depends:       
vermagic:       2.6.29.4-167.fc11.i686.PAE SMP mod_unload 686
parm:           ip_list_tot:number of IPs to remember per list (uint)
parm:           ip_pkt_list_tot:number of packets per IP to remember (max. 255) (uint)
parm:           ip_list_hash_size:size of hash table used to look up IPs (uint)
parm:           ip_list_perms:permissions on /proc/net/xt_recent/* files (uint)
parm:           ip_list_uid:owner of /proc/net/xt_recent/* files (uint)
parm:           ip_list_gid:owning group of /proc/net/xt_recent/* files (uint)

# echo "options xt_recent ip_list_tot=1024" ; /etc/modprobe.d/xt_recent.conf

Obs.: Não esqueça de descarregar o módulo e recarregá-lo para honrar as configurações.

Ah! Para finalizar não esqueça de salvar suas regras e ativar o serviço de firewall persistente ao reboot.

# service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables: [ OK ]

# chkconfig iptables on

Pretendo em outro post demonstrar como podemos criar algumas regras para que o iptables trabalhe com port knocking, assim permitindo que o serviço somente seja liberado se a sequência de portas estiver correta.

E agora vivente, prepara o teu chimarrão e a tua mateira e se arranca índio véio configurar o teu firewall tchê! :)

   

Páginas do artigo
   1. Introdução
Outros artigos deste autor

Instalação automatizada de servidores com Kickstart (parte 2)

Transportando dados com segurança - encripte seu pendrive em 5 passos

Instalação automatizada de servidores com kickstart

Leitura recomendada

Um pouco sobre IPtables

L7-filter (funcionando) no Slackware 10.2

Squid + iptables (método ninja)

Usando o PF - Packet Filter

Iptables 1.3.4 com Layer 7 e Kernel 2.6.14 no Debian 3.1

  
Comentários
[1] Comentário enviado por Win7User em 19/12/2009 - 14:36h

Bello topico Chello!
bem interessante este recurso do iptables ,no caso tem como limitar o tamanho "log" do historico ou nao?
abraços

[2] Comentário enviado por magnolinux em 19/12/2009 - 21:16h

Boa chello..

utilizo o modulo recent para fazer port knocking...

funciona muito bem...

Continue contribuindo com otimos artigos..

abraço...

[3] Comentário enviado por d3lf0 em 21/12/2009 - 10:07h

Grato pela contribuição, otimo artigo.
bem interessante mesmo.

[4] Comentário enviado por fmpfmp em 21/12/2009 - 10:45h

Na minha opinião a medida mais simples e eficiente que existe contra ataques de força bruta é a mudança de porta padrão. Ao invés de 22 dp ssh coloque outra alta, como 34834. Dificilmente alguém ou algum bot vai encontrá-la.

[5] Comentário enviado por elgio em 21/12/2009 - 11:01h

Muito bom artigo. Parabéns. Além de explicar o modulo Recent ainda entrou, de tabelinha, na parte de criação de chains.

Só tenho uma critica a fazer...

Aqui mesmo no VOL, muitos outros autores escreveram sobre Iptables. Um deles inclusive sobre Recent (http://www.vivaolinux.com.br/artigo/Iptables-+-modulo-recent/)

Eu entendo ser muito interessante (e podem discordar de mim) quando se escreve um assunto procurar no VOL quem já escreveu sobre ele antes e referenciar, citar estes outros artigos. Valoriza o trabalho dos outros colaboradores do Viva o Linux.

Mas claro, isto é uma opinião minha, uma dica.

No mais, gostei muito mesmo do artigo. Entrou para meus (poucos) favoritos.

[]'s

[6] Comentário enviado por fernandoborges em 22/12/2009 - 17:43h

Muito bom o artigo. Parabéns.

[7] Comentário enviado por marcrock em 25/12/2009 - 13:37h

Realmente é um ótimo artigo. Parabéns!!!

[8] Comentário enviado por claudiotecnico em 27/12/2009 - 00:03h

Parabéns ao autor pelo artigo.

Acho que deveria ter sido explicado:

- Qual distro e versão do Linux está sendo usada?
- Qual o procedimento básico para instalação do módulo recent (ele foi instalado pelo gerenciador de pacotes da distro ou foi preciso baixar e compilar)?
- Onde baixar?
- Em quais locais posso obter mais informações e documentação sobre o módulo em questão?

No mais o artigo está perfeito.

Abraços,

Claudio

[9] Comentário enviado por tchello.mello em 27/12/2009 - 08:43h

Olá Claudio,

Obrigado pela comentário e respondendo suas perguntas:

- Qual distro e versão do Linux está sendo usada?
Fedora 12
- Qual o procedimento básico para instalação do módulo recent (ele foi instalado pelo gerenciador de pacotes da distro ou foi preciso baixar e compilar)?
Foi instalado diretamento com yum. O próprio iptables já estava com o suporte.

- Onde baixar?
http://netfilter.org/projects/iptables/downloads.html">http://netfilter.org/projects/iptables/downloads.html

- Em quais locais posso obter mais informações e documentação sobre o módulo em questão?
http://netfilter.org/projects/iptables

Grande abraço.


[10] Comentário enviado por danielrsj em 29/12/2009 - 11:37h

dá pra bloquear o ultrasurf (porta 443) com esse módulo?
Alguém já tentou?

[11] Comentário enviado por marcusburghardt em 06/01/2010 - 10:57h

Bom dia!

Legal seu artigo. Dei uma palestra sobre essa e mais algumas técnicas de Segurança em Firewalls no FISL 10.
Era um assunto bem interessante e pouco explorado no iptables.

Abraço!

[12] Comentário enviado por removido em 17/03/2010 - 14:00h

Show em Marcelo!

[]'s

[13] Comentário enviado por capitainkurn em 01/04/2010 - 17:02h

Ótimo artigo! Já está nos favoritos.

[14] Comentário enviado por removido em 03/11/2010 - 13:26h

Marcelão, muito bom o artigo!
Agora que tu tá com mais tempo, continue contribuindo... heheheh

Poderia ainda melhorar a segurança do Forewall utilizando outras técnicas e ferramentas, por exemplo o fail2ban.

Abração

Bruno Lima®
Brasília-DF-Brasil

[15] Comentário enviado por removido em 04/01/2011 - 10:52h

Otimo artigo, muito interessante esse modulo externo do netfilter,
meus parabens.

[16] Comentário enviado por rrossilva em 21/03/2011 - 10:42h

Otimo artigo!!! Funciona que é uma beleza.
Já implementei uma jaula com varias portas monitoradas, ficou show de bola.

[17] Comentário enviado por gilmar_gnu/slack em 01/06/2011 - 11:32h

Tem um tempo que não vejo nada novo de configuração de firewall.
Pois é necessário.
To ferrado em linux estes dias.
Virei um fanfarrão.
só não pedi para sair porquê tenho materiais.
Sinto falta do meu Slackware de Sempre.
hahahaha ^^
òtimo artigo man.

[18] Comentário enviado por felipetsi em 31/05/2012 - 14:20h

tchello.mello, excelente artigo. Eu não conhecia esse módulo do iptables.

Meus parabéns pelo artigo.

[19] Comentário enviado por hackerdubuntu em 27/07/2012 - 09:23h

ola amigo achei interesante esse artigo sera se teria problem em eu publicar para outros???

[20] Comentário enviado por pharaohgt em 03/10/2012 - 17:31h

Boa , obrigado pela contribuiçao!!!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts