SSH agent forwarding: acessando repositórios via jump hosts

1. Fundamentos do SSH Agent Forwarding

SSH agent forwarding é um mecanismo que permite que um servidor remoto utilize as chaves SSH armazenadas no agente da sua máquina local, sem que você precise copiar a chave privada para o servidor intermediário. O funcionamento é simples: quando você se conecta a um host remoto com forwarding habilitado, o servidor cria um canal de comunicação com o agente SSH da sua máquina local. Qualquer tentativa de autenticação SSH feita a partir desse host remoto é redirecionada para o seu agente local, que realiza a assinatura criptográfica e retorna o resultado.

A diferença fundamental entre agent forwarding e cópia de chaves privadas é que, no forwarding, a chave privada nunca sai da sua máquina. Apenas operações de assinatura são delegadas ao agente local. Isso elimina o risco de exposição da chave caso o servidor intermediário seja comprometido.

O cenário típico envolve um desenvolvedor em sua máquina local (workstation) que precisa acessar um servidor Git remoto (como GitHub, GitLab ou Bitbucket) através de um servidor intermediário (jump host ou bastion host). Esse jump host é o único ponto de entrada na rede corporativa, e o servidor Git está acessível apenas a partir dele.

2. Configuração Básica do Ambiente

Primeiro, verifique se o agente SSH está em execução na sua máquina local:

$ ssh-add -l
The agent has no identities.

Se o agente não estiver rodando, inicie-o:

$ eval "$(ssh-agent -s)"
Agent pid 12345

Adicione sua chave privada ao agente:

$ ssh-add ~/.ssh/id_ed25519
Enter passphrase for /home/usuario/.ssh/id_ed25519:
Identity added: /home/usuario/.ssh/id_ed25519 (usuario@exemplo.com)

Configure o arquivo ~/.ssh/config para habilitar o forwarding para o jump host:

Host jump-host
    HostName jump.exemplo.com
    User usuario
    ForwardAgent yes
    IdentityFile ~/.ssh/id_ed25519

A diretiva ForwardAgent yes instrui o cliente SSH a encaminhar o agente para a sessão remota. Sem essa configuração, o forwarding não ocorre.

3. Jump Hosts e Acesso a Repositórios Git

A estrutura de conexão típica é: local → jump host → servidor Git remoto. O comando git clone precisa atravessar o jump host para alcançar o repositório.

Exemplo prático usando -J (atalho para ProxyJump):

$ git clone -J usuario@jump.exemplo.com git@github.com:usuario/repositorio.git

Para maior clareza, configure o ~/.ssh/config com o proxy:

Host github.com
    HostName github.com
    User git
    ProxyJump usuario@jump.exemplo.com
    ForwardAgent yes

Agora o clone fica simples:

$ git clone git@github.com:usuario/repositorio.git

Para verificar se o forwarding está funcionando, conecte-se ao jump host e execute:

$ ssh usuario@jump.exemplo.com
$ echo $SSH_AUTH_SOCK
/tmp/ssh-XXXXXX/agent.XXXX
$ ssh-add -l
256 SHA256:xxxxxxxxxx usuario@exemplo.com (ED25519)

A presença da variável SSH_AUTH_SOCK e a listagem das chaves confirmam que o agente local foi encaminhado.

4. Segurança e Riscos do Forwarding

O principal risco do SSH agent forwarding é que qualquer usuário com privilégios de root no jump host pode utilizar sua chave para autenticar em outros servidores. Durante o período em que você está conectado, o socket do agente fica acessível no sistema de arquivos remoto.

Boas práticas de segurança:

  • Configure ForwardAgent no como padrão no ~/.ssh/config e habilite apenas para hosts específicos
  • Use ForwardAgent no global e habilite apenas para o jump host confiável:
Host *
    ForwardAgent no

Host jump-host
    ForwardAgent yes
  • Nunca use forwarding para hosts públicos ou não confiáveis
  • Utilize ssh -A apenas quando necessário, não por padrão

Uma alternativa mais segura é usar ProxyJump sem forwarding. Nesse caso, o jump host atua apenas como túnel, sem acesso às suas chaves:

