Continuando a prática.....
Que tal bloquear o SSH ou outro serviço e só liberar para IPs de origem que estejam na tabela criada, usando o Módulo Recent, mas o IP de origem só
estará na tabela depois que for enviado um pacote para uma porta especifica.
Bom, é isso que irá ser feito no próximo exemplo, para mostrar como se pode trabalhar com o Módulo Recent.
Para colocar em prática, primeiro será criado 3 regras no Host 192.168.20.10 que roda o SSH.
Na primeira, adiciono uma regra a Chain INPUT que trata todos os pacotes TCP destinados a porta 63000, criando com o Módulo Recent, uma tabela
chamada de OpenSSH, e adicionando o endereço de origem de quem está enviando o pacote, e quando estes pacotes forem tratados pelo IPtables,
serão bloqueados.
Na segunda regra, aceito todos os pacotes destinados à porta 22 do SSH, que sejam do protocolo TCP e que o endereço de origem esteja na tabela (--
name) OpenSSH, pois o mesmo será verificado (--update) pelo Recent e caso esteja realmente na tabela, será aceito.
Na terceira regra, bloqueio todas as conexões via SSH destinadas à porta 22.
# iptables -A INPUT -p tcp --dport 63000 -m recent --set --name openssh -j REJECT
# iptables -A INPUT -p tcp --dport 22 -m recent --update --name openssh -j ACCEPT
# iptables -A INPUT -p tcp --dport 22 -j REJECT
- Testando:
* Primeiro, tento me conectar ao Host rodando o SSH, e onde estão as regras sem enviar nenhum pacote para a porta 63000:
# date;ssh -p 22 edson@192.168.20.10
Qua Fev 22 13:42:37 BRT 2012
ssh: connect to host 192.168.20.10 port 22: Connection refused
[ Não se conectou... ]
* Veja após a tentativa de conexão, a saída do comando "iptables -nvL", e observe que tem um pacote dropado.
# iptables -nvL
Chain INPUT (policy ACCEPT 1298 packets, 213K bytes)
pkts bytes target prot opt in out source destination
0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:63000 recent: SET name: openssh side: source
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 recent: UPDATE name: openssh side: source
1 60 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 reject-with icmp-port-unreachable
* Agora, o envio do pacote para a porta 63000, usando o Telnet do Host 192.168.20.20, e o pacote será bloqueado, porém, o endereço de origem será
adicionado à tabela.
# date;telnet 192.168.20.10 63000
Qua Fev 22 14:12:08 BRT 2012
Trying 192.168.20.10...
telnet: Unable to connect to remote host: Connection refused
* Saída dos comandos abaixo, na máquina com o servidor SSH, veja que o pacote foi bloqueado e na mesma o endereço foi adicionado à tabela:
# iptables -nvL
Chain INPUT (policy ACCEPT 89 packets, 11250 bytes)
pkts bytes target prot opt in out source destination
1 60 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:63000 recent: SET name: openssh side: source reject-with icmp-port-unreachable
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 recent: UPDATE name: openssh side: source
1 60 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 reject-with icmp-port-unreachable
# cat /proc/net/xt_recent/openssh
src=192.168.20.20 ttl: 64 last_seen: 1051576 oldest_pkt: 1 1051576
* Após o envio do pacote, a tentativa de conexão via SSH:
# date;ssh -p 22 edson@192.168.20.10
Qua Fev 22 14:15:39 BRT 2012
edson@192.168.20.10's password:
Last login: Tue Feb 21 23:50:31 2012 from abrtop.local
[ Conexão realizada com sucesso....]
* Tentativa de conexão de Host que não tem o endereço de origem na tabela:
# date;ssh -p 22 edson@192.168.20.10
Qua Fev 22 14:16:10 BRT 2012
ssh: connect to host 192.168.20.10 port 22: Connection refused
[ Não se conectou.... ]
* Após a conexão via SSH, veja a saída do comando "iptables -nvL" e "cat /proc/net/xt_recent/openssh", e veja
também que foi recusada mais uma conexão que é justamente do IP que não está na tabela.
# iptables -nvL
Chain INPUT (policy ACCEPT 422 packets, 52871 bytes)
pkts bytes target prot opt in out source destination
1 60 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:63000 recent: SET name: openssh side: source reject-with icmp-port-unreachable
18 2797 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 recent: UPDATE name: openssh side: source
2 180 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 reject-with icmp-port-unreachable
# cat /proc/net/xt_recent/openssh
src=192.168.20.20 ttl: 64 last_seen: 1117918 oldest_pkt: 18 1051576, 1117174, 1117174, 1117178, 1117178, 1117178, 1117178, 1117182,
1117189, 1117199, 1117199, 1117291, 1117790,
1117801, 1117801,
1117804, 1117808, 1117918
Após testar, veja que após aplicar as regras, tentei acessar via SSH e foi bloqueada a conexão, pois o endereço de origem não estava na tabela.
Depois disso, enviei um pacote para a porta 63000, para adicionar o endereço de origem na tabela OpenSSH, aí em seguida, tentei outra vez a
conexão e foi realizada com sucesso. Depois tentei com outra máquina conectar-me, mas aí foi bloqueada a conexão, pois o endereço da máquina de
origem não estava na tabela.
Para remover o endereço de origem da tabela, crie a regra abaixo, na máquina com o SSH e depois envie o um pacote via Telnet.
# iptables -A INPUT -p tcp --dport 23000 -m recent --name openssh --remove -j REJECT
# telnet 192.168.20.10 23000
Para o último exemplo, será feito praticamente a mesma coisa do exemplo anterior, porém, irei controlar a conexão no servidor SSH operando na porta
22 com base em tempo e quantidade.
Aplicação de regras e explicação das mesmas:
# iptables -A INPUT -p tcp --dport 22 -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A INPUT -p tcp --dport 558 -m recent --name timessh --set -j REJECT
# iptables -A INPUT -p tcp --syn --dport 22 -m recent --name timessh --update --seconds 30 --hitcount 2 -j ACCEPT
# iptables -A INPUT -p tcp --dport 22 -j REJECT
- Na primeira regra, serão aceitos pacotes de conexões já estabelecidas na porta 22.
- Na segunda regra, bloqueio conexões na porta 558. Esta porta será usada para incluir endereços de pacotes de origem na tabela TimeSSH usando o
Módulo Recent, para que a próxima regra aceite pacotes de endereços de origem que estão nesta tabela.
- Na terceira regra, aceito tentativas de novas conexões somente de pacotes de endereços de origem, que estejam na tabela TimeSSH e que tenham 2
ou mais pacotes registrados na tabela no intervalo de 30 segundos. Caso não tenha dois ou mais pacotes no intervalo de 30 segundos na tabela, então
será executado a próxima regra.
- Na última regra, bloqueio todas conexões nesta porta 22.
- Testando:
* Tentativa de conexão via SSH na porta 22:
date;ssh -p 22 edson@192.168.20.10
Qua Fev 22 19:29:17 BRT 2012
ssh: connect to host 192.168.20.10 port 22: Connection refused
[ Não se conectou... ]
* Veja a saída do comando abaixo, após a primeira tentativa de conexão sem entradas na tabela TimeSSH:
# iptables -nvL
Chain INPUT (policy ACCEPT 34 packets, 4200 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state RELATED,ESTABLISHED
0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:558 recent: SET name: timessh side: source reject-with icmp-port-unreachable
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 flags:0x17/0x02 recent: UPDATE seconds: 30 hit_count: 2 name: timessh side: source
1 60 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 reject-with icmp-port-unreachable
* Envio do pacote via Telnet para liberar o SSH na porta 22, e nova tentativa de conexão via SSH, a conexão foi bloqueada, pois é a mesma.
date;telnet 192.168.20.10 558
Qua Fev 22 19:30:18 BRT 2012
Trying 192.168.20.10...
telnet: Unable to connect to remote host: Connection refused
# date;ssh -p 22 edson@192.168.20.10
Qua Fev 22 19:30:30 BRT 2012
ssh: connect to host 192.168.20.10 port 22: Connection refused
[ Não se conectou.... ]
* Após segunda tentativa de conexão via SSH, sem sucesso:
# iptables -nvL
Chain INPUT (policy ACCEPT 90 packets, 11028 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state RELATED,ESTABLISHED
1 60 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:558 recent: SET name: timessh side: source reject-with icmp-port-unreachable
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 flags:0x17/0x02 recent: UPDATE seconds: 30 hit_count: 2 name: timessh side: source
2 120 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 reject-with icmp-port-unreachable
* Envio de outro pacote Telnet e nova tentativa de conexão via SSH, com sucesso desta vez, pois a mesma aconteceu após ser enviados dois pacotes
para porta 558, no intervalo de 30 segundos
# date;telnet 192.168.20.10 558
Qua Fev 22 19:30:36 BRT 2012
Trying 192.168.20.10...
telnet: Unable to connect to remote host: Connection refused
# date;ssh -p 22 edson@192.168.20.10
Qua Fev 22 19:30:38 BRT 2012
edson@192.168.20.10's password:
Last login: Wed Feb 22 19:18:27 2012 from abrtop.local
* Após envio do segundo pacote Telnet e tentativa de conexão via SSH com sucesso:
# iptables -nvL
Chain INPUT (policy ACCEPT 104 packets, 12463 bytes)
pkts bytes target prot opt in out source destination
16 2737 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state RELATED,ESTABLISHED
2 120 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:558 recent: SET name: timessh side: source reject-with icmp-port-unreachable
1 60 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 flags:0x17/0x02 recent: UPDATE seconds: 30 hit_count: 2 name: timessh side: source
2 120 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 reject-with icmp-port-unreachable
# cat cat /proc/net/xt_recent/timessh
src=192.168.20.20 ttl: 64 last_seen: 5841279 oldest_pkt: 2 5836616, 5841279
Veja no decorrer dos Posts, que foram bloqueadas duas tentativas de acesso via SSH por que o endereço de origem não tinha duas ou mais entradas
no intervalo de 30 segundos na tabela TimeSSH. Repito a dizer que isto foi feito com o SSH, mas poderia ser feito com outro serviço ou de acordo com
a necessidade de cada um.
Finalizando
Como podem perceber, o Módulo 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 estes arquivos e consequentemente, manipular as tabelas:
# echo +192.168.20.15 > /proc/net/xt_recent/timessh - para adicionarmos um endereço na tabela
# echo -192.168.20.10 > /proc/net/xt_recent/timessh - para removermos um endereço da tabela
# echo / > /proc/net/xt_recent/timessh - para limparmos a tabela
Algo importante que precisa ser colocado, é que se você for trabalhar com um grande número de conexões no seu Firewall, por padrão, o Módulo
Recent irá armazenar apenas 100 endereços nas tabelas criadas.
Para alterar este 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
Não esqueça de descarregar o módulo e recarregá-lo.
Referências