SSH por dentro: o protocolo, as chaves e o OpenSSH
Uma imersão no SSH: as três camadas do protocolo, a troca de chaves, a autenticação por chave e certificado, túneis, o OpenSSH e as falhas recentes.

Quase todo servidor Linux do mundo é administrado por SSH. É por ele que se entra no servidor para ver um log, que o código chega ao servidor numa implantação, que os arquivos de backup são copiados, que o repositório Git é clonado e que boa parte das ferramentas de automação conversa com as máquinas. É tão comum que ninguém pensa nele, até o dia em que um aviso diz que a "identificação do servidor mudou", ou que uma notícia anuncia uma falha que permite entrar num servidor sem senha.
O SSH resolve um problema que, em 1995, era muito concreto: os protocolos de acesso remoto da época mandavam tudo em texto aberto, inclusive as senhas. Ele cifra a conexão, autentica o servidor para o cliente e o cliente para o servidor, e permite passar outros tráfegos por dentro do mesmo túnel. Cada uma dessas coisas tem um mecanismo próprio, e entender os mecanismos é o que permite usar o SSH com segurança.
O artigo segue em quatro partes. A primeira conta de onde veio o SSH e como o protocolo é organizado, em três camadas. A segunda trata da criptografia: a troca de chaves, a chave do servidor e a autenticação do usuário, com chaves e certificados. A terceira cobre o uso: túneis, saltos, multiplexação e transferência de arquivos. A quarta trata do OpenSSH, das falhas recentes que mudaram a forma de configurar os servidores, das boas práticas e dos erros comuns.
De onde veio o SSH
Um ataque na universidade
O SSH foi criado por Tatu Ylönen, pesquisador da Universidade de Tecnologia de Helsinque, depois de um ataque de captura de senhas na rede da universidade, em 1995 [1]. A primeira versão, o SSH-1, foi pensada para substituir o rlogin, o telnet, o FTP e o rsh, que não tinham autenticação forte nem confidencialidade, e foi lançada como software gratuito em julho daquele ano [1]. Em dezembro de 1995, Ylönen fundou a SSH Communications Security, e as versões seguintes da empresa foram ficando cada vez mais proprietárias [1].
A adoção foi rápida. Segundo os números citados pela Wikipédia, a partir de um livro de 2001 sobre o assunto, o SSH tinha cerca de 20 mil usuários em cinquenta países no fim de 1995 e cerca de 2 milhões em 2000 [1].
O SSH-2 e o padrão
O SSH-1 tinha falhas de projeto, como uma de 1998 que permitia inserir conteúdo numa sessão, e hoje é considerado obsoleto [1]. A versão 2, incompatível com a primeira, foi padronizada pelo grupo de trabalho "secsh" do IETF, e os documentos centrais saíram em janeiro de 2006 [1]. A arquitetura está na RFC 4251, assinada por Tatu Ylönen e C. Lonvick [2].
O OpenSSH
Em 1999, desenvolvedores do OpenBSD criaram o OpenSSH a partir de uma bifurcação do OSSH, de Björn Grönvall, que por sua vez partia da última versão do SSH original publicada com licença aberta; o OpenSSH saiu com o OpenBSD 2.6 e é hoje a implementação mais usada [1]. É dele que vêm o cliente ssh, o servidor sshd e as ferramentas ssh-keygen, ssh-agent, scp e sftp que vêm em praticamente todo Linux, no macOS e no Windows.

As três camadas do protocolo
A RFC 4251 organiza o SSH em três protocolos, cada um rodando sobre o anterior [2].

