Sua rotação de chaves de host SSH está pronta?
Planeje a rotação de chaves de host SSH com chaves sobrepostas, fingerprints publicados, janela controlada e testes de revogação.

Uma chave de host SSH deve mudar no seu cronograma, quando a substituta já é confiável. Se os desenvolvedores descobrem a rotação pelo aviso vermelho no terminal, o plano já falhou. O aviso não diz se o servidor mudou legitimamente ou se alguém interceptou a conexão. Uma mensagem apressada pedindo que todos apaguem uma linha de known_hosts destrói a evidência necessária para decidir.
Uma rotação segura tem quatro ações distintas: publicar os fingerprints antigo e novo por um canal confiável, disponibilizar as duas chaves por tempo suficiente para os clientes aprenderem a nova, remover a antiga numa janela definida e provar que os clientes rejeitam a identidade aposentada. Já vi equipes acertarem o trabalho do servidor e ainda ensinarem aos desenvolvedores o pior hábito: tratar a verificação do host como obstáculo. O trabalho operacional é tornar o caminho seguro comum antes do aviso.
Identidade do host não é autenticação do usuário
A chave de host prova qual servidor SSH respondeu; a chave de usuário prova quem pede login. Girar uma não gira a outra. A distinção parece básica, mas manuais de incidentes misturam authorized_keys, chaves pessoais, certificados de host e arquivos /etc/ssh/ssh_host_* numa instrução vaga para "girar chaves SSH".
A RFC 4253 coloca a autenticação do servidor no handshake de transporte. O servidor assina o hash da troca com sua chave privada de host, e o cliente compara a pública com uma fonte confiável, como known_hosts, uma autoridade certificadora de hosts ou registros SSHFP autenticados. Senhas, certificados e chaves de usuário vêm depois. Se o cliente deixa de verificar o servidor, um desenvolvedor pode entregar credenciais válidas a um impostor.
Por isso o alerta de host alterado é severo de propósito. Ele marca uma quebra de continuidade: o nome digitado agora apresenta outra identidade. Substituição planejada, máquina virtual reconstruída, balanceador apontando para o pool errado, DNS adulterado e interceptação ativa podem parecer iguais naquele momento. O cliente não vê seu chamado de mudança.
Escreva o escopo antes de gerar qualquer coisa. Registre cada hostname e alias, porta fora do padrão, endereço escrito em scripts, rota por bastion, runner de CI, agente de deploy e GlobalKnownHostsFile compartilhado. [host]:port é diferente de host, e aliases escondem o destino canônico. Cobrir git.example.net e esquecer git.internal produzirá uma falha aparentemente intermitente, mesmo que ambos cheguem à mesma máquina.
Inventarie também todos os algoritmos oferecidos. Um servidor pode ter chaves Ed25519, ECDSA e RSA ao mesmo tempo. O OpenSSH negocia com o cliente, então dois desenvolvedores podem fixar públicas diferentes para o mesmo daemon. Trocar apenas a chave vista no seu notebook não define o conjunto completo de identidade. Use as entradas HostKey e os arquivos públicos verificados como inventário oficial e compare com o que cada grupo de clientes negocia.
Publique os dois fingerprints antes de mudar o servidor
Publique o atual e o substituto enquanto a chave atual ainda atende o tráfego. A publicação deve passar por um canal cuja confiança não dependa do host em mudança. Um repositório operacional assinado, uma página interna autenticada, configuração gerenciada de dispositivos ou zona DNSSEC administrada à parte funcionam. Uma mensagem copiada da mesma sessão SSH possivelmente interceptada não funciona.
Gere fingerprints a partir dos arquivos públicos numa máquina administrativa confiável, não perguntando à rede de produção o que ela serve. O OpenSSH mostra SHA-256 por padrão. O comando e o formato de saída são:
$ ssh-keygen -lf ssh_host_ed25519_key.pub -E sha256
256 SHA256:<base64-fingerprint> host.example.net (ED25519)
Publique mais que o resumo curto. Para cada identidade, inclua hostname e porta, algoritmo, fingerprint SHA-256, estado (current, new ou retired), início de uso, aposentadoria e quem aprovou. Indique o fuso horário. Liste aliases que compartilham a chave. Se nós atrás do mesmo nome apresentam chaves diferentes de propósito, publique todo o conjunto permitido e explique o motivo.
Um registro útil se parece com este:
Host: build.example.net:22
Algorithm: ssh-ed25519
Current: SHA256:<old-fingerprint>
New: SHA256:<new-fingerprint>
Overlap begins: 2026-08-10 15:00 UTC
Old key removed: 2026-08-17 15:00 UTC
Old key marked revoked: 2026-08-17 15:30 UTC
Owner: Platform operations
As datas são ilustrativas, a ordem não. Publicar depois da mudança transforma trabalho planejado numa decisão improvisada de confiança. Publicar só o valor novo impede a comparação com um pin existente. Mantenha o registro antigo visível como aposentado para investigadores reconhecerem máquinas desatualizadas e reutilização inesperada.
Fingerprints são identificadores públicos, não segredos. A privada fica protegida no servidor, mas distribua a pública e o fingerprint o suficiente para a verificação não depender de achar um administrador durante a janela. Trate a aprovação como mudança de segurança: dois arquivos de origem produzindo o mesmo fingerprint são mais fortes que uma captura colada no chat.
A sobreposição ensina a substituta com segurança
Sirva as chaves antiga e nova juntas antes de remover a antiga. Durante a sobreposição, um cliente estabelecido autentica o servidor com a antiga confiável e aprende a adicional pela extensão [email protected]. A continuidade vem da antiga, portanto a nova não chega como afirmação sem autenticação.
O manual ssh_config descreve UpdateHostKeys como suporte à rotação gradual e lista limites importantes. O cliente só aceita chaves adicionais depois de se autenticar com uma chave simples já confiável ou aceita explicitamente, usando o arquivo do usuário. Isso não ocorre quando um certificado de host fez a autenticação nem quando só o arquivo global foi usado. O padrão também pode ser desativado se o usuário substituir UserKnownHostsFile ou ativar VerifyHostKeyDNS.
Não presuma o padrão. Inspecione a configuração efetiva:
$ ssh -G build.example.net | grep -E '^(updatehostkeys|userknownhostsfile|stricthostkeychecking) '
stricthostkeychecking ask
updatehostkeys true
userknownhostsfile ~/.ssh/known_hosts ~/.ssh/known_hosts2
No servidor, mantenha arquivos privados separados e declare ambos. Estes nomes são exemplos:
HostKey /etc/ssh/ssh_host_ed25519_key_old
HostKey /etc/ssh/ssh_host_ed25519_key_new
Rode sshd -t antes do reload. Segundo o manual, esse modo verifica configuração e sanidade das chaves, encontrando arquivo ilegível ou ajuste inválido antes da releitura. Recarregue em vez de encerrar sessões, salvo instrução diferente do gerenciador. Depois conecte um cliente limpo que só confia na antiga e examine seu arquivo isolado após uma sessão autenticada.
Várias chaves configuradas não garantem que todos negociem a mesma. Preferência de algoritmo, idade do cliente, HostKeyAlgorithms personalizado, certificados e stores globais influenciam. Mantenha a sobreposição por ao menos um ciclo normal de cada classe, não por um número arbitrário de horas. Notebooks semanais e workers de CI que conectam a cada minuto precisam de janelas diferentes.
Meça a adoção sem fingir que vê todo known_hosts pessoal. Clientes gerenciados podem informar se a nova pública está no arquivo distribuído. Nos demais, acompanhe conexões por versão se a política permitir, publique um comando de verificação e mantenha a sobreposição durante o uso comum. Silêncio não prova propagação.
A janela precisa de estados e condições de parada
Uma janela deve definir estados observáveis, responsáveis e condições de retorno. "Girar às 15h" não diz nada sobre sobreposição, preparo ou quando a identidade antiga se torna proibida. Coloque a transição de confiança na mesma linha do tempo do deploy.
Use cinco pontos:
- Publicação concluída: revisores independentes reproduzem todos os fingerprints a partir dos arquivos aprovados.
- Sobreposição ativa: o servidor oferece as duas identidades, passa em
sshd -t, e clientes limpos autenticam pela antiga enquanto aprendem a nova. - Preparo atingido: stores gerenciados contêm a substituta, testes cobrem sistemas e rotas, e o suporte tem os fingerprints exatos.
- Corte concluído: o servidor não oferece mais a privada antiga, novas sessões funcionam com verificação estrita e nenhum nó inesperado ainda a apresenta.
- Revogação provada: um endpoint de teste com a identidade antiga é rejeitado, e o fingerprint aposentado permanece publicado como revogado.
Dê a uma pessoa autoridade para parar. Pare se um nó apresentar chave não publicada, se uma rota alcançar nó fora do inventário, se um cliente suportado não receber a substituta ou se voltar exigir uma chave considerada comprometida. Uma rotação rotineira pode voltar durante a sobreposição; uma resposta a comprometimento não pode tratar a chave comprometida como segura.
Separe rollback do serviço e da confiança. Você pode restaurar um pacote anterior sem recuperar a identidade aposentada. Mantenha configuração conhecida, acesso à nova privada e console ou provedor disponíveis. Se SSH for a única forma de consertar SSH, há um ponto único de falha escondido.
Inclua sessões multiplexadas longas. Um master OpenSSH pode permanecer ativo enquanto novos shells reutilizam o transporte; eles não verificam a identidade pós-corte. Feche masters de teste com ssh -O exit host quando aplicável e exija novas conexões TCP das sondas.
Marque a aposentadoria com precisão e mantenha a comunicação aberta depois. Quem volta de férias terá pins antigos. O resultado esperado é uma falha documentada e um caminho verificado, não uma exceção. O suporte deve comparar fingerprints, localizar a entrada com ssh-keygen -F e substituí-la pelo registro aprovado.
Ensaie o aviso com um arquivo de confiança isolado
Teste sem tocar no ~/.ssh/known_hosts real de ninguém. Um arquivo isolado torna cada estado reproduzível e evita sucesso baseado em chaves aprendidas meses atrás. Use um endpoint de staging que reproduza a sequência ou um sshd temporário em outra porta sob as mesmas restrições.
Crie known_hosts.test pela pública antiga aprovada, não por scan ao vivo. Conecte fixando o nome lógico com HostKeyAlias:
$ ssh -F /dev/null \
-o HostKeyAlias=build.example.net \
-o UserKnownHostsFile=./known_hosts.test \
-o GlobalKnownHostsFile=/dev/null \
-o StrictHostKeyChecking=yes \
-o UpdateHostKeys=yes \
-p 2222 test-host.example.net true
A primeira execução deve funcionar com as duas chaves. Inspecione com ssh-keygen -F build.example.net -f ./known_hosts.test, confirme a substituta e compare cada fingerprint com a publicação. Status zero prova conectividade, não o conjunto de identidades.
Depois sirva apenas a nova e abra uma conexão nova. Ela deve funcionar graças à aprendizagem autenticada. Restaure uma cópia contendo só o pin antigo e repita: com StrictHostKeyChecking=yes, deve falhar. Esse caso negativo prova que clientes que perderam a sobreposição param em vez de aceitar silenciosamente.
Por fim, apresente uma chave sem relação. Guarde texto e status da falha para o manual. Não enfraqueça o teste para fazê-lo passar; a rejeição é o comportamento protegido. Confirme que scripts propagam o status diferente de zero em vez de escondê-lo em retries.
Nunca use StrictHostKeyChecking=no como correção. O manual atual diz que ele permite algumas chaves alteradas, enquanto accept-new ainda as rejeita. Este também não resolve a rotação de um nome conhecido. Forneça confiança autenticada ou use a sobreposição.
Revogação deve causar rejeição, não sugerir limpeza
Remover a privada antiga do servidor pretendido só prova que esse servidor parou de oferecê-la. Revogar significa que clientes recusam sua pública se reaparecer num nó esquecido ou com um invasor. Apagar a linha de known_hosts faz o contrário: remove a memória da identidade aposentada.
Arquivos OpenSSH aceitam o marcador @revoked. Uma chave correspondente nunca é aceita e gera alerta. Distribua uma entrada global ou arquivo dedicado, usando exatamente a pública aprovada e um escopo consciente:
@revoked build.example.net ssh-ed25519 <old-public-key-data>
Uma Key Revocation List ajuda quando o conjunto cresce ou há certificados. Gere uma KRL de teste e consulte-a:
$ ssh-keygen -k -f revoked-hostkeys.krl ssh_host_ed25519_key_old.pub
$ ssh-keygen -Q -f revoked-hostkeys.krl ssh_host_ed25519_key_old.pub
ssh_host_ed25519_key_old.pub (<comment>): REVOKED
A consulta retorna status diferente de zero para chave revogada; a automação deve interpretá-lo de propósito. Configure RevokedHostKeys, exija rejeição do endpoint antigo e sucesso do novo. Um arquivo inválido ou ilegível pode bloquear todas as conexões.
ssh-keygen -R host edita arquivos com nomes em hash, mas não revoga. Ele remove todas as entradas, inclusive a substituta válida, e deixa a próxima conexão decidir confiança de novo. Use só após comparar e depois adicione a nova chave aprovada. Encadear -R com ssh-keyscan sem autenticação automatiza a entrega da confiança.
Guarde o material público revogado. Você pode destruir uma privada aposentada não comprometida conforme a política, mas mantenha pública, fingerprint, aprovação e resultado do teste. Eles identificam uma imagem antiga que volte meses depois.
A automação deve falhar fechada sem ficar frágil
Jobs não interativos precisam de fonte de confiança mantida, não de verificação desligada. Runners de CI, agentes de deploy e agentes autônomos costumam ver a rotação primeiro porque abrem conexões curtas o dia inteiro. Quando a imagem traz uma chave e ninguém cuida da renovação, o patch comum é StrictHostKeyChecking=no. Ele transforma um erro de disponibilidade em falha de autenticação.
Escolha um modelo por classe: grave ambas as chaves na imagem durante a sobreposição, monte arquivo global gerenciado, retorne linhas aprovadas via KnownHostsCommand, use SSHFP validado por DNSSEC ou confie numa CA de host. O manual diz que o comando complementa os arquivos normais e encerra a conexão se falhar. É o padrão certo, mas o serviço de confiança precisa estar disponível.
Declare o comportamento batch:
Host build.example.net
BatchMode yes
StrictHostKeyChecking yes
UserKnownHostsFile /etc/company/ssh_known_hosts
UpdateHostKeys no
UpdateHostKeys no é intencional aqui. A gestão de configuração é dona do arquivo; deixar cada worker efêmero alterá-lo cria estado perdido e não auditado. Num arquivo persistente do desenvolvedor, yes pode ser melhor. A propriedade da distribuição decide.
Teste aliases, jump hosts, IPs diretos e portas como identidades separadas. ProxyJump ainda autentica o destino, e o salto tem pin próprio. Contêineres e agentes isolados podem usar arquivo read-only, outro binário ou ignorar o diretório do usuário. Rode ssh -G target no ambiente real.
Para SSH operado por agentes, separe credenciais da confiança no host. Sallyport executa ações com sp-ssh enquanto as chaves ficam no vault criptografado, então o agente não recebe os segredos. Isso protege a custódia; a rotação ainda requer fonte de identidade autenticada e rejeição testada.
Uma falha deve indicar fingerprints esperado e observado sem imprimir material privado. Não tente de novo com ajuste mais fraco. Pare o job, guarde stderr e configuração efetiva, e envie ao responsável.
Rode o mesmo teste num worker descartável sem estado de diretório pessoal. Dê exatamente o bundle gerenciado, invoque o job real e arquive ssh -G. Isso encontra falso sucesso causado por sessão interativa que preencheu arquivo não declarado.
Remova a substituta de uma cópia do bundle após o corte para testar falha. O job deve parar antes do comando remoto e preservar o status SSH. Distribua a substituta e repita. Se o framework transformar toda falha SSH em timeout, corrija antes da janela para distinguir identidade rejeitada, rede e usuário.
Procure confiança ampla demais. Um curinga pode validar uma chave para vários nomes; chaves compartilhadas tornam máquinas indistinguíveis. Isso pode ser intencional, mas o registro deve declarar o escopo. Prefira linha específica para identidades distintas e teste o hostname exato do job.
Fixe também o binário SSH e o contrato de configuração dos jobs autônomos. Uma atualização de imagem pode mudar padrões junto com a identidade. Capture versão, algoritmos, hash do arquivo e nome lógico antes e depois para distinguir servidor errado, chave ausente e negociação impossível.
DNS e certificados mudam o trabalho de distribuição
SSHFP e certificados reduzem o gerenciamento por host, mas não eliminam o planejamento. Eles movem a âncora estável. Use-os quando puder operar essa âncora melhor que milhares de entradas independentes.
A RFC 4255 exige DNS autenticado antes de confiar num SSHFP. Na prática, DNSSEC deve validar do cliente até o registro. DNS sem assinatura ajuda a comparar, mas não estabelece identidade contra quem altera respostas. VerifyHostKeyDNS yes só confia implicitamente em correspondências seguras.
Publique os dois registros durante a sobreposição, espere caches e resolvers e remova o antigo junto com a privada. Gere com ssh-keygen -r hostname -f public_key_file a partir de arquivos aprovados. Verifique registro e validação pelo caminho real. TTL curto não conserta DNSSEC quebrado nem valor errado.
Certificados permitem confiar numa entrada como @cert-authority *.example.net. Uma nova chave certificada com principals e validade corretos passa sob a CA existente. É mais simples para frotas dinâmicas, mas a CA tem muito poder. Proteja a privada, limite emissão, registre seriais e principals e ensaie a revogação da CA.
Não implante uma CA só para evitar uma rotação incômoda. Ela adiciona emissão, expiração, nomes e rotação de CA. Uma frota pequena e estável opera pins explícitos; uma grande e efêmera costuma se beneficiar de certificados.
Documente onde a confiança começa. UpdateHostKeys não se aplica após certificado, e arquivo global não aprende adições pelo arquivo do usuário. Misturar modelos sem precedência dá sucesso no notebook e falha na CI.
Encerre com evidências que sobrevivem à janela
Uma rotação concluída prova o que mudou, quem aprovou, o que os clientes aceitaram e se o antigo foi rejeitado. Guarde públicas, fingerprints reproduzidos, resultado de sshd -t, configuração efetiva, revisão publicada, matriz de clientes, horários, artefato de revogação e teste negativo. Nunca ponha a privada no ticket.
Registre o estado real depois da janela. Consulte cada nó por cada rota e compare ao conjunto aprovado, lembrando que coleta de rede é observação, não fonte própria de confiança. Compare com a publicação autenticada. Confira imagens de autoscaling e nós desligados; chaves antigas costumam voltar com capacidade substituta.
Activity journal e Sessions journal do Sallyport podem guardar registro resistente a adulteração das ações SSH de um agente, projetado de um log criptografado encadeado por hashes. sp audit verify verifica a cadeia offline sobre o texto cifrado sem chave do vault, adicionando evidência sem substituir os testes de host.
Marque acompanhamento conforme o comportamento da frota. Procure clientes falhando pelo fingerprint aposentado, nós inesperados e scripts que ganharam opções de bypass. Remova a sobreposição temporária. Mantenha a revogação enquanto a privada puder sobreviver em backup, imagem ou cópia não autorizada.
O alerta de host deve continuar raro e alarmante. Uma boa rotação não o suprime. Ela organiza a transição cedo para que clientes esperados nunca precisem ignorá-lo e prova que ele ainda bloqueia a identidade aposentada se ela voltar.
FAQ
Com que frequência devo girar chaves de host SSH?
Defina um ciclo conforme a custódia, as imagens e as obrigações; nenhum intervalo universal protege toda frota. Gire imediatamente diante de possível exposição e ensaie a rotina o bastante para conhecer o caminho de emergência.
Posso girar a chave sem desconectar usuários ativos?
Sessões existentes costumam continuar porque o handshake acabou. Recarregue a configuração validada e teste novas conexões TCP, pois sessões e masters multiplexados não verificam a nova identidade.
Por que o SSH diz que a identificação remota mudou?
A identidade guardada não corresponde à chave apresentada. Rotação, interceptação, erro de DNS, infraestrutura reconstruída ou backend inesperado podem gerar o mesmo aviso; verifique o fingerprint separadamente.
É seguro apagar a entrada antiga de known_hosts?
Só depois de compará-la ao fingerprint publicado e instalar a substituta por caminho confiável. Apagar sem verificar remove evidência e faz da próxima conexão uma nova decisão de confiança.
StrictHostKeyChecking accept-new resolve a rotação?
Não. accept-new inclui hosts desconhecidos, mas rejeita chave alterada de identidade já guardada. Use sobreposição autenticada, confiança gerenciada, SSHFP com DNSSEC ou certificados.
Por quanto tempo as chaves devem se sobrepor?
Ao menos por um ciclo normal de cada classe de cliente. Baseie a duração no comportamento observado e marque a aposentadoria, em vez de manter a antiga indefinidamente.
ssh-keyscan pode verificar a nova chave?
Ele informa o que o endpoint apresenta, mas a observação não autentica a si mesma. Compare com fingerprint de arquivo aprovado ou outra fonte independente.
Qual a diferença entre remover e revogar?
Remover impede o servidor pretendido de oferecer a privada antiga. Revogar faz clientes recusarem a pública onde quer que reapareça; teste os dois comportamentos.
A CI deve usar UpdateHostKeys?
Só quando o worker possui arquivo persistente do usuário e preserva o estado aprendido. Workers efêmeros costumam funcionar melhor com arquivo central read-only contendo ambas as chaves na sobreposição.
Certificados eliminam a rotação de chaves?
Eles reduzem atualizações por host ao mover confiança para uma CA, mas servidores ainda precisam de novas chaves e certificados. Também será preciso proteger, emitir, expirar, revogar e por fim girar a CA.