8 min de leitura

Verificação de hosts SSH para agentes que acessam a produção

Verificação de hosts SSH para agentes autônomos de programação: fixe fingerprints, restrinja contas remotas e revise comandos antes que os danos se espalhem.

Verificação de hosts SSH para agentes que acessam a produção

Um agente autônomo de programação nunca deve decidir sozinho que um novo servidor SSH é confiável. Ele pode inspecionar um repositório, preparar uma implantação e solicitar acesso, mas deve parar quando a identidade remota não corresponder a um registro estabelecido por uma pessoa ou por um processo confiável de provisionamento.

O SSH apresenta duas perguntas de segurança separadas: «Cheguei ao servidor pretendido?» e «O que essa conta pode fazer nesse servidor?». As equipes costumam misturar as duas porque ambas usam chaves públicas. Esse erro transforma uma conexão direcionada ao lugar errado em exposição de credenciais e depois transforma uma conta com permissões amplas em um incidente de produção.

O desenho prático é simples: fixe a identidade do host antes que o agente se conecte, dê a cada tarefa do agente uma conta remota com escopo restrito e peça a uma pessoa que revise os comandos cujo efeito não possa ser inferido com segurança. Cada camada limita um tipo diferente de falha. Nenhuma substitui as outras.

A identidade do host deve ser verificada antes da autenticação do usuário

A verificação do host responde se o cliente SSH chegou ao servidor que pretendia alcançar. A autenticação do usuário responde se esse servidor aceita a credencial da conta oferecida pelo cliente. A ordem importa porque o SSH negocia e verifica a chave de host do servidor antes de o cliente enviar os dados de autenticação do usuário.

Uma chave de host pertence ao servidor, não ao administrador nem ao agente. O fingerprint é uma representação curta dessa chave pública de host, normalmente exibida no formato SHA256. Se deploy.example.internal normalmente apresentar um fingerprint e de repente apresentar outro, o cliente terá evidência de que algo mudou. Pode ser uma reconstrução legítima. Também pode ser um erro de DNS, um endereço reutilizado, um erro no bastion ou uma tentativa ativa de interceptação.

Considere um agente de programação instruído a executar uma migração em db-prod.internal. A configuração SSH resolve esse nome para um endereço. Um invasor que consiga influenciar o DNS, uma rota de proxy ou uma entrada antiga do inventário pode direcionar a conexão para um servidor sob seu controle. Se o cliente aceitar a chave de host desconhecida, esse servidor poderá solicitar a autenticação do usuário. Uma chave privada SSH no lado do cliente talvez não deixe o cliente, mas o acesso do agente costuma incluir senhas, fluxos de assinatura de certificados, encaminhamento ou comandos que revelam informações úteis depois do login. Mais importante, o agente agora pode executar o comando pretendido na máquina errada.

Um fingerprint de host fixado faz a conexão falhar antes que o agente possa tratar a máquina como seu alvo. Por isso, um host desconhecido ou alterado é um limite de autorização, não um aviso secundário que deve ser suprimido.

A verificação do host não confirma que uma máquina está saudável, configurada corretamente ou segura para alterações. Ela confirma apenas a continuidade da identidade criptográfica. Essa limitação é útil. Não peça a um fingerprint de host que decida se rm -rf, uma migração de esquema ou uma alteração no firewall faz sentido.

Confiar na primeira utilização não é adequado para trabalho sem supervisão

Confiar na primeira utilização pode ser aceitável para um desenvolvedor que se conecta manualmente a uma máquina pessoal descartável. É um padrão ruim para um processo autônomo, porque a primeira conexão é exatamente o momento em que alguém precisa decidir se o hostname, a rota e o fingerprint correspondem entre si.

O OpenSSH documenta essa escolha no manual ssh_config, na opção StrictHostKeyChecking. Com yes, o cliente nunca adiciona automaticamente chaves de host desconhecidas e recusa uma chave alterada. Com accept-new, ele registra automaticamente uma chave desconhecida, mas ainda recusa uma chave alterada. Com no ou off, aceita mais situações que merecem a atenção de um operador.

accept-new costuma ser vendido como um meio-termo sensato. Ele reduz a instabilidade quando os hosts são criados com frequência. Também concede a uma rota de rede o direito de estabelecer o registro de identidade inicial. Para um agente que pode alterar a infraestrutura, essa é a parte errada tomando a decisão.

Use StrictHostKeyChecking=yes para endpoints de produção e staging operados por agentes. Quando uma conexão falhar porque o host é desconhecido, encaminhe a solicitação do agente a uma pessoa que possa comparar o fingerprint informado com uma fonte externa à conexão SSH. Um console de nuvem, um registro de inventário assinado, um console físico ou um canal de gerenciamento já existente pode fornecer essa comparação.

Não resolva a interrupção colocando StrictHostKeyChecking=no em um arquivo de configuração global. Essa linha costuma sobreviver ao incidente temporário que a justificou e depois se aplica silenciosamente a hosts que ninguém pretendia deixar menos protegidos.

Há uma exceção mais restrita: infraestrutura de teste de curta duração cujas identidades de host vêm de um sistema de provisionamento capaz de publicar uma lista de hosts autenticada antes do início do teste. Ainda assim, o agente não deve aprender a identidade do host a partir do próprio primeiro contato pela rede. A fonte de confiança mudou, mas não desapareceu.

Um fingerprint só é útil quando sua fonte é independente

Um fingerprint copiado do endpoint que você está tentando verificar quase não prova nada. ssh-keyscan é conveniente para coletar chaves públicas de host, e essa conveniência cria uma armadilha conhecida: um operador executa o comando contra um hostname, cola o resultado em known_hosts e considera o host verificado. Se o DNS ou o roteamento já apontar para um invasor, ele terá fixado a chave do invasor.

Use ssh-keyscan como comando de coleta depois de obter um fingerprint independente, não como fonte de confiança. Por exemplo, um administrador pode obter um fingerprint da chave de host em um console do provedor ou em um registro de build assinado e depois compará-lo com a chave coletada.

ssh-keyscan -t ed25519 app-prod.internal > /tmp/app-prod.hostkey
ssh-keygen -lf /tmp/app-prod.hostkey -E sha256

O segundo comando exibe uma saída neste formato:

256 SHA256:exampleFingerprintMaterial app-prod.internal (ED25519)

Compare o valor SHA256: caractere por caractere com o valor obtido de forma independente. Verifique também o algoritmo. Se o registro disser ED25519 e o resultado coletado for RSA, pare e investigue, em vez de tratar os dois resultados como equivalentes.

Depois, fixe a chave pública, não apenas uma anotação que contenha seu fingerprint. Um arquivo dedicado mantém os alvos do agente separados do acúmulo pessoal de máquinas antigas de um desenvolvedor:

app-prod.internal ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExamplePublicHostKeyMaterial
[192.0.2.44]:22 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExamplePublicHostKeyMaterial

Inclua o hostname canônico e qualquer forma de endereço que o agente tenha permissão para usar. Caso contrário, um fluxo que use um endereço em um dia e um nome no dia seguinte poderá tomar uma nova decisão de confiança. Mantenha o arquivo sob gerenciamento de configuração controlado, com uma revisão da mudança que identifique o fingerprint antigo e o substituto.

Os registros DNS SSHFP podem ajudar quando a validação de DNSSEC estiver corretamente implementada de ponta a ponta. Eles não salvam uma configuração de agente que aceite respostas DNS comuns e não assinadas como prova. Trate o SSHFP como um canal adicional de publicação verificada, não como um registro decorativo que torna segura a primeira utilização às cegas.

Fixe a rota e o registro do host na configuração SSH

Um agente precisa de uma configuração SSH que elimine ambiguidades, não de uma configuração que herde os hábitos de uma estação de trabalho. Fixe o nome de destino, o arquivo de chaves de host esperado, a conta e o comportamento da conexão em uma entrada explícita.

Host app-production
    HostName app-prod.internal
    User agent_release
    Port 22
    UserKnownHostsFile ~/.ssh/agent_known_hosts
    GlobalKnownHostsFile /dev/null
    StrictHostKeyChecking yes
    UpdateHostKeys no
    PasswordAuthentication no
    KbdInteractiveAuthentication no
    ForwardAgent no
    PermitLocalCommand no

Esse trecho evita vários erros comuns. UserKnownHostsFile impede uma dependência inesperada das entradas de host acumuladas por uma pessoa. GlobalKnownHostsFile /dev/null impede que um arquivo não administrado, válido para toda a máquina, amplie a confiança silenciosamente. UpdateHostKeys no impede que atualizações automáticas de chaves alterem o conjunto fixado durante o trabalho do agente. ForwardAgent no impede que a máquina remota use um agente de autenticação encaminhado para alcançar outro lugar.

O manual ssh_config do OpenSSH explica que UpdateHostKeys permite a rotação de chaves de host quando um host prova que possui uma chave confiável. Esse comportamento pode ser útil para frotas interativas com gerenciamento disciplinado de hosts. Para um agente autônomo, a mutação automática dificulta a análise de incidentes. Uma pessoa deve aprovar uma mudança de identidade em produção e atualizar deliberadamente o arquivo de hosts controlado.

Use um alias estável como app-production na solicitação do agente e reserve endereços brutos para procedimentos de emergência. O alias torna o destino aprovado visível nos logs e evita comandos que alternem entre nomes, endereços temporários e trechos de shell copiados.

Teste a configuração efetiva antes de conceder ao agente qualquer caminho para uma credencial:

ssh -G app-production | grep -E '^(hostname|user|stricthostkeychecking|userknownhostsfile|forwardagent|updatehostkeys) '

Espere valores semelhantes a estes:

hostname app-prod.internal
user agent_release
stricthostkeychecking yes
userknownhostsfile /Users/operator/.ssh/agent_known_hosts
forwardagent no
updatehostkeys no

Isso detecta erros de precedência causados por arquivos Include, padrões definidos pelo usuário e gerenciamento de configuração. Já vi entradas cuidadosas de host serem anuladas por uma regra curinga posterior que alterava o usuário, ativava o encaminhamento ou escolhia outro arquivo de hosts conhecidos. A configuração que realmente será executada é a que você precisa inspecionar.

O escopo da conta limita os danos depois de uma conexão correta

Combine fixação do host com controle de chaves
Fixe o host por conta própria e deixe o Sallyport executar ações SSH aprovadas sem entregar a chave ao agente.

Um host verificado ainda pode receber um comando errado, portanto dê ao agente uma conta com uma função pequena e deliberada. Não entregue a um agente autônomo a mesma conta SSH que um operador usa para toda emergência.

O escopo da conta tem quatro partes: a quais hosts a conta chega, quais arquivos e serviços ela pode afetar, quais caminhos de escalonamento de privilégios possui e por quanto tempo continua utilizável. Uma conta separada torna essas respostas verificáveis. Um login deploy compartilhado transforma cada execução de automação em um problema de atribuição e geralmente termina com permissões amplas, porque cada novo fluxo precisa de mais uma exceção.

Um agente de release em um servidor de aplicações pode precisar ler um diretório de releases, gravar um novo artefato, chamar um único wrapper de implantação e reiniciar um serviço específico. Ele não precisa de um shell com sudo irrestrito, acesso de leitura a todos os diretórios pessoais nem capacidade de alterar a configuração SSH.

Quando a tarefa for restrita, limite a chave pública SSH autorizada com um comando forçado. Em authorized_keys, uma entrada no servidor pode vincular essa credencial a um wrapper:

command="/usr/local/sbin/agent-release-wrapper",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleAgentPublicKey agent-release

O wrapper deve analisar um pequeno conjunto de argumentos, rejeitar metacaracteres de shell, registrar a operação solicitada e chamar binários fixos usando caminhos fixos. Não escreva um wrapper que aceite uma string arbitrária em SSH_ORIGINAL_COMMAND e a entregue a sh -c. Isso apenas esconde o acesso irrestrito ao shell remoto atrás do nome de uma função.

Comandos forçados não servem para toda tarefa de manutenção. Quando um agente realmente precisar de um shell para investigação, use uma conta de investigação distinta, com permissões de leitura e sem escalonamento de privilégios. Crie um caminho separado e revisado explicitamente para alterações. Misturar diagnóstico e mutação em uma única conta ampla dá ao agente espaço demais para transformar uma inferência imperfeita em uma ação irreversível.

Certificados SSH de curta duração podem reduzir o trabalho de limpeza quando você já opera uma autoridade certificadora com controles claros de emissão. Eles não eliminam a necessidade de verificar o host. Um certificado diz algo sobre a conta do cliente; o fingerprint do host diz qual servidor o recebeu.

A revisão do comando deve mostrar o efeito, não uma intenção vaga

Uma aprovação de comando só é útil quando a pessoa vê contexto suficiente para avaliar seu efeito. «Implantar release» é uma intenção. sudo systemctl restart payments-api em app-production como agent_release é uma ação que um revisor pode avaliar.

Revise o alias exato do destino, a conta remota, o comando literal, os argumentos e o diretório de trabalho. Verifique também se o comando chama um shell, expande variáveis, lê um script remoto, baixa conteúdo ou usa sudo. Esses detalhes determinam se uma solicitação aparentemente inofensiva pode alcançar muito além de sua descrição.

Um registro razoável de aprovação para uma ação remota se parece com isto:

Target: app-production (app-prod.internal)
Account: agent_release
Command: /usr/local/sbin/agent-release-wrapper activate 2025.04.17-rc2
Reason: activate the approved release after smoke tests

Compare com esta solicitação:

ssh app-production "curl $URL | sudo sh"

O segundo comando combina obtenção de conteúdo remoto, execução de shell, privilégio elevado e um valor que pode ser expandido de forma diferente do que o revisor espera. Nenhuma configuração de verificação de host torna isso seguro. Rejeite-o e exija um artefato cujo digest tenha sido verificado antes, um programa de implantação fixo e argumentos que identifiquem um release aprovado.

A revisão de comandos também tem um modo próprio de falha: a fadiga de aprovação. Se um agente pedir confirmação para cada cat, git status e verificação de integridade de serviço inofensivos, as pessoas aprenderão a aprovar sem ler. Coloque a investigação somente leitura atrás de uma conta restrita ou de um wrapper de comandos bem definido e reserve as aprovações interativas para ações que gravem, reiniciem, façam rotação, alterem permissões ou atravessem um limite de confiança.

O Sallyport pode manter as credenciais SSH dentro do cofre criptografado e exigir aprovação para cada uso de uma credencial selecionada, enquanto seu canal SSH executa por meio do sp-ssh sem expor a credencial ao agente. Ainda assim, cabe a você fixar o host e decidir se o comando visível merece aprovação.

O caminho perigoso de falha costuma ser uma cadeia de atalhos comuns

Evite o excesso de regras de política SSH
Sua sequência fixa de decisões cobre o bloqueio do cofre, a autorização da sessão e as chaves selecionadas que exigem aprovação a cada uso.

A maioria dos incidentes de SSH relacionados à automação não começa com uma quebra criptográfica exótica. Começa com um atalho que parecia inofensivo durante a configuração.

Imagine um agente de release configurado com StrictHostKeyChecking=accept-new, uma conta de implantação compartilhada e um prompt de aprovação que diz apenas «executar deploy». Um registro DNS aponta brevemente para uma máquina substituta antes que a atualização do inventário seja concluída. O agente vê um host desconhecido, registra sua chave, entra na máquina substituta porque aceita a conta compartilhada e executa o wrapper de implantação. O wrapper tem amplo acesso de gravação porque a conta compartilhada também dá suporte a reparos de emergência.

Nada nessa sequência exige um invasor. Um erro comum de nomenclatura pode implantar artefatos no ambiente errado, expor a saída da implantação a uma máquina não pretendida ou modificar um host que não está preparado. Acrescente um invasor capaz de influenciar a resolução de nomes ou o roteamento e os mesmos atalhos oferecem uma abertura muito mais grave.

Cada controle interrompe um ponto diferente dessa cadeia:

  1. Um registro de host previamente fixado rejeita a máquina substituta até que um operador a verifique.
  2. Uma conta dedicada limita os danos se o alvo aprovado ainda estiver errado de uma forma que a identidade do host não consiga detectar.
  3. Um registro de aprovação contendo o comando completo dá ao revisor a chance de perceber um destino inesperado ou uma ação elevada.
  4. Um registro da sessão e das chamadas permite reconstruir a solicitação, a aprovação, o alvo e o resultado depois de uma falha.

Não substitua o primeiro controle pelos seguintes. Um revisor pode não perceber uma divergência no destino. Uma restrição de conta pode conter um privilégio não identificado. Um log explica os danos depois do fato. Fixar a identidade do host impede uma classe de erros de conexão antes que a conta remota entre em cena.

A rotação da chave de host precisa de um procedimento de mudança, não de um botão de exceção

Mantenha as chaves SSH no Sallyport
O Sallyport executa o SSH por meio do sp-ssh, mantendo as chaves SSH armazenadas no cofre fora do processo do agente.

As chaves de host mudam por motivos legítimos: uma máquina é reconstruída, uma imagem é substituída, um algoritmo é aposentado ou um operador faz a rotação das credenciais depois de uma possível exposição. Trate esses eventos como mudanças planejadas de identidade, com evidências, não como caixas de aviso a serem ignoradas.

A pessoa responsável pelo host deve obter a nova chave pública de host no console da nova máquina ou por outro caminho de gerenciamento autenticado. Ela deve publicar a nova entrada no arquivo de hosts conhecidos controlado, registrar o motivo da mudança e retirar a entrada antiga somente depois que a transição for concluída. Se a máquina precisar manter o serviço durante a transição, o OpenSSH poderá armazenar mais de uma chave de host aceita para o mesmo hostname. Assim, os clientes podem aceitar as identidades antiga e nova durante uma janela definida.

Mantenha o registro da rotação pequeno, mas específico: hostname, endereço quando relevante, fingerprint anterior, fingerprint novo, motivo, verificador e prazo de validade de qualquer período com duas chaves. Um ticket com «SSH alterado» não é suficiente para distinguir um trabalho planejado de alguém ensinando os clientes a confiar em um impostor.

Nunca instrua o agente a executar ssh-keygen -R hostname e reconectar automaticamente. Remover o registro antigo apaga o sinal de divergência antes que alguém estabeleça por que ela ocorreu. Um operador pode usar esse comando depois da verificação como parte de uma atualização revisada, mas ele não deve fazer parte da lógica de recuperação de um fluxo do agente.

Os registros de auditoria devem permitir reconstruir a decisão

Depois que uma ação SSH falhar ou surpreender você, o registro útil responde a quatro perguntas: qual processo do agente a solicitou, qual identidade a aprovou, qual conexão e comando exatos foram usados e qual resultado foi retornado. «O agente implantou o serviço» não responde a nenhuma delas.

Mantenha os registros de sessão separados dos registros de chamadas individuais. Uma sessão identifica a execução do agente e permite que um operador revogue sua permissão quando ele começa a se comportar mal. Um registro de chamada individual captura o alias do host, a conta, o horário, o resultado da aprovação, o comando e a saída ou o erro. A distinção importa quando uma execução do agente faz cem leituras seguras e depois uma gravação insegura.

Proteja os logs contra o agente que gerou a solicitação. Se um agente puder editar o registro depois de um comando remoto, a trilha de auditoria será um diário, não uma evidência. Armazenamento somente para anexação com verificação de integridade é um mínimo prático. Evite também colocar segredos em comandos ou argumentos, porque um bom log de auditoria preservará exatamente aquilo que você pedir que ele preserve.

O Sallyport registra sessões e atividades em um log de auditoria criptografado, encadeado por hash e sem permissão de gravação pelo processo que faz a solicitação; sp audit verify pode verificar a cadeia offline sem uma chave do cofre. Use esse tipo de evidência para investigar uma exceção, mas projete a fixação do host, as restrições da conta e o texto da aprovação antes que um incidente lhe dê um motivo para consultá-la.

A primeira mudança operacional é simples: encontre todas as configurações SSH de agentes que aceitam um host desconhecido, substitua esse comportamento por um arquivo de hosts fixado e dedicado e teste as configurações efetivas com ssh -G. Você encontrará aliases antigos, regras curinga acidentais e contas com muito mais autoridade do que suas funções exigem. Essas são as conexões que vale a pena corrigir antes que o agente fique mais rápido.

FAQ

O que é um fingerprint de host SSH?

Um fingerprint de host SSH identifica a chave pública de host do servidor remoto. Ele permite que o cliente detecte se chegou ao servidor esperado ou a outra máquina que apresenta uma chave de host diferente. Ele não identifica a conta humana ou do agente que faz login.

Uma chave SSH prova que o servidor remoto é seguro?

Não. A verificação do host SSH e a autenticação do usuário resolvem problemas diferentes. Uma credencial de usuário válida ainda pode ser entregue a um invasor se o cliente aceitar o servidor do invasor como o host pretendido.

Qual configuração de StrictHostKeyChecking um agente autônomo deve usar?

StrictHostKeyChecking=yes é o padrão prático mais seguro para um agente autônomo. Ele recusa hosts desconhecidos e chaves de host alteradas, interrompendo a implantação até que uma pessoa verifique a situação. Essa interrupção custa menos do que enviar silenciosamente uma credencial de conta ao endpoint errado.

Posso usar ssh-keyscan para verificar um host de produção?

Não. ssh-keyscan solicita uma chave de host ao endpoint da rede, mas não prova quem controla esse endpoint. Use-o apenas quando puder comparar o resultado com um fingerprint obtido por um canal confiável separado, como um console ou um registro de infraestrutura assinado.

O que devo fazer quando o fingerprint SSH de um servidor muda?

Trate um fingerprint alterado como um incidente até que o responsável pela infraestrutura confirme uma reconstrução planejada do host, uma rotação da chave de host ou uma substituição. Verifique o fingerprint por um caminho independente, atualize o registro fixado deliberadamente e mantenha os valores antigo e novo no registro da mudança.

Por que cada agente de programação deve ter uma conta SSH separada?

Um login compartilhado esconde qual carga de trabalho agiu e costuma acumular privilégios amplos, porque cada usuário precisa de algo diferente. Dê a cada carga de trabalho do agente sua própria conta, restrinja os comandos permitidos quando possível e remova a conta quando a tarefa terminar.

O que devo verificar antes de aprovar o comando SSH de um agente?

Revise o comando remoto literal, seus argumentos, o host de destino, a conta, o diretório de trabalho e qualquer expansão de shell antes de aprovar. Comandos que baixam e executam conteúdo, reescrevem configurações, alteram controles de acesso ou passam por um shell exigem um nível de cuidado maior do que uma verificação de status somente leitura.

A verificação do host impede comandos SSH destrutivos?

Não. A verificação do host confirma a identidade criptográfica do endpoint, mas não que um comando seja sensato ou autorizado. Um host de produção verificado ainda pode receber um comando destrutivo de uma conta com privilégios excessivos.

Como lidar com novos hosts SSH sem confiar na primeira utilização?

Use um certificado de host assinado ou uma fonte de fingerprints administrada de forma independente, se o seu ambiente oferecer suporte a isso. Não transforme a primeira conexão de um agente no evento de aprovação. Um operador deve estabelecer o registro de confiança antes que o agente possa se conectar.

Um gateway de ações pode substituir as restrições da conta SSH?

Mantenha a conta restrita a um repositório, serviço ou tarefa operacional específica e registre a identidade da sessão e cada chamada remota. Um gateway de ações pode manter as credenciais fora do processo do agente, mas não torna segura uma conta remota mal dimensionada.

Sallyport

O Sallyport executa chamadas de API e comandos SSH pelo seu agente de IA. As chaves ficam em um cofre local no seu Mac; você aprova cada execução e toda ação vai para um registro selado.

© 2026 Sallyport · Código aberto sob Apache-2.0 · Oleg Sotnikov