Transporte
O protocolo de transporte autentica o servidor, garante a confidencialidade e a integridade da conexão e, opcionalmente, a compressão; normalmente roda sobre uma conexão TCP/IP [2]. É ele que faz a troca de chaves e cifra tudo o que vem depois.
Autenticação do usuário
O protocolo de autenticação do usuário autentica o usuário do lado do cliente para o servidor, e roda sobre o de transporte [2]. Quando ele começa, a conexão já está cifrada: a senha ou a prova de posse da chave nunca passam em texto aberto.
Conexão
O protocolo de conexão divide o túnel cifrado em vários canais lógicos, e roda sobre o de autenticação [2]. É ele que permite, numa mesma conexão, ter uma sessão de terminal, executar comandos, transferir arquivos e encaminhar portas.
A separação em camadas tem uma vantagem prática: cada problema tem o seu lugar. Um aviso de chave de host trocada é da camada de transporte; uma falha de login, da de autenticação; um túnel que não abre, da de conexão.
O transporte por dentro
A troca de versões
A conexão começa com uma troca de texto simples: cada lado envia uma linha de identificação no formato SSH-versãodoprotocolo-versãodosoftware, seguida de comentários opcionais [3]. A versão do protocolo precisa ser 2.0, e a linha tem no máximo 255 caracteres [3]. Numa conexão real, a linha do servidor costuma dizer algo como SSH-2.0-OpenSSH_10.0, e é por isso que ferramentas de varredura conseguem descobrir a versão do OpenSSH de um servidor sem se autenticar.
Os pacotes
Depois disso, tudo viaja em pacotes binários com campos fixos: o tamanho do pacote, o tamanho do preenchimento, a carga, que pode vir comprimida, pelo menos quatro bytes de preenchimento aleatório e o código de autenticação da mensagem, que fica vazio até um algoritmo de autenticação ser combinado [3]. O preenchimento completa o pacote até um múltiplo do tamanho de bloco da cifra ou de 8 bytes, o que for maior [3], para esconder o tamanho exato do que é enviado.
A troca de chaves
O passo central do transporte é a troca de chaves. Os dois lados combinam os algoritmos e, por meio de uma troca baseada em criptografia de chave pública, chegam a um segredo compartilhado, K, e a um resumo da troca, H, sem que ninguém que observe a rede consiga calcular o segredo [3]. O resumo H da primeira troca serve também como identificador da sessão, e esse identificador não muda mesmo que as chaves sejam renegociadas depois [3]. Das chaves derivadas do segredo saem as chaves da cifra e da autenticação das mensagens.
A troca de chaves de novo
A RFC recomenda trocar as chaves depois de cada gigabyte de dados transmitidos ou de cada hora de conexão, o que vier primeiro, com a ressalva de que a troca é uma operação de chave pública e não deve acontecer com frequência demais [3]. Em conexões longas, como um túnel que fica aberto o dia inteiro, isso limita a quantidade de dados protegidos pela mesma chave.
O pedido de serviço
Terminada a troca de chaves, o cliente pede um serviço pelo nome, como ssh-userauth, e o servidor aceita ou encerra a conexão [3]. É aí que começa a camada de autenticação do usuário.
A troca de chaves pós-quântica
A troca de chaves do SSH mudou muito nos últimos anos, por causa de uma ameaça que ainda não existe na prática: o computador quântico.
Guardar agora, decifrar depois
A privacidade de uma sessão SSH depende da troca de chaves. A página do OpenSSH sobre o assunto explica o risco: um atacante pode gravar hoje sessões cifradas e decifrá-las no futuro, quando houver um computador quântico capaz de quebrar a criptografia de chave pública atual; é o ataque conhecido como "guardar agora, decifrar depois" [4]. Para dados que precisam continuar secretos por anos, como as credenciais e as configurações que passam por uma sessão de administração, o risco é real hoje.
Os algoritmos híbridos
Por isso, o OpenSSH usa troca de chaves pós-quântica por padrão desde a versão 9.0, de abril de 2022, quando o algoritmo sntrup761x25519-sha512 passou a ser o padrão [4][5]. O algoritmo mlkem768x25519-sha256, baseado no ML-KEM, foi acrescentado na versão 9.9 e virou o padrão na versão 10.0, de abril de 2025 [4][5].
Os dois são híbridos: combinam um algoritmo pós-quântico com o X25519, a troca de chaves clássica por curvas elípticas [4]. A vantagem é de segurança: se a parte pós-quântica for quebrada no futuro, a combinação não fica mais fraca do que a troca clássica sozinha [4].
O aviso da versão 10.1
A partir da versão 10.1, o cliente passa a registrar um aviso quando uma conexão usa uma troca de chaves que não é pós-quântica, controlado pela nova opção WarnWeakCrypto, ligada por padrão [4][5]. A recomendação para quem vê o aviso é atualizar o servidor ou conferir se a opção KexAlgorithms não está desligando os algoritmos pós-quânticos [4].
E as assinaturas
As assinaturas RSA e ECDSA também são vulneráveis aos computadores quânticos, mas o OpenSSH considera o problema menos urgente: forjar uma assinatura no futuro não expõe o tráfego passado, como acontece com a quebra da troca de chaves [4]. A prioridade é aposentar as chaves de assinatura clássicas antes de os computadores quânticos se tornarem práticos, e o OpenSSH planeja acrescentar assinaturas pós-quânticas [4]. A página de manual do ssh-keygen já lista um tipo híbrido, o mldsa44-ed25519, entre os tipos de chave aceitos [6].
A chave do servidor
A troca de chaves garante que ninguém no meio da rede leia a conversa. Mas não garante, sozinha, que o cliente está falando com o servidor certo. Quem garante isso é a chave de host.
Por que ela existe
Cada servidor deve ter uma chave de host, e o cliente a usa durante a troca de chaves para conferir que está falando com o servidor correto; para isso, precisa conhecer de antemão a chave pública do servidor [2]. Sem essa conferência, um atacante no meio do caminho poderia fazer uma troca de chaves com o cliente fingindo ser o servidor, e outra com o servidor fingindo ser o cliente, lendo tudo no meio.
Os dois modelos de confiança
A RFC 4251 descreve duas formas de o cliente conhecer a chave do servidor [2]:
- uma base local: o cliente guarda um mapa do nome de cada servidor para a sua chave pública; não precisa de infraestrutura central, mas a base pode ficar trabalhosa de manter;
- uma autoridade certificadora: uma autoridade confiável certifica a associação entre o nome e a chave, e o cliente só precisa conhecer a chave da autoridade; em troca, toda chave de host precisa ser certificada antes do uso.
No OpenSSH, a base local é o arquivo ~/.ssh/known_hosts, e o sistema também consulta o /etc/ssh/ssh_known_hosts [7].
A primeira conexão
O protocolo permite pular a conferência na primeira conexão, e é o que acontece quando o cliente pergunta "a autenticidade do servidor não pode ser estabelecida; deseja continuar?". A RFC é clara sobre o custo: a conexão continua protegida contra quem só escuta a rede, mas fica vulnerável a um ataque ativo de intermediário [2]. Responder "sim" sem conferir a impressão digital é confiar no primeiro que atender. A conferência pode ser feita comparando a impressão digital mostrada com a que o administrador do servidor obteve no próprio servidor, por um canal confiável, como o console da máquina ou o painel do provedor.
Quando a chave muda
Se a chave de um servidor conhecido muda, o cliente avisa e desliga a autenticação por senha, para não entregar a senha a um impostor [7]. A opção StrictHostKeyChecking controla como o cliente trata as chaves desconhecidas e as trocadas [7]. Uma chave que mudou pode ter explicação, como a reinstalação do servidor, mas o aviso deve ser conferido, e não contornado apagando a linha do known_hosts por reflexo.
Há duas formas de tornar a conferência menos manual. A primeira é publicar as impressões digitais no DNS, em registros SSHFP, que o cliente compara com a chave apresentada, controlado pela opção VerifyHostKeyDNS [7]. O tipo de registro foi definido pela RFC 4255, de janeiro de 2006, com o código 44, e traz o algoritmo da chave, o tipo de resumo e a impressão digital [22]. A RFC tem uma condição que não pode ser esquecida: uma chave conferida assim não deve ser considerada confiável se o registro não tiver sido autenticado pelo DNSSEC [22]. Sem o DNSSEC, um atacante que falsifique a resposta do DNS falsifica também a impressão digital, e a conferência não vale nada.
A segunda forma é o modelo de autoridade certificadora, com os certificados de host, tratados adiante.

