Port Knocking (Knockd) no OpenWRT: Problemas com a Configuração do Firewall

1. Port Knocking (Knockd) no OpenWRT: Problemas com a Configuração do Firewall


0x3e8volts

(usa Outra)

Enviado em 23/07/2015 - 22:59h

PREFÁCIO:

Estou tendo alguns problemas relacionados ao Firewall e a configuração do Port Knocking no sistema OpenWRT (BarrierBreaker 14.07). Estou precisando de ajuda para conseguir entender as configurações feitas no Firewall, para que o Port Knocking funcione sem nenhum problema.

INTRODUÇÃO:

Na Wiki do OpenWRT, há o artigo Secure your router's access:

http://wiki.openwrt.org/doc/howto/secure.access

Nele, há diversas dicas para tornar o acesso ao sistema mais seguro. Uma delas, descrita no tópico Network hardening, é a utilização do recurso port knocking, através do daemon Knockd, para, por exemplo, tornar mais seguro o acesso via SSH.

Também, é possível encontrar na Wiki o tutorial knockd server, explicando sobre a instalação e configuração do daemon:

http://wiki.openwrt.org/doc/howto/portknock.server

OBJETIVO:

É possível utilizar o Knockd para desbloquear/ bloquear qualquer porta UDP e/ou TCP, mas o meu objetivo é apenas desbloquear e, após a utilização, voltar bloquear o acesso a porta SSH do roteador.

OS PROBLEMAS:

Tentei seguir o tutorial knockd server, mas estou tendo os seguintes problemas:

1. Utilizando a função open_port, do script uciknockd.sh, eu consigo liberar o acesso à porta SSH, mas, ao utilizar a função close_port, a conexão com a Internet para de funcionar e eu não consigo mais acessar o roteador de nenhuma forma, nem após a reinicialização do mesmo. Sou obrigado a resetá-lo.

2. A função open_port, teoricamente, cria uma nova regra no Firewall chamada KnockdSSH, na cadeia INPUT, mas eu não consigo localizá-la após utilizar o comando:

user@OpenWRT:~$ sudo iptables -L -t raw --line-numbers 

O mesmo é informado na Wiki, no artigo sobre o Firewall, no tópico How to delete a rule:

http://wiki.openwrt.org/doc/uci/firewall#how_to_delete_a_rule

Atualmente, eu estou abrindo a porta SSH com o Knockd, mas tendo que reinicializar o roteador (user@OpenWRT:~$ sudo reboot) para que a porta seja fechada novamente.

EXPLICAÇÃO UM POUCO MAIS DETALHADA:

Seguindo o tutorial knockd server, após instalar o Knockd através do comando:

opkg install knockd 

criei 3 arquivos:

1. /etc/uciknockd.sh;
2. /etc/forward.sh (opcional, não foi utilizado nos testes);
3. /etc/init.d/knockd.

E os tornei executáveis, através do comando:

user@OpenWRT:~$ sudo chmod 755 /etc/uciknockd.sh /etc/forward.sh /etc/init.d/knockd 

Eu deixei os conteúdos destes 3 arquivos exatamente iguais aos informados no tutorial da Wiki. A únicas alterações que eu fiz foram no arquivo /etc/knockd.conf, que é onde o Knockd é configurado. E efetuei as seguintes alterações no exemplo que consta no tutorial -- relacionado ao uso do knockd.conf em conjunto com o script uciknockd.sh:

1. Na seção [options], alterei a interface para br-lan, pois, caso contrário, no meu caso, o Knockd não é inicializado;
2. Alterei as sequências de portas que serão utilizadas para ativar o Knockd;
3. Alterei a porta 22 para a porta que eu utilizo para acesso SSH;
4. Apaguei as seções [openFORWARD] e [closeFORWARD], pois não serão utilizadas.

O conteúdo final ficou da seguinte forma:

[options]
logfile = /var/log/knockd.log
interface = br-lan

[openSSH]
sequence = <porta 1>,<porta 2>,<porta 3>
seq_timeout = 5
command = /etc/uciknockd.sh open-port KnockdSSH %IP% <porta SSH>
tcpflags = syn