Host github.com
    HostName github.com
    User git
    ProxyJump usuario@jump.exemplo.com
    ForwardAgent no

A diferença é sutil: com ProxyJump, a conexão SSH para o servidor Git é estabelecida diretamente da sua máquina, usando um túnel através do jump host. O jump host nunca vê as requisições de autenticação.

5. Solução de Problemas Comuns

Erro "Permission denied (publickey)" mesmo com chave carregada:

$ git clone git@github.com:usuario/repositorio.git
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Diagnóstico passo a passo:

  1. Teste a conexão SSH manualmente:
$ ssh -T git@github.com

Se falhar, teste a conexão ao jump host:

$ ssh -v usuario@jump.exemplo.com
  1. Verifique as permissões do diretório ~/.ssh e da chave:
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/id_ed25519
$ chmod 644 ~/.ssh/id_ed25519.pub
  1. Confirme que a chave está no agente:
$ ssh-add -l
  1. Teste o forwarding conectando ao jump host e verificando o agente remoto:
$ ssh usuario@jump.exemplo.com "ssh-add -l"

Se o comando retornar "The agent has no identities", o forwarding não está funcionando. Verifique se ForwardAgent yes está configurado corretamente.

6. Fluxos Avançados com Múltiplos Saltos

Para ambientes com múltiplos jump hosts (local → host1 → host2 → Git), configure o ProxyJump encadeado:

Host host1
    HostName host1.exemplo.com
    User usuario1
    ForwardAgent yes
    IdentityFile ~/.ssh/chave_para_host1

Host host2
    HostName host2.exemplo.com
    User usuario2
    ProxyJump usuario1@host1.exemplo.com
    ForwardAgent yes
    IdentityFile ~/.ssh/chave_para_host2

Host github.com
    HostName github.com
    User git
    ProxyJump usuario2@host2.exemplo.com
    ForwardAgent no

Para usar identidades diferentes em cada salto, utilize ProxyCommand com controle fino:

Host host1
    HostName host1.exemplo.com
    User usuario1
    IdentityFile ~/.ssh/chave_a
    ForwardAgent yes

Host host2
    HostName host2.exemplo.com
    User usuario2
    ProxyCommand ssh -W %h:%p host1
    IdentityFile ~/.ssh/chave_b
    ForwardAgent yes

Host github.com
    HostName github.com
    User git
    ProxyCommand ssh -W %h:%p host2
    IdentityFile ~/.ssh/chave_git

Nessa configuração, a chave chave_a autentica no host1, chave_b no host2, e chave_git no servidor Git. O forwarding só é necessário nos hosts intermediários se você precisar autenticar a partir deles.

7. Integração com Credential Helpers e Automação

É importante distinguir entre agent forwarding (para SSH) e credential helpers (para HTTPS). O credential helper armazena credenciais HTTP e não tem relação com o agente SSH.

Para automação, você pode configurar o agente para iniciar automaticamente em sessões SSH. Adicione ao ~/.bashrc ou ~/.zshrc:

if [ -z "$SSH_AUTH_SOCK" ]; then
    eval "$(ssh-agent -s)" > /dev/null
    ssh-add ~/.ssh/id_ed25519 2>/dev/null
fi

Para controle fino do comando SSH usado pelo Git, utilize GIT_SSH_COMMAND:

$ GIT_SSH_COMMAND="ssh -o ForwardAgent=yes -J usuario@jump.exemplo.com" git clone git@github.com:usuario/repositorio.git

Isso permite sobrescrever o comportamento padrão sem modificar o ~/.ssh/config. Você pode definir essa variável no ~/.bashrc para sessões específicas:

export GIT_SSH_COMMAND="ssh -o ForwardAgent=yes -J usuario@jump.exemplo.com"

Lembre-se: o forwarding é uma ferramenta poderosa, mas use com discernimento. Prefira ProxyJump sem forwarding sempre que possível, e reserve o agent forwarding apenas para cenários onde o jump host precisa autenticar em seu nome.

Referências