A autenticação do usuário
Com a conexão cifrada e o servidor conferido, falta o servidor saber quem é o usuário.
Os métodos
A RFC 4252 define os métodos de autenticação [8]: a chave pública, obrigatória em toda implementação; a senha e a autenticação baseada no host, opcionais; e o método none, reservado, que não pode ser anunciado e serve principalmente para o cliente perguntar quais métodos o servidor aceita. É o servidor que conduz: ele diz ao cliente quais métodos podem continuar, e o cliente os tenta em qualquer ordem [8].
Vários passos
O protocolo permite exigir mais de um método. Uma resposta de falha traz um indicador de "sucesso parcial", verdadeiro quando o passo deu certo mas ainda faltam outros, e a mensagem de sucesso só é enviada quando todos os passos terminam [8]. É o que permite exigir, por exemplo, uma chave e um código de uso único.
Os limites
A RFC recomenda que o servidor desconecte depois de um tempo sem autenticação, de 10 minutos, e limite as tentativas falhas, com um limite recomendado de 20 por sessão [8]. O OpenSSH é mais rígido: o tempo padrão para autenticar, o LoginGraceTime, é de 120 segundos [9].
Como a chave pública prova a identidade
Na autenticação por chave pública, o cliente assina um bloco de dados que começa com o identificador da sessão e inclui os detalhes do pedido; como o servidor consegue conferir essa assinatura com a chave pública, a assinatura prova que o cliente tem a chave privada correspondente [8]. Dois detalhes tornam o método forte. A chave privada nunca sai do cliente: o servidor recebe só uma assinatura. E a assinatura inclui o identificador da sessão, que é diferente a cada conexão, por isso não pode ser reaproveitada numa sessão de um atacante.
Comparada à senha, a vantagem é grande. Uma senha fraca pode ser adivinhada; uma senha reaproveitada pode vazar de outro serviço; uma senha digitada num servidor falso é entregue ao falsário. Nada disso acontece com uma chave.
As chaves do usuário
Os tipos
O ssh-keygen gera chaves de vários tipos: ecdsa, ecdsa-sk, ed25519, que é o padrão, ed25519-sk, rsa e o híbrido mldsa44-ed25519 [6]. O DSA foi removido do OpenSSH na versão 10.0, completando uma descontinuação que começou em 2015 [5].
As recomendações da Mozilla para o OpenSSH resumem a escolha: usar o Ed25519 quando não houver necessidade de compatibilidade com sistemas muito antigos, e, para compatibilidade, uma chave RSA de 4.096 bits [10].
# uma chave Ed25519, com um comentário que identifica o dono
ssh-keygen -t ed25519 -C "maria@notebook"
Por que o Ed25519
O algoritmo ssh-ed25519 foi padronizado para o SSH pela RFC 8709, de fevereiro de 2020, que trouxe também o ssh-ed448; os dois servem só para assinatura, e os procedimentos vêm da especificação do EdDSA, a RFC 8032 [21]. No Ed25519, a chave pública tem 32 bytes, e a assinatura, 64 [21].
O tamanho pequeno tem efeitos práticos. Uma linha do authorized_keys com uma chave Ed25519 cabe numa linha de terminal, enquanto uma RSA de 4.096 bits ocupa várias; a geração da chave e as assinaturas são rápidas; e não há um tamanho de chave a escolher, e portanto não há como escolher um fraco demais. Somados à recomendação da Mozilla e ao fato de ser o tipo padrão do ssh-keygen atual, esses motivos explicam por que o Ed25519 virou a escolha de referência [6][10].
Chaves em dispositivos físicos
Os tipos terminados em -sk usam um autenticador físico, como uma chave de segurança FIDO: o arquivo da chave privada guarda só um identificador, e a chave privada de verdade fica no dispositivo, sem poder ser exportada [6]. Opcionalmente, a chave pode ficar residente no próprio dispositivo, o que facilita o uso em vários computadores, mas aumenta o risco se ele for roubado [6]. Com uma chave -sk, quem rouba o arquivo do notebook não consegue usá-lo sem o dispositivo.
A frase-senha e a separação de chaves
A Mozilla recomenda proteger as chaves de usuário com uma frase-senha forte e nunca copiá-las para fora da própria estação de trabalho ou dos dispositivos pessoais [10]. As chaves de máquinas, usadas por automações, podem não ter frase-senha, mas devem ser únicas para cada uso, restritas aos privilégios mínimos e registradas num inventário; e devem evitar contas de root ou com sudo [10]. Também recomenda usar chaves separadas para propósitos diferentes [10].
O ssh-agent
Digitar a frase-senha a cada conexão cansa, e é para isso que existe o ssh-agent: ele guarda as chaves privadas usadas na autenticação por chave pública, e o ssh recorre a ele ao entrar em outras máquinas [18]. As chaves são acrescentadas com o ssh-add, ou pelo próprio ssh, quando a opção AddKeysToAgent está ligada [18]. A página de manual destaca que as frases-senha e as chaves privadas nunca passam pela rede: o agente faz a assinatura e devolve só o resultado [18].
O cliente encontra o agente pela variável de ambiente SSH_AUTH_SOCK, que aponta para um socket criado quando o agente inicia [18]. O manual é honesto sobre o limite dessa proteção: o socket só é acessível ao próprio usuário, mas pode ser usado facilmente pelo root ou por outra instância do mesmo usuário [18]. Por padrão, as chaves ficam no agente para sempre; a opção -t define um tempo máximo de vida, e o ssh-add pode definir um tempo para cada chave [18]. A Mozilla sugere, quando for preciso usar o agente de forma mais cuidadosa, pedir confirmação a cada uso, com ssh-add -c, ou dar um prazo de validade às chaves carregadas, com ssh-add -t [10].
Um agente com as chaves carregadas o dia inteiro, numa máquina compartilhada, é um agente que qualquer processo com privilégio suficiente pode usar. Um prazo de algumas horas, que obriga a digitar a frase-senha de novo depois do almoço, é um custo pequeno para um risco grande.
Certificados SSH
Com dezenas de servidores e de pessoas, manter os arquivos authorized_keys e known_hosts em todo lugar vira um trabalho em si. Os certificados do OpenSSH resolvem isso com uma autoridade certificadora, o segundo modelo de confiança da RFC 4251 [2].
Como funcionam
O ssh-keygen assina uma chave pública com a chave de uma autoridade e produz um certificado de usuário ou de host [6]. O certificado reúne a chave pública, uma identidade, um ou mais principais, que são os nomes de usuário ou de servidor para os quais ele vale, e opções [6]. As opções principais do comando são [6]:
-s: a chave da autoridade usada para assinar;-I: a identidade da chave, usada nos registros e na revogação;-n: os principais;-h: gera um certificado de host, em vez de usuário;-V: o intervalo de validade.
# um certificado de usuário, válido por 8 horas, para o usuário "deploy"
ssh-keygen -s ca_usuarios -I maria-2026-11-16 -n deploy -V +8h id_ed25519.pub
O que muda
Com certificados de usuário, o servidor não precisa de uma lista das chaves de cada pessoa: basta confiar na chave da autoridade. Com certificados de host, o cliente não precisa conferir a impressão digital de cada servidor: basta confiar na autoridade dos hosts, e o aviso da primeira conexão desaparece. E a validade curta muda a gestão de acessos: um certificado de oito horas, emitido a cada manhã, expira sozinho, e quem sai da equipe deixa de ter acesso sem que ninguém precise caçar a chave dele em cada servidor.
Revogação
Para os casos em que é preciso cancelar uma chave ou um certificado antes da hora, o OpenSSH tem as listas de revogação de chaves, os arquivos KRL, um formato binário compacto que lista as chaves e os certificados revogados, criados e consultados pelo próprio ssh-keygen [6].
Restringir o que cada chave pode fazer
Uma linha do authorized_keys não precisa dar acesso total. O formato aceita opções antes da chave, que restringem o que pode ser feito com ela [16].
As opções
As opções mais úteis são estas [16]:
- **
command="...":** força um comando a cada uso da chave, ignorando o que o cliente pediu; o comando original fica na variávelSSH_ORIGINAL_COMMAND; - **
from="...":** exige, além da chave, que a origem case com uma lista de nomes ou endereços, inclusive em notação CIDR; - **
no-port-forwarding**, **no-agent-forwarding**, **no-pty** e **no-X11-forwarding:** bloqueiam, cada uma, um recurso; - **
permitopen="host:porta":** limita os encaminhamentos locais a um destino específico; - **
restrict:** liga todas as restrições de uma vez, desligando os encaminhamentos de porta, de agente e de X11, a alocação de terminal e o~/.ssh/rc, e inclui automaticamente as restrições que vierem a existir no futuro; - **
expiry-time="...":** recusa a chave depois de uma data; - **
cert-authority:** marca a chave como uma autoridade certificadora, cujos certificados de usuário são aceitos, e oprincipals=limita os principais aceitos.
Uma chave de backup
O exemplo da página de manual mostra o uso típico: uma chave que só pode rodar um comando de backup, sem terminal nem encaminhamentos [16].
restrict,command="/usr/local/bin/backup-diario",from="10.0.5.20" ssh-ed25519 AAAA... backup@servidor-backup
Com essa linha, mesmo que a chave do servidor de backup vaze, quem a tiver só consegue rodar o backup, e só a partir do endereço do servidor de backup. Sem as opções, a mesma chave daria um terminal completo.
O restrict tem uma vantagem sobre a lista de proibições individuais: como ele inclui as restrições futuras, uma versão nova do OpenSSH que acrescente um recurso não abre uma porta nova numa chave restrita [16]. E é possível reabrir um recurso específico, como o terminal, com restrict,pty [16].
Chaves que expiram
O expiry-time dá às chaves comuns uma validade, como os certificados têm [16]. Para um acesso temporário, como o de um fornecedor durante uma implantação, uma chave com data de expiração evita a situação comum em que o acesso continua lá anos depois de o projeto terminar.
Quando uma chave vaza
Mais cedo ou mais tarde, uma chave vaza: um notebook roubado, um arquivo copiado para o lugar errado, uma chave de automação esquecida num repositório. O que fazer depende de como os acessos foram montados.
**Com chaves soltas no authorized_keys**, é preciso remover a linha da chave em cada servidor onde ela foi cadastrada. É aqui que a falta de inventário cobra o preço: sem saber onde a chave estava, não há como ter certeza de que ela foi removida de todo lugar. Um LogLevel VERBOSE, que registra a impressão digital da chave em cada login, ajuda a descobrir onde ela foi usada [10].
Com certificados, o caminho é a revogação: a chave ou o certificado entra na lista de revogação do OpenSSH, o arquivo KRL, gerado e consultado pelo ssh-keygen, e os servidores passam a recusá-lo [6]. Se os certificados forem de validade curta, como algumas horas, o problema se resolve sozinho no fim do prazo, mesmo antes da revogação chegar a todos os servidores.
Para chaves de host, a marcação @revoked no known_hosts faz o cliente nunca mais aceitar aquela chave e avisar quando a encontrar [16].
Em todos os casos, a chave vazada é substituída por uma nova, e o incidente deixa uma lição para o desenho: quanto menos tempo uma credencial vale e quanto menos ela pode fazer, menor é o estrago quando ela vaza. É o argumento mais forte a favor dos certificados de validade curta e das restrições no authorized_keys.
Certificados no servidor e no cliente
A seção sobre certificados mostrou como emiti-los. Para que funcionem, os dois lados precisam confiar nas autoridades.
No servidor
Do lado do servidor, a opção TrustedUserCAKeys lista as chaves das autoridades que assinam certificados de usuário; os certificados só são aceitos se trouxerem uma lista de principais, e os sem principais são recusados [15]. Para que o servidor apresente o próprio certificado de host, a opção HostCertificate aponta o arquivo do certificado, cuja chave pública precisa casar com uma das HostKey configuradas [15].
# /etc/ssh/sshd_config
TrustedUserCAKeys /etc/ssh/ca_usuarios.pub
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
No cliente
Do lado do cliente, o known_hosts aceita a marcação @cert-authority antes de uma chave, que a torna uma autoridade: qualquer servidor do domínio indicado que apresente um certificado assinado por ela é aceito [16]. E a marcação @revoked marca uma chave como revogada: ela nunca é aceita, e o cliente avisa quando a encontra [16].
# ~/.ssh/known_hosts
@cert-authority *.exemplo.com.br ssh-ed25519 AAAA... ca-hosts
Com essa única linha, o cliente confia em todos os servidores do domínio que tiverem certificado de host, sem perguntar nada na primeira conexão, e sem que alguém precise distribuir as impressões digitais de cada servidor.
Contas só para transferir arquivos
Um caso muito comum é dar a um parceiro acesso para enviar ou buscar arquivos, como arquivos de retorno bancário, notas fiscais ou relatórios, sem dar a ele um terminal no servidor. O OpenSSH resolve isso com duas opções [15].
ForceCommand e ChrootDirectory
O ForceCommand roda um comando fixo no lugar do que o cliente pedir, e o valor internal-sftp força um servidor SFTP embutido no próprio sshd [15]. O ChrootDirectory confina a sessão numa pasta depois da autenticação: o usuário passa a ver aquela pasta como a raiz do sistema [15]. A página de manual impõe uma condição: todos os componentes do caminho precisam pertencer ao root e não podem ter permissão de escrita para o grupo nem para os outros [15].
# /etc/ssh/sshd_config
Match Group parceiros-sftp
ChrootDirectory /srv/sftp/%u
ForceCommand internal-sftp
DisableForwarding yes
PasswordAuthentication no
O detalhe dos encaminhamentos
O exemplo tem uma linha que costuma ser esquecida. A página de manual avisa que o ForceCommand não restringe os encaminhamentos de porta, que precisam do DisableForwarding ou das opções específicas de cada recurso [15]. Sem ela, um parceiro com acesso só de SFTP ainda poderia usar o servidor como ponte para a rede interna, com um encaminhamento local.
Como o usuário não consegue gravar na raiz confinada, que pertence ao root, a prática é criar dentro dela uma pasta de trabalho que pertença a ele, como /srv/sftp/parceiro/entrada.
RSA, SHA-1 e as assinaturas
Muitos servidores antigos ainda usam chaves RSA, e uma mudança de 2018 explica avisos e falhas de conexão que aparecem em sistemas velhos.
O problema do ssh-rsa
O algoritmo de assinatura original das chaves RSA no SSH, o ssh-rsa, usa o SHA-1. A RFC 8332, de março de 2018, registra que os algoritmos originais "são hoje considerados deficientes" e que o NIST não permite mais o SHA-1 para gerar assinaturas digitais, fora de orientações específicas [17]. Ela definiu dois algoritmos novos para as chaves RSA: o rsa-sha2-256, recomendado, e o rsa-sha2-512, opcional, ambos com resumos SHA-2 [17].
A mesma chave, outra assinatura
A parte importante da RFC é que a chave não muda: as chaves RSA existentes funcionam com os algoritmos novos sem nova codificação, mantêm o formato ssh-rsa de chave pública, e as impressões digitais já confiadas continuam valendo [17]. O que muda é o algoritmo da assinatura.
Isso explica uma confusão comum. Quando um cliente novo se recusa a conectar num servidor muito antigo com uma chave RSA, o problema raramente é a chave: é o servidor antigo, que só sabe assinar com SHA-1. A solução certa é atualizar o servidor; a solução de emergência, reativar o ssh-rsa só para aquele servidor no ~/.ssh/config, deve ser tratada como temporária. E, para chaves novas, a recomendação continua sendo o Ed25519 [6][10].
A conexão: canais e túneis
A camada de conexão é a que dá ao SSH a versatilidade que vai muito além do terminal remoto.
Os canais
O protocolo de conexão oferece sessões interativas, execução remota de comandos, encaminhamento de conexões TCP/IP e de X11, tudo multiplexado num único túnel cifrado [11]. Tudo isso são canais: qualquer um dos lados pode abrir um canal, vários canais dividem a mesma conexão, e cada canal tem controle de fluxo por uma janela, que limita quantos bytes podem ser enviados até o outro lado liberar mais [11].
Os tipos de canal são quatro [11]:
- session: roda um terminal, um comando ou um subsistema, como o SFTP;
- x11: leva conexões gráficas encaminhadas;
- forwarded-tcpip: aberto pelo servidor quando chega uma conexão numa porta encaminhada remotamente;
- direct-tcpip: pede ao outro lado que se conecte a um endereço e porta, para um encaminhamento local.
A RFC tem regras de segurança para eles: os clientes devem recusar pedidos de abertura de sessão vindos do servidor, e as implementações devem recusar os canais de X11 e de portas que não foram pedidos [11].
Os encaminhamentos de porta
O cliente ssh tem três formas de encaminhar portas [7]:
- **local, com
-L:** as conexões a uma porta do computador local são levadas pelo túnel e saem do lado do servidor; - **remoto, com
-R:** o inverso, uma porta no servidor é encaminhada de volta para o cliente; por padrão, ela só escuta no endereço local do servidor, a menos que oGatewayPortspermita outra coisa; - **dinâmico, com
-D:** osshvira um proxy SOCKS, nas versões 4 e 5 do protocolo.
# acessar, do notebook, um banco que só escuta dentro da rede do servidor
ssh -L 5433:localhost:5432 usuario@servidor
# agora, psql -h localhost -p 5433 chega ao banco pelo túnel
O encaminhamento local é a forma mais segura de acessar um serviço interno, como um banco de dados, sem expô-lo à internet: o banco continua escutando só na rede interna, e o acesso passa pelo SSH, com toda a autenticação dele.