[closeSSH]
sequence = <porta 3>,<porta 2>,<porta 1>
seq_timeout = 5
command = /etc/uciknockd.sh close-port KnockdSSH %IP% <porta SSH>
tcpflags = syn


Em /etc/firewall.user, incluí a seguinte regra:

iptables -A INPUT -p tcp --dport <porta SSH> -j DROP 

Observação: a regra acima só entrou em vigor após a reinicialização do roteador, não adiantou reinicializar apenas do Firewall através do comando /etc/init.d/firewall restart.

Após isso, ativei o Knockd através dos comandos:

user@OpenWRT:~$ sudo /etc/init.d/knockd enable && sudo /etc/init.d/knockd start 

e, através do log /var/log/knockd.log, pude confirmar que o Knockd foi inicializado com sucesso:

[yyyy-mm-dd hh:mm] starting up, listening on br-lan
[yyyy-mm-dd hh:mm] starting up, listening on br-lan
[yyyy-mm-dd hh:mm] starting up, listening on br-lan
[yyyy-mm-dd hh:mm] starting up, listening on br-lan
[yyyy-mm-dd hh:mm] starting up, listening on br-lan
[yyyy-mm-dd hh:mm] starting up, listening on br-lan


Enviando o comando de ativação para o Knockd, através do computador cliente, usando o comando:

cliente@GNULinux:~$ knock 192.168.1.1 <porta 1> <porta 2> <porta 3> 

Também foi possível verificar no roteador, através do log knockd.log, que o Knockd recebeu o comando com sucesso e, na sequência, executou os comandos configurados no arquivo /etc/knockd.conf.

Ou seja, o problema está apenas na execução dos comandos definidos no script /etc/uciknockd.sh. E, como eu havia dito, somente quando eu utilizo o comando para fechar a porta SSH, através da função close-port:

[...]
command = /etc/uciknockd.sh close-port KnockdSSH %IP% <porta SSH>
[...]


AS DÚVIDAS:

1. Quais alterações fazer no script uciknockd.sh?

2. Mesmo eu conseguindo acessar o roteador após fazer o Knockd liberar o acesso à porta SSH, se eu uso o comando iptables -L e verifico todas as regras, não encontro nenhuma regra com o nome KnockdSSH, que, teoricamente, está sendo criada com o auxílio do script uciknockd.sh.

Na cadeia INPUT, há apenas a regra:

DROP       tcp  --  anywhere             anywhere             tcp dpt:<porta SSH> 

criada no arquivo /etc/firewall.user.

Seria uma alternativa usar o Knockd para abrir a porta SSH, mas, antes de encerrar o meu acesso, fecharia o acesso a porta manualmente. Pelo que eu entendi, se eu quiser excluir uma regra manualmente, eu teria que saber o ID da mesma, como explicado em:

http://wiki.openwrt.org/doc/uci/firewall#how_to_delete_a_rule

Mas como eu faço isso se eu não consigo localizar a regra KnockdSSH?

3. É possível configurar os comandos no arquivo knockd.conf, sem o uso de scripts. Por exemplo, se eu quiser abrir a porta SSH sem scripts, a seção [OpenPort] ficaria da seguinte forma:

[...]
[OpenPort]
sequence = <porta 1>,<porta 2>,<porta 3>
seq_timeout = 5
command = /sbin/uci add firewall rule
command = /sbin/uci set firewall.@rule[-1].name=KnockdSSH
command = /sbin/uci set firewall.@rule[-1].src=wan
command = /sbin/uci set firewall.@rule[-1].src_ip=%IP%
command = /sbin/uci set firewall.@rule[-1].dest_port=<porta SSH>
command = /sbin/uci set firewall.@rule[-1].target=ACCEPT
command = /sbin/uci set firewall.@rule[-1].proto=tcp
command = /sbin/uci commit firewall
command = /etc/init.d/firewall restart
tcpflags = syn
[...]


(Mas da mesma forma que com o uso do script, eu não consigo localizar a regra KnockdSSH usando iptables -L.)

Também seria possível utilizar comandos para fechar a porta, sem o uso de um script?

