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:
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:
É 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:
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.
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.
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.
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:
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:
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:
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
# 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