Saltar por um servidor intermediário
Muitas redes só permitem chegar aos servidores internos passando por um servidor de entrada, o bastião. A opção -J, o ProxyJump, faz isso de uma vez: o ssh conecta primeiro ao servidor intermediário e, de lá, encaminha uma conexão TCP até o destino [7].
ssh -J bastiao.exemplo.com.br usuario@servidor-interno
A grande vantagem sobre a alternativa antiga, entrar no bastião e de lá conectar ao destino, é que as chaves continuam só no notebook: a autenticação no servidor interno é feita de ponta a ponta, pelo túnel.
O risco do encaminhamento do agente
A alternativa antiga costumava vir com o encaminhamento do agente, a opção -A, para que as chaves do notebook pudessem ser usadas a partir do bastião. A página de manual do ssh alerta: usuários capazes de contornar as permissões de arquivos no servidor remoto conseguem acessar o agente local pela conexão encaminhada; não conseguem extrair as chaves, mas conseguem usá-las para se autenticar onde quiserem enquanto o encaminhamento estiver ativo [7]. A própria página sugere o servidor de salto como opção mais segura [7], e a Mozilla recomenda não manter o encaminhamento do agente quando ele não for necessário e preferir o ProxyJump [10].
Usar o SSH no dia a dia
O arquivo de configuração
O arquivo ~/.ssh/config evita digitar as mesmas opções a cada conexão. Os blocos Host e Match limitam as opções seguintes aos servidores ou condições que casam com eles, e, como vale o primeiro valor encontrado, as configurações específicas devem vir no começo do arquivo e os padrões gerais no fim [12].
Host interno-*
ProxyJump bastiao.exemplo.com.br
User deploy
IdentityFile ~/.ssh/id_ed25519_deploy
IdentitiesOnly yes
Host *
ServerAliveInterval 60
HashKnownHosts yes
Algumas opções resolvem problemas conhecidos. O IdentitiesOnly faz o cliente usar só as chaves configuradas, mesmo que o agente ofereça outras, o que evita ser recusado por excesso de tentativas quando o agente guarda muitas chaves [12]. O ServerAliveInterval manda mensagens de manutenção cifradas quando a conexão fica sem dados, evitando que um firewall derrube uma sessão parada [12]. E o HashKnownHosts, recomendado pela Mozilla, guarda os nomes dos servidores do known_hosts em forma de resumo, para esconder a quais servidores as suas chaves dão acesso se o arquivo vazar [10].
Reaproveitar a conexão
A troca de chaves e a autenticação levam algum tempo, e, para quem abre muitas sessões seguidas no mesmo servidor, como um script de implantação, esse tempo se soma. O ControlMaster permite compartilhar várias sessões numa mesma conexão de rede; o ControlPath define onde fica o socket de controle, que deve ficar numa pasta em que outros usuários não possam gravar; e o ControlPersist mantém a conexão principal aberta em segundo plano depois que a primeira sessão termina [12].
O ritmo da digitação
Uma sessão interativa tem um vazamento discreto: cada tecla digitada gera um pacote, e o intervalo entre os pacotes, visível para quem observa a rede mesmo com tudo cifrado, revela o ritmo da digitação, o que em tese ajuda a adivinhar o que foi digitado. A versão 9.5 do OpenSSH acrescentou ao cliente uma ofuscação do tempo das teclas, controlada pela opção ObscureKeystrokeTiming [5]. Ela é, aliás, uma das proteções que o ataque Terrapin conseguia desligar, como mostra a seção sobre as falhas recentes [13].
Sair de uma sessão travada
Uma sessão que trava por uma queda de rede pode ser encerrada com a sequência de escape ~., digitada no começo de uma linha [7]. É um detalhe que poupa muitos terminais fechados à força.
A transferência de arquivos
O SSH tem dois jeitos clássicos de copiar arquivos: o scp, herdeiro do antigo rcp, e o sftp, que roda como um subsistema dentro de uma sessão. Na versão 9.0, o OpenSSH mudou o scp para usar o protocolo SFTP por padrão, em vez do protocolo legado scp/rcp [5]. O comando continua o mesmo para quem usa, mas por baixo deixa de depender de um protocolo antigo, que tinha problemas conhecidos de interpretação de nomes de arquivo.
O SSH no Git e no GitHub
Para muita gente, o primeiro contato com chaves SSH não é um servidor, e sim um repositório Git. O mecanismo é o mesmo: o serviço de hospedagem guarda a chave pública, e o cliente prova a posse da chave privada.
Autenticar no repositório
Ao clonar um repositório pelo endereço SSH, como git@github.com:empresa/projeto.git, o Git chama o ssh, que se autentica com a chave da pessoa e pede ao servidor o acesso ao repositório. Tudo o que vale para os servidores vale aqui: a conferência da chave de host na primeira conexão, as chaves Ed25519, a frase-senha e o agente.
Assinar commits com a mesma chave
A mesma chave pode servir para outra coisa: assinar os commits. O GitHub aceita commits e tags assinados com chaves SSH, além do GPG e do S/MIME, e marca como "Verified" os que têm uma assinatura verificável [19]. Para isso, a chave precisa ser cadastrada na conta como chave de assinatura, e, se ela já for usada para autenticação, pode ser cadastrada de novo para assinatura [19]. A verificação de assinaturas SSH existe a partir do Git 2.34 [19].
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
A assinatura responde a uma pergunta que a autenticação não responde: quem escreveu aquele commit. Qualquer pessoa pode configurar o Git com o nome e o e-mail de outra; só quem tem a chave privada consegue produzir a assinatura. Em repositórios com regras de proteção que exigem commits assinados, isso fecha uma porta de falsificação.
O SSH no Windows
O SSH deixou de ser uma ferramenta só do mundo Unix. O Windows traz o OpenSSH como um recurso opcional, mantido e atualizado pela Microsoft pelo Windows Update, a partir do Windows 10, versão 1809, e do Windows Server 2019 [20]. A partir do Windows Server 2025, o OpenSSH vem instalado por padrão, e o serviço sshd pode ser ligado ou desligado pelo Gerenciador do Servidor [20].
Nas versões anteriores, a instalação é feita pelos recursos opcionais ou pelo PowerShell, com o Add-WindowsCapability, e a instalação do servidor cria uma regra de firewall que libera a porta 22 [20]. Para limitar quem pode entrar por SSH no Windows Server 2025, a documentação indica o grupo de usuários "OpenSSH Users" [20]. A Microsoft mantém também uma bifurcação própria do projeto, cujas versões podem diferir da que vem no Windows [20].
Para quem administra um ambiente misto, isso significa que o mesmo cliente, as mesmas chaves e os mesmos certificados podem servir para os servidores Linux e Windows, o que simplifica bastante a gestão de acessos.
O servidor: o OpenSSH na prática
A configuração de referência
As recomendações da Mozilla para o servidor, no perfil "moderno", são uma boa referência [10]:
- chaves de host, com o Ed25519 primeiro na lista;
- algoritmos, com o curve25519 na troca de chaves e o ChaCha20-Poly1305 ou o AES-GCM na cifra, preferindo as variantes que cifram antes de autenticar;
- **
AuthenticationMethods publickey**, para aceitar só login por chave; - **
PermitRootLogin no**, para que os administradores entrem com usuários comuns e usemsudo, deixando cada ação atribuível a uma pessoa; - **
LogLevel VERBOSE**, que registra a impressão digital da chave usada em cada login, criando uma trilha de auditoria.
# trecho de /etc/ssh/sshd_config
HostKey /etc/ssh/ssh_host_ed25519_key
AuthenticationMethods publickey
PermitRootLogin no
LogLevel VERBOSE
Senhas e segundo fator
O segundo fator de autenticação é recomendado onde for possível, mas tem uma armadilha que a Mozilla destaca: os códigos de uso único exigem a autenticação interativa por teclado, que pode permitir login por senha, e por isso o PasswordAuthentication no não basta; é preciso configurar também o PAM para bloquear a autenticação por senha do sshd [10]. As contas de máquina não conseguem completar o segundo fator, e a recomendação é permitir que elas entrem só a partir de faixas de endereços privados, protegidas por outra camada, como uma VPN, num bloco Match User que exija chave pública [10].
O rodízio das chaves de host
Trocar a chave de host de um servidor costuma ser adiado por um motivo prático: todos os clientes vão ver o aviso de chave trocada. O OpenSSH tem um mecanismo para suavizar isso. Depois da autenticação, o servidor pode anunciar chaves de host adicionais, e a opção UpdateHostKeys do cliente controla se ele as aceita e as acrescenta ao known_hosts, com os valores sim, não ou perguntar [12]. Com isso, um servidor pode passar a anunciar uma chave Ed25519 nova ao lado da antiga, os clientes vão aprendendo a nova nas conexões normais, e a antiga pode ser retirada depois, sem uma onda de avisos.
A Mozilla lembra o outro lado da questão: quando um servidor passa a oferecer um tipo de chave diferente do que está no known_hosts, como uma Ed25519 onde havia uma RSA, o cliente pode mostrar o aviso de chave trocada, e a chave nova deve ser conferida antes da conexão [10].
A porta 22
O SSH escuta, por padrão, na porta 22, e é ela que a instalação do servidor no Windows libera no firewall [20]. Um servidor com a porta 22 aberta para a internet recebe tentativas automáticas de login o tempo todo, e as defesas que vimos, como o PerSourcePenalties, o MaxStartups e a autenticação só por chave, existem justamente para isso [15].
Mudar a porta para outro número reduz o ruído nos registros, porque muitos robôs só tentam a 22, mas não acrescenta segurança de verdade: uma varredura encontra a porta nova em segundos. As medidas que protegem são as outras: aceitar só chaves, limitar quem pode entrar, manter o OpenSSH atualizado e, quando possível, não expor o SSH à internet, deixando-o acessível só por uma VPN ou por um servidor de salto.
Penalidades por origem
A versão 9.8 do OpenSSH acrescentou a opção PerSourcePenalties, ligada por padrão [5]. Ela penaliza as origens que derrubam o sshd, que falham na autenticação, que se desconectam sem tentar autenticar ou que estouram o LoginGraceTime, e recusa conexões daquela faixa de endereços por um tempo [15]. As penalidades padrão vão de 1 segundo, para quem se desconecta sem tentar, a 90 segundos, para quem derruba o servidor; uma falha de autenticação custa 5 segundos [15]. É uma defesa contra as tentativas automáticas de adivinhar senhas, que qualquer servidor SSH exposto na internet recebe o dia inteiro.
Os padrões que vale conhecer
A página de manual do sshd_config traz os valores padrão de cada opção, e alguns surpreendem [15]:
- **
PermitRootLogin** tem o padrãoprohibit-password: o root pode entrar por chave, mas não por senha nem por autenticação interativa; - **
PasswordAuthentication** e **KbdInteractiveAuthentication** vêm ligadas por padrão, ou seja, um servidor recém-instalado aceita senhas, a menos que a distribuição mude isso; - **
MaxAuthTries** permite 6 tentativas de autenticação por conexão, e as falhas passam a ser registradas quando chegam à metade disso; - **
MaxStartups**, com o padrão10:30:100, controla as conexões que ainda não se autenticaram: acima de 10, as novas passam a ser recusadas ao acaso, com probabilidade crescente, e acima de 100, todas; - **
LoginGraceTime** dá 120 segundos para o cliente se autenticar; - **
ClientAliveInterval** vem em zero, sem mensagens de manutenção; com oClientAliveCountMax, de 3 por padrão, um intervalo de 15 segundos derruba os clientes sem resposta em cerca de 45 segundos.
As opções AllowUsers e AllowGroups não têm restrição por padrão; quando definidas, só os usuários ou grupos da lista podem entrar, e as regras de negação têm precedência sobre elas [15]. Num servidor com muitos usuários de sistema, uma lista curta de quem pode entrar por SSH é uma das proteções mais simples e eficazes.
SSH em automações
Scripts de implantação, rotinas de backup e ferramentas de integração contínua usam o SSH tanto quanto as pessoas, e as recomendações para elas são um pouco diferentes.
Uma chave por automação
A recomendação da Mozilla para as chaves de máquina vale aqui: chaves únicas por uso, com privilégios mínimos, registradas num inventário, e longe de contas de root ou com sudo [10]. Na prática, a rotina de backup tem a sua chave, a implantação tem a dela, e cada uma só faz o que precisa, com as opções do authorized_keys: o restrict, um command forçado e um from com o endereço de origem [16].
Fixar a chave do servidor
Automações não respondem à pergunta da primeira conexão, e a tentação é desligar a conferência com StrictHostKeyChecking no. É exatamente o que a RFC descreve como vulnerável a um intermediário [2]. O caminho certo é gravar de antemão a chave do servidor no known_hosts da automação, conferida por um canal confiável, ou usar certificados de host com a marcação @cert-authority [16]. Assim a automação recusa um servidor falso, em vez de entregar a ele os arquivos.
Conexões reaproveitadas
Uma implantação que roda vinte comandos no mesmo servidor faz vinte trocas de chaves e vinte autenticações, a menos que reaproveite a conexão com o ControlMaster e o ControlPersist [12]. O ganho é grande em scripts com muitos passos, e o socket de controle deve ficar numa pasta só da conta da automação [12].
Mantenha a sessão viva, mas não para sempre
Do lado do servidor, o ClientAliveInterval e o ClientAliveCountMax derrubam as sessões de clientes que pararam de responder [15], o que evita que conexões de automações interrompidas fiquem penduradas. Do lado do cliente, o ServerAliveInterval faz o mesmo no sentido contrário [12].
Quando a conexão não funciona
Os problemas de SSH costumam se repetir, e o próprio cliente tem as ferramentas para descobri-los.
Ver o que o cliente está fazendo
A opção -v liga as mensagens de diagnóstico sobre o andamento do cliente, úteis para problemas de conexão, de autenticação e de configuração; repetida, aumenta o detalhe, até o máximo de três vezes [7]. Com ela, o cliente mostra a versão que o servidor anunciou, os algoritmos combinados, a chave de host apresentada, as chaves que ele está tentando e a resposta do servidor a cada tentativa.
ssh -vv usuario@servidor
Ver a configuração que vale
Com um ~/.ssh/config cheio de blocos Host e Match, nem sempre é óbvio qual opção está valendo para um servidor. A opção -G faz o cliente imprimir a configuração depois de avaliar os blocos e sair, sem conectar [7]. É a forma mais rápida de descobrir por que o ProxyJump não está sendo usado, ou qual chave o cliente vai oferecer.
ssh -G servidor-interno | grep -E "proxyjump|identityfile|user "
Ver o que o cliente suporta
A opção -Q lista os algoritmos que o cliente suporta para um recurso, como as cifras, os códigos de autenticação das mensagens, as trocas de chaves e os tipos de assinatura [7]. Ela ajuda a entender uma falha de negociação com um servidor antigo: se o servidor só oferece algoritmos que o cliente não tem mais, a conexão falha antes da autenticação.
ssh -Q kex
Os sintomas mais comuns
Com essas ferramentas, a maior parte dos problemas tem diagnóstico rápido:
- "Permission denied (publickey)": o servidor não aceitou nenhuma das chaves oferecidas; o
-vmostra quais foram tentadas, e o motivo costuma ser a chave errada, a falta doIdentitiesOnlyou permissões erradas noauthorized_keysdo servidor; - "Too many authentication failures": o agente ofereceu chaves demais antes da certa e estourou o
MaxAuthTriesdo servidor, de 6 por padrão; oIdentitiesOnlyresolve [12][15]; - "No matching key exchange method found": cliente e servidor não têm um algoritmo em comum, típico de servidores muito antigos; o
-Qe o-vmostram o que cada um oferece; - "REMOTE HOST IDENTIFICATION HAS CHANGED": a chave de host mudou; descubra o motivo antes de aceitar a chave nova [7];
- conexão que cai depois de um tempo parada: um firewall no caminho derruba as conexões ociosas; o
ServerAliveIntervalmantém a conexão viva [12].
Túneis sem terminal
Para quem usa o SSH só para encaminhar portas, duas opções completam o quadro: o -N não executa nenhum comando remoto, o que é útil quando só se quer o encaminhamento, e o -f manda o cliente para o segundo plano logo antes de executar o comando, depois de pedir a senha ou a frase-senha, se for preciso [7]. O -T desliga a alocação de terminal, útil para comandos não interativos [7].
# um túnel para o banco, em segundo plano, sem terminal
ssh -f -N -L 5433:localhost:5432 usuario@servidor
As falhas que mudaram a configuração
Três incidentes recentes ensinaram muito sobre o SSH, e cada um deixou uma lição diferente.

