Usar o Knocking, para esconder o SSH de ataques
Os servidores, são implementados, com a ideia de servir algum tipo de conteúdo. Esse é realmente o seu principal trabalho. Se implementarmos um servidor web, queremos com certeza, que sirva conteúdo, sem parar e que esteja sempre disponível, para que o mundo tenha acesso, ao conteúdo que oferecemos ou vendemos. Quando implementamos um serviço de email, também queremos com certeza, que o servidor esteja sempre disponível, para receber as nossas mensagens, bem como enviá-las. De qualquer maneira, nenhum computador é 100% seguro. Qualquer computador, que esteja a disponibilizar conteúdos para a web, é alvo de ataques. Por esta razão, devemos apenas deixar os serviços, que realmente são necessários, abertos ao mundo. Então e como é que eu administro, o meu computador, remotamente via SSH? Tenho que deixar o porto deste serviço aberto!
Neste artigo, vou mostrar, como podemos evitar muitos problemas, de ataques aos serviços, que só usamos de vez em quando, para tarefas administrativas. Vou mostrar, passo a passo, como configuramos o nosso servidor, para abrir os portos que usamos para tarefas administrativas, apenas, quando realmente vamos usa-los.
O Port knocking, é uma técnica, de manter os serviços que usamos para administração, aqueles que não queremos disponibilizar publicamente, desligados, até serem realmente necessários. Esta técnica, consiste em enviar uma sequência de pacotes, a uns determinados portos, escolhidos por nós. Ao ser reconhecida a sequência, abre-se um determinado porto, para que possamos ligar-nos ao serviço desejado. Esta lógica é importante, para que os atacantes, que normalmente fazem scan por portos abertos, não verem, que estamos a usar determinados portos, como o SSH por exemplo.
Apesar de poder ser bastante segura esta técnica, visto que temos 65535 portos no sistema e a sequência, pode ser grande, o que nos permite alguma segurança. Não é de todo, impossível, descobrir esta sequência. Portanto, não podemos ver este tipo de técnica, como uma substituição, de uma boa palavra passe, mas sim, como mais uma camada de segurança.
Apesar de existir, vários softwares, que executam este tipo de técnica, vou usar neste artigo, o knockd, que é um software bem conhecido. De fácil configuração e instalação. Suporta tanto TCP, quanto UDP.
Usei para testar todos os passos, que descrevo neste artigo, o Ubuntu Server 14.04.1.
Configurar a firewall
Este knockd, trabalha com o iptables, que é a firewall do Linux. Quando é reconhecida, uma sequência de pacotes, em determinados portos do sistema, é realizada uma acção de bloquear ou desbloquear um porto. Vou assumir, que este servidor, é apenas servidor web e que tem acesso, para administração, o protocolo SSH.
Como queremos, que os únicos portos abertos neste servidor, sejam os portos 80 e 443, para servir conteúdo web e o porto 22, para administração, vamos configurar a firewall de acordo. Claro que, se a vossas necessidades, forem diferentes, as regras terão de ser modificadas, para que vá de acordo, às vossas necessidades.
Regras de firewall
Esta regra, permite que todos os pacotes que cheguem à interface loopback, sejam aceites. Precisamos ter sempre a interface loopback desbloqueada, pois são muitos os processos que utilizam esta interface para comunicar entre si.
# iptables -A INPUT -i lo -j ACCEPT
Esta regra, permite que as ligações, que já estejam estabelecidas, se mantenham abertas, mesmo que uma regra, para fechar um determinado porto, seja inserida na firewall. Esta regra, é importante, como iremos perceber mais adiante, pois permite, que com apenas uma sequência abrir um porto. Depois, ligamos-nos ao serviço e num tempo estabelecido, a firewall fecha-se automaticamente, mas não corta a ligação, que estejamos a usar.
# iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Esta regra, permite manter o porto 80 sempre aberto, para disponibilizar conteúdo web, não seguro.
# iptables -A INPUT -p tcp --dport 80 -j ACCEPT
Esta regra, permite manter o porto 443 sempre aberto, para disponibilizar conteúdo web seguro.
# iptables -A INPUT -p tcp --dport 443 -j ACCEPT
Esta regra, permite fechar todos os outros portos, que não foram explicitamente abertos até aqui.
# iptables -A INPUT -j DROP
Estas regras, vão se perder se reiniciarmos o servidor. Para que estas regras, se tornem permanentes, vou instalar o iptables-persistent, que é um serviço, que trata de inserir as regras, todas as vezes que o servidor reiniciar. Para isso executamos:
# apt-get install iptables-persistent
Agora já podemos iniciar o serviço, para isso executamos:
# service iptables-persistent start
Bem, neste momento, já temos a nossa firewall configurada, se estão a trabalhar remotamente via SSH, não terminem a vossa sessão agora, pois o porto 22 está bloqueado na firewall, não vão conseguir uma nova ligação, apenas manter essa ligação.
Instalar o serviço knockd
Iremos agora instalar o serviço knockd, para configura-lo, para as nossas necessidades.
# apt-get install knockd
O serviço foi instalado, mas terá que ser configurado, antes de ser iniciado.
Diretivas de configuração do serviço knockd
O ficheiro de configuração do knockd, encontras-se em /etc/knockd.conf. O seu conteúdo é este por defeito.
[options] UseSyslog [openSSH] sequence = 7000,8000,9000 seq_timeout = 5 command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn [closeSSH] sequence = 9000,8000,7000 seq_timeout = 5 command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn
Ele vem configurado para funcionar com o SSH. Devido às configurações que fiz, na firewall para bloquear todo o tráfego de entrada e permitir apenas HTTP e HTTPS. A regra que vem por defeito não funciona, pois usa o parâmetro -A, acrescentar, que coloca a regra, no final da lista de regras, depois, da regra que fecha todos os portos. Nos exemplos que dou, essa regra, já está modificada, para usar o parâmetro -I, inserir, que permite inserir a regra, numa posição, que no caso é a posição 1.
Diretivas globais
Na secção “options”, temos a diretiva “UseSyslog”, que é utilizada, para enviar as mensagens, de abertura e fechamento de portos, para o log do sistema.
UseSyslog
Esta diretiva, permite-nos configurar um ficheiro, que será usado, pelo knockd, para escrever as mensagens de eventos que vão surgindo.
logfile = /caminho/para/o/ficheiro
A diretiva “pidfile”, permite-nos escolher, onde será criado o ficheiro com o ID do processo do knockd. Não vejo porque razão ousa-la, foi criada basicamente, para se adaptar às diferenças das distribuições Linux.
pidfile = /caminho/para/o/ficheiro
Diretivas de eventos
Esta diretiva, permite-nos informar, em que interface, o knockd fica a escutar as sequências, de pedidos, para abrir ou fechar portos. Esta diretiva, faz sentido nos sistemas com mais de que uma interface de rede.
interface = <nome da interface ex: eth0>
No ficheiro, temos também configurados dois eventos, “openSSH” e “closeSSH”, são estes eventos, que temos que configurar como desejarmos, para que cumpram as nossas necessidades. Existem várias diretivas, que podemos configurar para um evento.
Esta diretiva, especifica a sequência de portos, necessária, para ativar o respectivo evento. Ela aceita pares com, “port:protocolo”, o porto pode ser qualquer um até 65535 e protocolo pode ser TCP ou UDP, separados por virgula. Se não se definir o protocolo, por defeito é usado o TCP. Podemos usar uma sequência mista, com portos TCP e portos UDP, na mesma sequência.
sequence =2222:udp,3333:tcp,4444:udp
Esta diretiva, especifica o ficheiro, no qual irá ser lida a sequência, que será utilizada apenas uma vez. O conteúdo deste ficheiro, é organizado por linhas, cada linha, tem uma sequência de portos que serão usados. Após a utilização de uma linha, essa linha é comentada, com o carácter “#”, portanto convém que ao criar o ficheiro, que o primeiro carácter seja um espaço em branco, pois será substituído pelo comentário “#” e é utilizada a linha seguinte, para testar o evento seguinte. Esta diretiva, trás mais alguma segurança, mas também mais alguma complexidade. O ficheiro, não pode ser editado, enquanto está a ser utilizado pelo Knockd.
one_time_sequences = /caminho/para/o/ficheiro
Esta directiva especifica o tempo máximo em segundos que é esperado que uma sequência completa de portos chegue. O tempo começa a contar a partir do primeiro porto recebido. Se o tempo terminar antes de uma sequência completa chegar a sequência é descartada.
seq_timeout = <timeout>
Os pacotes de rede, podem ser marcados com vários tipos de bandeiras “flags”, o knockd, reconhece essas flags também. Dependendo do ambiente de rede, algumas flags, podem não funcionar. Por exemplo, num túnel SSH é importante utilizar a flag “syn” pois o SSH precisa marcar os pacotes dentro do túnel, e pode não funcionar bem, com algumas flags. Portanto, se configurarmos para usar flags e os pacotes não trazem estas flags, os pacotes são descartados. Estas flags, são separadas por virgulas e podem ser excluídas, com o ponto de exclamação “!”.
tcpflags = fin, syn, rst, psh, ack, !urg
Esta diretiva, especifica o comando, que será executado, quando uma sequência correta de portos, for recebida. No comando, sempre que for encontrado “%IP%”, será substituído, pelo IP real, de quem enviou a sequência de portos.
command = <comando a executar>
Esta diretiva, especifica o comando, que será executado, quando uma sequência correta de portos, for recebida. No comando, sempre que for encontrado “%IP%”, será substituído pelo IP real, de quem enviou a sequência de portos. A diretiva “comando”, é um aliais para esta diretiva.
start_command = <comando a executar>
Esta diretiva, especifica o tempo de espera, após a diretiva “start_command”, para executar a diretiva “stop_command”. Esta diretiva, não é obrigatória, só é necessária, se for usada a diretiva “stop_command”.
cmd_timeout = <timeout>
Esta diretiva, especifica o comando, que será executado, passado o tempo definido na diretiva “cmd_timeout”. No comando, sempre que for encontrado “%IP%” será substituído pelo IP real, de quem enviou a sequência de portos. Esta diretiva é opcional.
stop_command = <comando a executar>
Agora que vimos, as diretivas que podemos utilizar nas nossas configurações, podemos configurar o knockd, para as nossas necessidades.
Configurar o kcnockd
O kcnokd, pode trabalhar de duas formas, em relação à execução de comandos. De forma manual, onde é recebido uma sequência de portos, para abrir um determinado porto e outra sequência de portos, para fechar um determinado porto. De forma automática, onde é recebido uma sequência de portos, para abrir um determinado porto e depois de um tempo, executa automaticamente um comando, para fechar o porto aberto anteriormente.
Neste artigo, vou mostrar estes dois tipos de configuração, para o SSH.
Configuração manual
Esta é a configuração manual, para o serviço SSH. Desta forma é necessário duas sequências de portos, uma para abrir o porto e outra para fecha-lo.
[options] UseSyslog [openSSH] sequence = 4000,5000,6000 seq_timeout = 5 command = /sbin/iptables -I INPUT 1 -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn [closeSSH] sequence = 6000,5000,4000 seq_timeout = 5 command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn
Configuração automática
Esta é a configuração automática, para o serviço SSH. Desta forma, só é necessário, uma única sequência de portos, para acedermos ao serviço.
[options] UseSyslog [opencloseSSH] sequence = 1000,2000,3000 seq_timeout = 5 tcpflags = syn start_command = /sbin/iptables -I INPUT 1 -s %IP% -p tcp --dport 22 -j ACCEPT cmd_timeout = 10 stop_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
Ativar o Knockd para iniciar a cada boot
Agora, que temos duas configurações prontas a testar, precisamos de ativar o serviço. O ficheiro, que permite configurar se o serviço arranca a cada boot ou não, é:
/etc/default/knockd
O seu conteúdo, é este por defeito:
################################################ # # knockd's default file, for generic sys config # ################################################ # control if we start knockd at init or not # 1 = start # anything else = don't start # # PLEASE EDIT /etc/knockd.conf BEFORE ENABLING START_KNOCKD=0 # command line options #KNOCKD_OPTS="-i eth1"
Precisamos de mudar o valor da variável START_KNOCKD, para 1, como podemos ver abaixo.
START_KNOCKD=1
Depois, de termos mudado o valor da variável e guardado o ficheiro, podemos iniciar o serviço desta forma:
$ sudo service knockd start
Testar o serviço knockd
Neste momento, temos tudo configurado e pronto a ser usado. O que vamos ver agora, é como testar e usar o serviço knockd.
Testar a firewall
Antes de mais, temos que ver se a firewall, está mesmo a bloquear o protocolo SSH e para isso executamos o seguinte comando.
$ nmap -PN ubuntu-base Starting Nmap 5.21 ( http://nmap.org ) at 2014-11-23 03:12 WET Nmap scan report for ubuntu-base (192.168.1.61) Host is up (0.0028s latency). rDNS record for 192.168.1.61: ubuntu-base.ncdc.pt Not shown: 998 filtered ports PORT STATE SERVICE 80/tcp open http 443/tcp closed https Nmap done: 1 IP address (1 host up) scanned in 4.72 seconds
Como podemos ver, o porto 22, está fechado, portanto, a firewall, está a funcionar.
Instalar o knock para enviar as sequências
Para que possamos enviar as sequências de portos, a fim de abrir o porto do serviço SSH, no servidor, precisamos de um software, instalado na máquina que vai enviar as sequências.
Existe alguns softwares como o nmap, entre outros, que são capazes de enviar estas sequências de portos. No artigo, vou utilizar o cliente do knockd, que funciona muito bem, como veremos e é bastante fácil trabalhar com ele.
Precisamos instalar o seguinte software, na máquina que irá enviar as sequências de portos:
# apt-get install knockd
Agora que temos o software instalado na máquina cliente, podemos continuar.
Enviar sequências de portos
Para enviar sequências, utilizamos este comando, desta forma:
$ knock IP sequência
Enviar a sequência, ao servidor, que foi configurado para abrir e fechar o porto manualmente:
$ knock ubuntu-base 4000 5000 6000
Neste momento, se nos ligarmos ao servidor, já temos acesso ao serviço SSH:
$ ssh miguel@ubuntu-base
Para podermos fechar o acesso ao serviço SSH, enviamos a sequência de portos:
$ knock ubuntu-base 6000 5000 4000
Neste momento, o porto 22 do SSH, está novamente fechado. Mas atenção, que a ligação que está estabelecida, ao servidor, mantêm-se aberta. Apenas, novas ligações, são recusadas, devido à regra de firewall, que permite manter as ligações já estabelecidas.
Enviar a sequência ao servidor, que foi configurado para fechar o porto automaticamente:
$ knock ubuntu-base 1000 2000 3000
Neste momento, temos dez segundos, para iniciar a ligação ao serviço SSH. Após este tempo, que foi o tempo definido na configuração, o porto fecha-se automaticamente.
$ ssh miguel@ubuntu-base
É tudo, temos o serviço a funcionar.
O knockd, é importante para evitar bastantes ataques, que as máquinas ligadas à rede, sofrem todos os dias. É mais uma camada de segurança, que é adicionada à frente de um determinado serviço.
Partilhem, Comentem e Experimentem!