A autenticação SSH por palavra-passe é a maior superfície exposta de um servidor vulgar. Contra ela não podem nem o Fail2ban nem limiar nenhum: mil endereços a uma tentativa por hora nunca chegarão a um limite, e continuarão a tentar exatamente enquanto tentar for possível. As chaves eliminam essa possibilidade, e de toda a lista de robustecimento esta é a única definição que muda a situação de forma qualitativa.

Só uma coisa assusta: desligar a palavra-passe e ficar de fora. Esta é a ordem em que isso não pode acontecer.

A chave

Gera-se na sua máquina, não no servidor:

ssh-keygen -t ed25519 -C "portátil de trabalho"

ed25519 em vez de RSA: mais curta, mais rápida e sem perguntas sobre o comprimento. RSA só é preciso se tiver de chegar a algo muito antigo; nesse caso -t rsa -b 4096.

Pôr uma frase-passe na chave compensa: o ficheiro da chave pode ser roubado de um portátil, e sem frase-passe funciona de imediato. Não terá de a escrever de cada vez, disso trata o ssh-agent, e no macOS e na maioria dos Linux de secretária já está a correr.

A cópia para o servidor é um comando, enquanto a palavra-passe ainda funciona:

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@203.0.113.25

Se o ssh-copy-id não estiver disponível, o conteúdo do ficheiro .pub acrescenta-se como linha ao ~/.ssh/authorized_keys no servidor. As permissões importam: a pasta .ssh a 700, o ficheiro a 600, pertencentes ao próprio utilizador. Com outras permissões o sshd recusa-se em silêncio a ler o ficheiro, e essa é a causa mais frequente de «a chave não funciona».

A verificação que decide

Antes de desligar seja o que for, abra uma segunda ligação sem fechar a primeira:

ssh -o PasswordAuthentication=no user@203.0.113.25

A opção proíbe o cliente de recorrer à palavra-passe: se o acesso resultar, resultou pela chave. Enquanto esse comando não passar, não avance. E mantenha a primeira ligação aberta até ao fim: é por ela que se repara tudo o que estragar.

O corte e uma armadilha pouco óbvia

As definições vão para um ficheiro à parte para que uma atualização do pacote não as apague. Mas o nome do ficheiro importa:

sudo tee /etc/ssh/sshd_config.d/10-hardening.conf <<'EOF'
PasswordAuthentication no
PermitRootLogin no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LogLevel VERBOSE
EOF

Acontece que o OpenSSH usa o primeiro valor obtido para um parâmetro, e não o último como em quase tudo o resto. Os ficheiros de sshd_config.d são lidos por ordem alfabética, e as imagens de nuvem do Ubuntu deixam lá o 50-cloud-init.conf, onde consta muitas vezes PasswordAuthentication yes. O seu ficheiro com o número 90 nessa situação não fará nada: a definição parece estar lá e a palavra-passe continua a funcionar. Daí o número 10, que é lido mais cedo.

O que saiu na realidade vê-se sem adivinhar:

sudo sshd -T | grep -Ei 'passwordauth|permitrootlogin|pubkeyauth'

Esse comando imprime a configuração efetiva depois de todas as inclusões. Acredite nele, não no conteúdo dos ficheiros.

Depois, verificação de sintaxe e recarga suave do serviço:

sudo sshd -t && sudo systemctl reload ssh

sshd -t é obrigatório: um erro de escrita na configuração deixará o serviço em baixo com restart e a si de fora. O reload, além disso, não corta as sessões abertas.

Ubuntu 24.04: a porta não está onde julga

Uma armadilha própria dos Ubuntu recentes: ali o sshd é iniciado através de um socket do systemd. Nesse modo a linha Port no sshd_config não faz nada: quem escuta é o socket, não o serviço. Se muda a porta, é ele que tem de ser alterado:

sudo systemctl edit ssh.socket

e o ListenStream= (um valor vazio reinicia o anterior) tem de indicar a porta nova. O sintoma que o denuncia: a configuração está alterada, o serviço reiniciado, e o servidor continua a responder na 22.

A propósito da mudança de porta: como proteção não funciona, os verificadores encontram um serviço em qualquer porta em minutos. O seu único efeito são registos mais tranquilos, porque a busca em massa vai só para a 22. É cómodo, mas não o confunda com segurança.

Quem pode entrar

Um acrescento útil é uma lista explícita:

AllowUsers deploy admin

Tudo o que não constar dela é recusado ainda antes da verificação da chave. Isso cobre também o caso de algum pacote criar um utilizador de sistema com interpretador de comandos e pasta pessoal.

Uma entrada de reserva

Uma chave num portátil é um ponto único de falha. O disco morre, o portátil perde-se, e o servidor fica inacessível para sempre. Um mínimo razoável:

  • uma segunda chave, a partir de outro dispositivo, no authorized_keys;
  • uma cópia da chave privada num gestor de palavras-passe ou numa pen cifrada;
  • um acesso de consola do alojamento já testado: VNC ou série. Testado significa que já entrou por ele pelo menos uma vez, não que «há um botão algures no painel».

Aproveite para ver o que já está no authorized_keys, tanto do seu utilizador como do root. Uma chave alheia ali sobrevive a qualquer mudança de palavra-passe e continua a ser um acesso operacional.

Depois

A busca de palavras-passe não desaparecerá, apenas se torna inútil: nos registos ficarão milhares de linhas Failed password, nenhuma das quais pode terminar em êxito. O que vale agora a pena observar são os acessos bem-sucedidos: de que endereço, com que utilizador, a que hora. Um acesso bem-sucedido por chave a partir de um endereço desconhecido é um acontecimento muito mais importante do que um milhão de falhas, e bastante mais difícil de notar no fluxo geral. É precisamente esse o quadro que a página de demonstração abaixo mostra.