Criando firewalls dinâmicos com Iptables Recent

Autor: Marcelo Moreira de Mello <tchello.mello at gmail.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ê!🙂


http://www.vivaolinux.com.br/artigo/Criando-firewalls-dinamicos-com-Iptables-Recent

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s