4. Por que, ao usar o comando iptables (/usr/sbin/iptables) ao invés do uci:

[...]
command = /usr/sbin/iptables -A INPUT -s %IP% -p tcp --dport <porta SSH> -j ACCEPT
[...]
command = /usr/sbin/iptables -D INPUT -s %IP% -p tcp --dport <porta SSH> -j ACCEPT
[...]

as regras não entram em vigência logo após a reinicialização do firewall (/etc/init.d/firewall restart)?

APÊNDICE:

O script /etc/uciknockd.sh:

#!/bin/sh 
# This is uciknockd.sh script, place it in /etc directory

. /lib/functions.sh

# callback for config_foreach
handle_delete()
{
local config="$1"
local option="$2"
local value="$3"
local optionVal=""
config_get optionVal "$config" "$option"
if [ "$optionVal" == "$value" ]; then
uci delete firewall.$config
return 1
fi
}

# to delete firewall.@rule[x].name="test"
# delete_rule firewall rule name test
#
delete_rule()
{
local config="$1"
local section="$2"
local name="$3"
local value="$4"
config_load $config
config_foreach handle_delete $section $name $value
}

# Opening ports
# This example enables machines on the internet to use SSH to access your router.
#
#config rule
# option src wan
# option dest_port 22
# option target ACCEPT
# option proto tcp

open_port()
{
local name=$1
local src_ip=$2
local dest_port=$3

uci batch <<EOF
add firewall rule
set firewall.@rule[-1].name=$name
set firewall.@rule[-1].src='wan'
set firewall.@rule[-1].src_ip=$src_ip
set firewall.@rule[-1].dest_port=$dest_port
set firewall.@rule[-1].target='ACCEPT'
set firewall.@rule[-1].proto='tcp'
EOF

uci commit firewall
/etc/init.d/firewall restart
}

close_port()
{
local name=$1
delete_rule firewall rule name $name

uci commit firewall
/etc/init.d/firewall restart
}

# Forwarding ports (Destination NAT/DNAT)
# This example forwards one arbitrary port that you define to a box running ssh.
#
#config 'redirect'
# option 'name' 'ssh'
# option 'src' 'wan'
# option 'proto' 'tcpudp'
# option 'src_dport' '5555'
# option 'dest_ip' '192.168.1.100'
# option 'dest_port' '22'
# option 'target' 'DNAT'
# option 'dest' 'lan'

forward_port()
{
local name=$1
local src_ip=$2
local src_dport=$3
local dest_ip=$4
local dest_port=$5

uci batch <<EOF
add firewall redirect
set firewall.@redirect[-1].name=$name
set firewall.@redirect[-1].src='wan'
set firewall.@redirect[-1].src_ip=$src_ip
set firewall.@redirect[-1].proto='tcp'
set firewall.@redirect[-1].src_dport=$src_dport
set firewall.@redirect[-1].dest_ip=$dest_ip
set firewall.@redirect[-1].dest_port=$dest_port
set firewall.@redirect[-1].target='DNAT'
set firewall.@redirect[-1].dest='lan'
EOF

uci commit firewall
/etc/init.d/firewall restart
}

remove_forward_port()
{
local name=$1
delete_rule firewall redirect name $name
uci commit firewall
/etc/init.d/firewall restart
}

case "$1" in
open-port)
#name=$1
#src_ip=$2
#dest_port=$3
name="$2_$3_$4"
open_port $name $3 $4
;;
close-port)
name="$2_$3_$4"
close_port $name $3 $4
;;
forward-port)
#name=$1
#src_ip=$2
#src_dport=$3
#dest_ip=$4
#dest_port=$5
name="$2_$3_$4"
forward_port $name $3 $4 $5 $6
;;
remove-forward-port)
name="$2_$3_$4"
remove_forward_port $name $3 $4
stop
;;
*)
echo "Usage:"
echo " $0 open-port namePrefix src_ip dest_port"
echo " $0 close-port namePrefix src_ip dest_port"
echo " $0 forward-port namePrefix src_ip src_dport dest_ip dest_port"
echo " $0 remove-forward-port namePrefix src_ip src_dport"
exit 1
esac

exit 0



  






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts