Acesso por bastion host para agentes de IA de programação, do jeito certo
O acesso por bastion host para agentes de IA de programação precisa de rotas impostas, credenciais controladas, evidências dos comandos SSH e registros confiáveis do destino.

Um bastion host pode oferecer aos agentes de IA para programação uma rota mais segura até a infraestrutura privada, mas apenas se você tratá-lo como parte de um limite de acesso. Uma jump box que apenas aparece em um arquivo de configuração SSH não é um controle. O agente pode contorná-la, usar uma credencial emprestada, abrir um túnel ou deixar um registro de auditoria que prova apenas que algo se conectou ao jump host.
Para trabalhos autônomos, o desenho útil é mais rigoroso: o agente chega a um único ponto de entrada controlado, esse ponto alcança apenas destinos conhecidos, as credenciais ficam fora do contexto do agente e seus registros distinguem o host solicitado pelo agente do host que realmente aceitou a conexão. Essa distinção parece excessiva até a primeira análise de incidente. Então ela passa a ser a diferença entre evidência e uma história reconfortante.
Um bastion muda a rota, não a autoridade do agente
Um desenho de acesso por bastion limita o alcance da rede, mas não reduz o que um agente pode fazer depois de chegar a uma conta privilegiada. As equipes costumam confundir essas funções porque ambas envolvem SSH. São controles separados e devem falhar separadamente.
Um jump host ajuda quando os destinos privados aceitam tráfego administrativo apenas desse host ou dessa sub-rede. Ele oferece um único lugar para aplicar limites de saída, coletar evidências de conexão e interromper o acesso durante uma investigação. Também evita que cada estação de trabalho, executor de build e sandbox de agente precise de rotas diretas para redes sensíveis.
Ele não responde a quatro perguntas que se tornam mais importantes com um cliente autônomo:
- O agente consegue alcançar o destino diretamente por outra rota?
- A conta de destino tem permissões mais amplas do que o trabalho solicitado exige?
- O agente consegue criar um túnel que lhe dê um caminho não revisado?
- Depois do fato, você consegue identificar a máquina final e o comando remoto?
Se a resposta à primeira pergunta for sim, o ProxyJump é uma configuração de conveniência, não uma imposição. Se a resposta à segunda for sim, o bastion apenas transferiu para outro ponto a entrada na rede de uma credencial poderosa demais.
Já vi equipes construírem uma jump box cuidadosamente mantida e depois permitirem uma saída SSH ampla de uma sub-rede de CI «para solucionar problemas». Um agente executado nessa sub-rede não precisa de exploração nem de truque inteligente. Ele pode chamar o endereço final diretamente. A arquitetura falhou porque a rede permitia o desvio, não porque o SSH se comportou mal.
Mantenha as funções claras. O ambiente do agente deve se conectar apenas ao host de entrada. O host de entrada deve se conectar apenas às redes e portas de destino previstas. O host final deve autorizar uma conta com finalidade restrita. Cada camada deve produzir registros que respondam a uma pergunta diferente.
O ProxyJump não expõe o comando final
Um jump host SSH normalmente não consegue inspecionar o comando que o agente executa no host final. Esse é o ponto que as equipes esquecem quando prometem «logs completos de comandos a partir do bastion».
O OpenSSH documenta ProxyJump em ssh_config(5) como uma conexão inicial com o jump host seguida da criação de um encaminhamento até o destino final. No uso comum do OpenSSH, o cliente efetivamente pede ao jump host que estabeleça uma conexão TCP com o destino e então executa sua sessão SSH de ponta a ponta por esse fluxo de bytes. O transporte SSH final continua criptografado entre o cliente e o destino.
O bastion geralmente consegue saber que se conectou a 10.42.8.19:22. Ele pode registrar a conta usada no bastion, a origem, os horários e o destino de uma solicitação de encaminhamento. Mas não sabe automaticamente se a sessão criptografada executou depois systemctl restart api, cat /etc/shadow ou um shell interativo.
Isso deixa três observações diferentes que as pessoas costumam juntar em uma só:
- O destino solicitado é o que o agente forneceu, como
prod-api-01. - O destino da conexão é o endereço e a porta que o proxy realmente abriu.
- O destino da execução é a identidade do servidor e a conta que aceitaram a autenticação SSH final.
Eles podem ser diferentes. Um alias pode ser resolvido de outra forma depois de uma alteração no DNS. Uma entrada compromised ou antiga de known-hosts pode tornar uma conexão suspeita. Uma regra de proxy pode enviar um alias amigável para um endereço inesperado. Registrar apenas prod-api-01 não prova qual servidor executou um comando.
A mesma separação vale para os comandos. Um gateway no lado do cliente pode registrar o comando solicitado antes do transporte. Um wrapper no host final pode registrar o comando que o OpenSSH passa em uma solicitação exec. O bastion pode registrar o destino TCP. Correlacione essas observações por identificador de sessão e janela de tempo. Não finja que uma única camada enxerga todas elas.
Se você precisa de um único lugar capaz de inspecionar e autorizar cada comando remoto, o SSH comum de ponta a ponta por um jump box é o mecanismo errado. Use um serviço específico de execução remota, um endpoint de comandos restrito ou um wrapper no destino que aceite apenas a operação que você pretende oferecer. Essa escolha reduz a flexibilidade. Também impede que você alegue uma visibilidade que não possui.
As regras de rede devem tornar o caminho aprovado inevitável
Um ponto de entrada controlado só funciona quando a rede ao redor torna indisponíveis os caminhos alternativos. Comece pela alcançabilidade antes de discutir caixas de aprovação ou formatos de log.
O runtime do agente precisa de SSH de saída apenas para o endereço e a porta do bastion. Ele não deve ter uma rota ampla para sub-redes de produção, interfaces públicas de administração ou um segundo jump host que ninguém considerou parte do desenho. O DNS também importa. Se o agente consegue resolver e conectar-se a endereços brutos dos destinos, uma convenção de nomes amigáveis não protege você.
O bastion precisa de uma lista curta de permissões de saída. Se ele administra hosts na porta TCP 22 em dois intervalos privados, permita esses intervalos e essa porta. Não dê a ele acesso arbitrário de saída e chame o host de bastion. Um host de entrada que alcança todos os serviços, bancos de dados e endpoints públicos vira um relay geral quando a conta do agente é abusada.
Os destinos finais devem aceitar administração SSH apenas pelo caminho do bastion. Grupos de segurança na nuvem, firewalls dos hosts e ACLs de rede podem ajudar. Use mais de um controle apenas quando conseguir manter clara a responsabilidade por cada um. Uma regra que ninguém mantém não é defesa.
Teste a rota com casos de bloqueio, não apenas com o comando bem-sucedido. Execute estas verificações com o mesmo usuário, contêiner ou VM que executa o agente:
nc -vz bastion.internal.example 22
nc -vz 10.42.8.19 22
ssh -o ConnectTimeout=5 prod-api-01 true
A primeira conexão deve funcionar. A conexão direta com o host final deve falhar. O comando SSH deve funcionar apenas porque a rota configurada usa o bastion. Se nc não estiver disponível, use o comando normal de teste TCP do seu ambiente. O objetivo é testar o caminho de rede sem permitir que a configuração SSH esconda uma rota direta.
Repita o teste depois de alterações no firewall, de novas sub-redes e de mudanças no executor do agente. É um teste pequeno com retorno excepcionalmente alto. Ele detecta o caso comum em que a configuração SSH parece correta, mas a rede ainda permite uma conexão direta.
O agente precisa de uma identidade que você possa revogar
Não conceda ao agente uma chave de administrador compartilhada esperando que o bastion torne isso aceitável. Uma chave privada copiada é uma decisão de autorização com consequências muito duradouras.
Dê a cada processo ou execução do agente uma identidade que você consiga atribuir e revogar. O mecanismo pode ser um certificado SSH de curta duração, uma chave efêmera registrada para um trabalho limitado ou uma credencial mantida por um gateway de ações que executa SSH em nome do agente. A escolha certa depende do seu ambiente, mas o agente não deve imprimir um segredo reutilizável em seu transcript, workspace, histórico do shell ou saída de ferramenta.
Certificados SSH ajudam quando você já opera uma autoridade certificadora SSH. Um certificado pode conter um período curto de validade, um principal para a conta de destino e opções críticas, como restrições de endereço de origem. O destino pode confiar na CA em vez de manter uma lista crescente de chaves públicas individuais. Isso facilita a inspeção da emissão e da expiração.
Certificados não tornam uma conta ampla em uma conta restrita. Um certificado para root continua sendo uma credencial de root até expirar. Eles também não comprovam a intenção de um comando. Trate-os como um mecanismo de emissão e duração.
Um gateway altera mais profundamente o padrão de exposição. O Sallyport pode executar SSH pelo helper sp-ssh, enquanto a chave SSH permanece em seu cofre criptografado, sem chegar ao processo do agente. Isso protege a chave privada contra o transcript do agente, mas as equipes ainda devem testar como a rota planejada pelo jump host, a identidade do destino e as evidências dos comandos são registradas.
Vincule a aprovação a um processo identificável, não à frase que o agente escreveu em uma janela de chat. Um processo pode ser assinado, iniciado em determinado horário, associado a um usuário local e revogado enquanto a sessão estiver em execução. Uma explicação em linguagem natural é um contexto útil, mas não é um limite de controle de acesso.
Evite uma única credencial compartilhada por todo o trabalho automatizado. Quando um log do lado do destino diz deploy, você precisa de um segundo registro que identifique a execução do agente que o invocou. Se todas as execuções usarem a mesma chave e a mesma conta, a análise de um incidente vira arqueologia.
Registre uma declaração de execução, um fato de rota e um resultado
Um registro de auditoria SSH de agente deve dizer exatamente o que cada campo significa. Isso impede que o sistema de auditoria faça afirmações que não consegue sustentar.
No momento da solicitação da ação, registre a identidade da execução do agente, o alias de host solicitado, a conta remota solicitada, o texto do comando ou a operação estruturada e se o chamador pediu um TTY ou encaminhamento. Essa é a declaração de execução. Ela informa o que o chamador tentou fazer.
No limite da rota, registre a identidade do host de entrada, o endereço de destino resolvido, a porta de destino e o resultado da conexão. Esse é o fato de rota. Se o proxy abrir uma conexão, ele pode dizer onde a abriu. Não pode inferir corretamente o comando final a partir de bytes criptografados.
No host final, registre a identidade estável do host de destino, a conta autenticada, a impressão digital da autenticação ou o número de série do certificado, o comando se o servidor recebeu uma solicitação exec, o status de saída e os logs locais relevantes do serviço. Essa é a evidência de execução. O host final é o único endpoint SSH normal que consegue ver o comando remoto sem romper o desenho SSH de ponta a ponta.
Use um formato de evento que torne visível a ausência de evidências:
{
"run_id": "run_7c31",
"requested": {
"host": "prod-api-01",
"user": "deploy",
"command": "sudo systemctl restart api",
"tty": false
},
"route": {
"bastion": "bastion.internal.example",
"destination_ip": "10.42.8.19",
"destination_port": 22
},
"final_host": {
"host_fingerprint": "SHA256:example",
"authenticated_user": "deploy",
"command_observed": true,
"exit_status": 0
}
}
O exemplo separa deliberadamente requested.command de uma observação feita no host final. Se a sessão foi interativa, defina command_observed como false e explique o motivo. Um campo vazio sem explicação convida alguém a presumir que a ferramenta o capturou.
Para execução de comandos comum, sshd_config(5) documenta ForceCommand, que força um comando para uma conta correspondente ou um bloco match. Um wrapper no lado do destino pode ler SSH_ORIGINAL_COMMAND em uma solicitação exec, validar uma operação permitida e gravar um registro de auditoria antes de chamar o programa aprovado. Ele exige um tratamento cuidadoso do shell. Não passe uma string de comando não confiável por eval e não presuma que SSH_ORIGINAL_COMMAND exista para um shell interativo.
O encadeamento de hashes e o armazenamento somente para anexação ajudam a detectar alterações posteriores nos eventos de auditoria. Eles não corrigem um conteúdo fraco. Um registro perfeitamente preservado que diga apenas «SSH conectado» continua sendo uma evidência fraca.
Torne a configuração SSH inspecionável
Mantenha aliases de host para as pessoas, mas inspecione o que o OpenSSH realmente fará antes de entregar uma configuração a um agente. ssh -G imprime a configuração efetiva do cliente depois que o OpenSSH processa as entradas Host correspondentes.
Este exemplo encaminha um destino nomeado por meio de um bastion também nomeado e desativa opções que costumam surpreender as equipes:
Host agent-bastion
HostName bastion.internal.example
User agent-gateway
IdentityFile ~/.ssh/agent_gateway
IdentitiesOnly yes
Host prod-api-01
HostName 10.42.8.19
User deploy
ProxyJump agent-bastion
StrictHostKeyChecking yes
UserKnownHostsFile ~/.ssh/agent_known_hosts
ForwardAgent no
RequestTTY no
Depois, confira as configurações renderizadas:
ssh -G prod-api-01 | grep -E '^(hostname|user|proxyjump|forwardagent|requesttty) '
A saída deve ter o mesmo formato deste exemplo:
user deploy
hostname 10.42.8.19
requesttty no
forwardagent no
proxyjump agent-bastion
Isso prova como o cliente planeja se comportar. Não prova que a rede bloqueia SSH direto, que o destino apresenta a chave de host esperada ou que o bastion restringe sua saída. Teste esses pontos separadamente.
Não permita que o agente forneça livremente flags arbitrárias do ssh. Um agente pode substituir a configuração com opções de linha de comando, especificar um endereço IP bruto, trocar o ProxyJump ou adicionar opções de encaminhamento se a camada de execução simplesmente repassar uma string de shell. Sempre que possível, coloque o destino, a conta e as opções SSH permitidas em entradas estruturadas de ação. Se você aceitar um comando bruto, trate-o como código e aplique a mesma desconfiança usada para um script de shell vindo de uma fonte não confiável.
A verificação da chave do host merece atenção porque os agentes tentam novamente de forma automática e muitas vezes tratam um erro como um obstáculo à tarefa. Pré-carregue as impressões digitais confiáveis dos hosts por meio de um processo controlado. Mantenha a verificação rigorosa ativada. Não ensine o agente a remover entradas de known-hosts ou aceitar chaves alteradas para destravar uma implantação. Uma alteração na chave do host exige que uma pessoa responsável verifique por que ela mudou.
Encaminhamento e shells criam caminhos ao redor da sua revisão
Desative o encaminhamento e os shells interativos para agentes autônomos, a menos que uma tarefa específica precise deles. As duas funções transformam um comando remoto limitado em um canal de acesso mais amplo.
O encaminhamento local permite que um cliente abra uma porta local que alcança um serviço interno por SSH. O encaminhamento remoto permite que um endpoint remoto exponha um caminho de volta ao lado do cliente. O encaminhamento dinâmico cria um proxy SOCKS. O encaminhamento do agente disponibiliza credenciais para outro host. Cada recurso pode ser legítimo para uma pessoa administradora. Cada um também enfraquece a afirmação de que o bastion é a única rota controlada.
O OpenSSH oferece restrições no servidor que devem ser aplicadas à conta do destino ou do bastion, não apenas na configuração do cliente do agente. sshd_config(5) documenta DisableForwarding, e authorized_keys aceita opções como no-port-forwarding, no-agent-forwarding, no-X11-forwarding e no-pty. Use os controles compatíveis com sua versão do OpenSSH e depois verifique-os com uma tentativa de conexão real.
Uma conta restrita pode usar uma entrada de chave autorizada com este formato:
no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... agent-run
Essa linha limita os recursos dessa chave pública. Ela não restringe os comandos que a conta pode executar. Combine-a com uma conta limitada, um wrapper ForceCommand ou uma interface específica do serviço se o escopo dos comandos for importante.
Para shells interativos, adote uma regra direta: por padrão, não dê um shell a um agente autônomo. Um shell aceita sequências de comandos, pipelines, redirecionamentos, processos em segundo plano e credenciais copiadas. O campo de comando da solicitação de ação inicial não descreverá a sessão inteira. Um wrapper forçado pode bloquear um shell, mas teste esse comportamento, pois ele muda conforme a configuração da conta e as solicitações de subsistema SSH.
Alguns trabalhos de manutenção realmente exigem um túnel ou um shell. Trate-os como caminhos de exceção explícitos, com aprovação de uma pessoa responsável e prazo curto. Tentar esconder uma exceção dentro de uma credencial geral de agente é como o acesso temporário se torna permanente.
Restrições no destino são melhores que filtros de strings de comando
Uma lista simples de prefixos de comandos do shell é fácil de contornar e difícil de manter. Ela é popular porque parece precisa: permitir systemctl restart api, rejeitar todo o resto. A gramática do shell torna essa confiança frágil.
Considere um filtro que aceita textos começando com systemctl restart api. O chamador pode acrescentar um operador do shell, usar um caminho diferente para o executável, provocar comportamento por meio de uma variável de ambiente ou explorar um wrapper que interpreta a string de forma inconsistente. Mesmo um parser cuidadoso não consegue conhecer todos os efeitos de um comando que chama outro programa.
Use operações estruturadas quando o trabalho tiver um formato estável. Um executor de implantação pode aceitar o nome de uma aplicação e um identificador de release. Um endpoint de manutenção pode aceitar um nome de serviço de uma lista fixa. Um wrapper restrito pode mapear um pequeno nome de operação para um array argv fixo. Em todos esses casos, evite o shell.
Quando for necessário aceitar comandos livres, reconheça o que está permitindo: autoridade para executar um shell remoto nessa conta. Registre isso, limite o tempo de validade da credencial, restrinja o ambiente de destino e exija um nível separado de aprovação. Não venda um filtro de strings como autorização de comandos.
A conta de destino também deve ter um limite de permissões no sistema operacional. Uma conta deploy que pode executar sudo sem restrições é, na prática, uma conta administradora com alguns caracteres extras. Dê a ela apenas as ações de serviço, arquivos e diretórios exigidos pela automação. Revise as regras de sudo como código, incluindo cada caminho de comando e padrão de argumentos.
O teste prático é verificar se um agente encarregado de reiniciar um serviço consegue ler segredos de produção, criar um túnel reverso, alterar a autorização SSH ou modificar o coletor de auditoria. Se conseguir, o escopo da conta está errado, mesmo que todas as conexões tenham usado o bastion correto.
A resposta a incidentes começa com a interrupção da rota ativa
Quando um agente se comportar de modo suspeito, revogue seu acesso ativo antes de começar a reconstruir sua intenção. Desative a sessão ativa no limite da ação, se você tiver esse controle, bloqueie a origem no bastion e impeça que a credencial associada se autentique novamente. Preserve os logs antes que alguém faça a rotação dos arquivos ou reinicie o host que contém as evidências.
Depois, monte uma linha do tempo a partir dos registros separados. Comece pela ação solicitada pelo agente. Relacione-a ao destino e ao horário da conexão no bastion. Relacione isso à autenticação no host final e às evidências do comando. Verifique se apareceu um TTY, uma solicitação de encaminhamento ou um destino alternativo. Uma divergência não é automaticamente maliciosa, mas mostra qual controle precisa ser investigado.
Não responda concedendo permanentemente mais acesso «para que o agente possa corrigir o problema». Essa é uma reação comum de pânico. Se o agente já se comportou fora do esperado, ampliar sua conta ou abrir uma rota direta remove as evidências necessárias e cria outro incidente.
Faça um pequeno exercício antes que a produção precise dele. Revogue um agente de teste durante um comando SSH inofensivo, confirme que novas solicitações falham e verifique se seus registros mostram o host solicitado, a rota real, a identidade do destino e o resultado da execução. Se esse exercício exigir um grupo de chat para descobrir o que aconteceu, seu desenho de acesso ainda está vago demais.
Um bastion cumpre seu papel quando impõe uma rota, permite uma revogação rápida e contribui com um fato preciso para a trilha de auditoria. Configure primeiro a rota, mantenha as credenciais fora do agente e colete as evidências no host final, onde os comandos finais ficam visíveis. Qualquer coisa abaixo disso é uma conveniência de SSH com um nome que parece seguro.
FAQ
Um bastion host torna um agente de IA seguro por si só?
Não. Um bastion apenas coloca um host no caminho da rede. Se o agente ainda puder alcançar diretamente os endereços de destino, escolher outro proxy ou possuir chaves privadas reutilizáveis, ele poderá contornar a rota planejada.
Um jump host consegue ver todos os comandos executados por um agente?
Geralmente não. Com ProxyJump, o bastion encaminha o transporte SSH, e o host final vê a sessão SSH real. Normalmente, o bastion não consegue ler o comando remoto dentro dessa sessão criptografada.
O que um registro de auditoria do acesso SSH de um agente deve conter?
Registre o alias solicitado, o host e a porta resolvidos, o bastion usado, a impressão digital do host final, a conta remota, o comando exato quando disponível, o status de saída e um transcript ou resumo do resultado, de acordo com uma política de retenção definida. Não trate um alias como prova da máquina alcançada.
Como impedir que um agente contorne o ProxyJump?
Use controles de rede como ponto de imposição. Permita que o ambiente do agente faça conexões SSH de saída apenas para o bastion. Depois, permita que o bastion saia apenas para os endereços e portas de destino aprovados.
Um agente de IA para programação deve ter uma chave privada SSH?
O agente não deve possuir uma chave privada de longa duração. Mantenha a credencial em um gateway ou emita certificados de curta duração após uma aprovação. Depois, restrinja a conta de destino ao menor conjunto de ações necessário.
Certificados SSH são melhores que chaves estáticas para agentes?
Os certificados SSH reduzem o impacto de um vazamento e tornam a emissão rastreável, mas não inspecionam comandos nem impedem encaminhamento por conta própria. Ainda são necessárias restrições de conta, limites de rede e evidências dos comandos no local em que eles ficam visíveis.
Quais recursos SSH devem ser desativados para agentes autônomos?
Trate o encaminhamento de portas, o encaminhamento de agente, o encaminhamento X11 e os shells interativos como capacidades separadas. Desative-os por padrão e adicione uma exceção estreita e testada quando uma tarefa real exigir uma delas.
Por que os agentes devem evitar shells SSH interativos?
Um shell interativo oferece ao agente uma sessão aberta e torna a auditoria em nível de comando muito mais fraca. Prefira um único comando explícito sem TTY, um wrapper restrito ou uma API remota quando a tarefa permitir.
Qual é o melhor lugar para capturar o comando remoto?
Um wrapper no host final usando ForceCommand pode receber SSH_ORIGINAL_COMMAND em solicitações exec comuns, enquanto um gateway de ações no cliente pode registrar a ação solicitada antes do início do transporte. Nenhum dos registros, sozinho, comprova todos os efeitos. Correlacione-os com os logs locais do host de destino e com o resultado.
O que fazer se um agente fizer uma conexão SSH suspeita?
Revogue a sessão ativa, remova as credenciais do agente ou pare de emiti-las e preserve os registros de auditoria relevantes antes de fazer alterações amplas na configuração. Depois, compare o destino solicitado, o destino da conexão e as evidências locais do host de destino para descobrir onde o controle falhou.