Terrapin: uma falha no protocolo
O Terrapin é um ataque de truncamento de prefixo contra o protocolo SSH: manipulando os números de sequência durante o aperto de mão, um atacante consegue remover em silêncio mensagens do início do canal seguro [13]. As conexões vulneráveis eram as que usavam o ChaCha20-Poly1305 ou cifras em modo CBC com autenticação depois da cifra, e o ataque exigia uma posição de intermediário na rede [13]. O impacto principal era remover a mensagem de negociação de extensões, o que permitia rebaixar a segurança da autenticação por chave RSA do cliente e, com o OpenSSH 9.5, desligar a proteção contra ataques de tempo de digitação [13].
O ataque foi publicado em 18 de dezembro de 2023 por Fabian Bäumer, Marcus Brinkmann e Jörg Schwenk, da Universidade do Ruhr em Bochum, e recebeu o identificador CVE-2023-48795 [13]. A contramedida é a troca de chaves estrita, o "strict kex", acrescentada no OpenSSH 9.6, lançado no mesmo dia [5][13]. Ela só funciona quando o cliente e o servidor a suportam [13], e por isso atualizar os dois lados é o que resolve.
A lição: até um protocolo padronizado há quase vinte anos e analisado por muita gente pode ter falhas de projeto. Manter cliente e servidor atualizados não é opcional.
regreSSHion: uma falha no código
Em 1º de julho de 2024, a Qualys publicou o regreSSHion, o CVE-2024-6387, uma condição de corrida no servidor do OpenSSH [9]. Se um cliente não se autentica dentro do LoginGraceTime, de 120 segundos por padrão, o tratador de alarme do sshd roda de forma assíncrona e chama funções que não são seguras naquele momento, como a de registro em log; em sistemas Linux com a glibc, isso podia permitir a execução remota de código como root, sem autenticação [9]. O OpenBSD não era afetado [9].
O nome vem da história: a falha era uma regressão de outra, de 2006, que voltou porque uma alteração de outubro de 2020, que chegou na versão 8.5p1, removeu uma proteção do código [9]. As versões afetadas iam da 8.5p1 à 9.7, e a correção saiu na 9.8 [5][9]. Como mitigação temporária, colocar o LoginGraceTime em zero impedia a execução de código, mas deixava o servidor vulnerável a negação de serviço, porque um atacante podia ocupar todas as conexões simultâneas permitidas [9].
A lição: código maduro também regride. Testes de regressão para falhas antigas, e atualizações rápidas quando um aviso sai, são parte da segurança do SSH.
O backdoor do xz: uma falha na cadeia de suprimentos
Em 29 de março de 2024, o engenheiro Andres Freund avisou a lista oss-security de que o repositório e os pacotes do xz tinham um backdoor, nas versões 5.6.0 e 5.6.1 da biblioteca liblzma [14]. O xz não tem nada a ver com o SSH, mas chegava a ele por um caminho indireto: algumas distribuições modificam o sshd para avisar o systemd, o que faz o sshd carregar o libsystemd, que depende da liblzma [14]. Freund percebeu o problema por um sintoma pequeno: logins por SSH gastando muito processador e erros do valgrind, numa versão de testes do Debian [14].
A lição: a segurança de um servidor SSH depende também das bibliotecas que ele carrega, inclusive as que ninguém imagina que estejam ali. E, às vezes, quem descobre um ataque sofisticado é alguém que estranhou um login meio segundo mais lento.
Um roteiro para proteger um servidor SSH
As seções anteriores se resumem num roteiro.
- Manter o OpenSSH atualizado, no servidor e nos clientes: o Terrapin e o regreSSHion foram corrigidos por atualizações [5][9][13].
- Aceitar só chaves, com
AuthenticationMethods publickey, e desligar de verdade as senhas, inclusive pelo PAM se houver autenticação interativa [10]. - Proibir o login de root, com
PermitRootLogin no, e usarsudo[10]. - Registrar as impressões digitais das chaves usadas, com
LogLevel VERBOSE[10]. - Usar chaves Ed25519, de preferência em dispositivos físicos para as pessoas, com frase-senha [6][10].
- Separar as chaves de máquina, únicas por uso, com privilégios mínimos e inventariadas [10].
- Conferir as chaves de host, por impressão digital, SSHFP ou certificados de host, em vez de aceitar no escuro [2][7].
- Preferir certificados de validade curta quando houver muitas pessoas e servidores [6].
- **Acessar a rede interna por
ProxyJump**, sem encaminhar o agente [7][10]. - Não publicar serviços internos: usar o encaminhamento local para chegar a eles [7].
- Manter a troca de chaves pós-quântica, sem desligá-la no
KexAlgorithms[4]. - Acompanhar os avisos de segurança do OpenSSH e das bibliotecas do sistema [14].
Erros comuns
- Aceitar a chave de host na primeira conexão sem conferir. A conexão fica exposta a um intermediário [2].
- **Apagar a linha do
known_hostsquando a chave muda.** Primeiro descubra por que mudou [7]. - Deixar a autenticação por senha ligada. Senhas são adivinhadas, vazam e são entregues a servidores falsos [8][10].
- **Achar que
PasswordAuthentication nobasta.** A autenticação interativa pode reabrir a porta; confira o PAM [10]. - Chaves sem frase-senha nos notebooks. Quem copia o arquivo entra no servidor [10].
- A mesma chave para tudo. Separe por propósito [10].
- **Encaminhar o agente com
-Apor hábito.** Use oProxyJump[7][10]. - Expor o banco de dados à internet para acessá-lo de casa. Use o encaminhamento local [7].
- Login direto como root. As ações deixam de ser atribuíveis a uma pessoa [10].
- Chaves DSA ou RSA com SHA-1 em sistemas antigos. O DSA saiu do OpenSSH 10.0; troque por Ed25519 [5][6].
- Desligar a troca de chaves pós-quântica por compatibilidade. O risco de guardar agora e decifrar depois é real [4].
- Ficar numa versão antiga do OpenSSH. As falhas recentes foram corrigidas em versões novas [5].
- **Confiar no padrão do
PasswordAuthentication.** Ele vem ligado; desligue explicitamente [15]. - Chaves de automação com acesso total. Use
restrict,commandefromnoauthorized_keys[16]. - **
StrictHostKeyChecking nonas automações.** Grave a chave do servidor de antemão ou use certificados de host [2][16]. - **Conta de SFTP sem
DisableForwarding.** OForceCommandnão bloqueia os encaminhamentos [15]. - Acesso temporário sem data de fim. Use o
expiry-timeou certificados de validade curta [6][16]. - Chaves no agente para sempre. Defina um tempo de vida com
-t[18]. - Commits sem assinatura num repositório que exige autoria verificável. A mesma chave SSH pode assinar [19].
Conclusão
O SSH nasceu em 1995 para acabar com as senhas trafegando em texto aberto, e a versão 2, padronizada em 2006, organiza o protocolo em três camadas: o transporte, que cifra e autentica o servidor; a autenticação, que identifica o usuário; e a conexão, que divide o túnel em canais [1][2]. A troca de chaves gera um segredo que ninguém na rede consegue calcular, e o OpenSSH já a faz com algoritmos híbridos pós-quânticos por padrão, contra quem grava hoje para decifrar amanhã [3][4].
A segurança de verdade, porém, está em duas conferências que dependem de quem usa. A chave de host garante que o cliente fala com o servidor certo, e aceitá-la no escuro anula a proteção [2]. A chave do usuário prova a identidade sem que a chave privada saia do cliente, e é muito mais forte que a senha [8]. Certificados de validade curta, dispositivos físicos e o ProxyJump levam essas garantias para ambientes com muitas pessoas e servidores [6][7].
Por fim, os incidentes recentes mostram que o SSH falha de três jeitos: no protocolo, como no Terrapin; no código, como no regreSSHion; e na cadeia de suprimentos, como no xz [9][13][14]. A defesa contra os três é a mesma: atualizar, configurar com cuidado e prestar atenção nos sinais estranhos. O SSH é uma das ferramentas mais confiáveis da internet, e continua assim porque muita gente cuida dele.
Para quem administra servidores, o resumo prático cabe em poucas linhas: chaves Ed25519 com frase-senha, de preferência em dispositivos físicos; senhas desligadas de verdade; nada de root direto; chaves de host conferidas ou certificadas; ProxyJump em vez de encaminhar o agente; chaves de automação restritas no authorized_keys; e o OpenSSH sempre atualizado. Com isso, o SSH continua sendo o que foi desde 1995: a forma segura de entrar num computador do outro lado da rede.
Fontes
- Secure Shell — en.wikipedia.org
- RFC 4251: The Secure Shell (SSH) Protocol Architecture — datatracker.ietf.org
- RFC 4253: The Secure Shell (SSH) Transport Layer Protocol — datatracker.ietf.org
- OpenSSH: Post-Quantum Cryptography — openssh.org
- OpenSSH Release Notes — openssh.org
- ssh-keygen(1) — man.openbsd.org
- ssh(1) — man.openbsd.org
- RFC 4252: The Secure Shell (SSH) Authentication Protocol — datatracker.ietf.org
- regreSSHion: RCE in OpenSSH's server, on glibc-based Linux systems (CVE-2024-6387) — qualys.com
- OpenSSH Security Guidelines — infosec.mozilla.org
- RFC 4254: The Secure Shell (SSH) Connection Protocol — datatracker.ietf.org
- ssh_config(5) — man.openbsd.org
- Terrapin Attack — terrapin-attack.com
- backdoor in upstream xz/liblzma leading to ssh server compromise — openwall.com
- sshd_config(5) — man.openbsd.org
- sshd(8) — man.openbsd.org
- RFC 8332: Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell (SSH) Protocol — datatracker.ietf.org
- ssh-agent(1) — man.openbsd.org
- About commit signature verification — docs.github.com
- Get started with OpenSSH Server for Windows — learn.microsoft.com
- RFC 8709: Ed25519 and Ed448 Public Key Algorithms for the Secure Shell (SSH) Protocol — datatracker.ietf.org
- RFC 4255: Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints — datatracker.ietf.org
Este post foi escrito com a ajuda da Juniper, a assistente de IA da Gothor, e revisado pela nossa equipe antes de ir ao ar.


