ProxyJump e Redes Complexas
Nota: Este é o nono tutorial da série sobre SSH. Se você perdeu o anterior sobre ssh-agent e gerenciamento de chaves, pode encontrá-lo aqui: SSH Agent, Agent Forwarding e Certificados SSH.
Em muitos ambientes de rede corporativos ou complexos, por razões de segurança, os servidores críticos não são diretamente acessíveis pela internet ou mesmo de todas as partes da rede interna. Em vez disso, o acesso é canalizado através de servidores intermediários especialmente designados, conhecidos como Bastion Hosts ou Jump Hosts (ou Jump Servers).
Esses servidores atuam como um ponto de entrada controlado e monitorado para segmentos de rede mais seguros. Para acessar um servidor final (destino), você primeiro se conecta ao bastion host e, a partir dele, estabelece uma segunda conexão para o destino.
Fazer isso manualmente (conectar ao bastion, depois digitar ssh destino
dentro dessa sessão) funciona, mas é inconveniente, especialmente para transferências de arquivos (scp
, rsync
) ou se houver múltiplos saltos. Felizmente, o OpenSSH (versão 7.3 e posteriores) oferece uma maneira muito mais elegante e transparente de lidar com isso: a diretiva ProxyJump
(e sua flag de linha de comando correspondente -J
).
O Conceito: Salto Transparente
O ProxyJump
permite que o cliente ssh
estabeleça automaticamente a conexão com o servidor intermediário (bastion) e, em seguida, use o comando sshd
nesse intermediário para encaminhar a conexão TCP para o destino final, tudo dentro de um único comando ssh
iniciado na sua máquina local.
Para o usuário, parece que ele está se conectando diretamente ao host de destino, embora a conexão esteja sendo seguramente tunelada através do(s) bastion(s).
Conectando Através de Um Salto (Bastion Host)
Vamos usar nossa arquitetura de referência. Queremos conectar da nossa Estação de Trabalho (192.168.0.10
) para a VM EVE-NG (192.168.122.50
), mas só podemos acessar diretamente o Servidor KVM (192.168.0.254
), que funciona como nosso bastion host.
Método 1: Usando a Flag -J
(Jump Host)
A flag -J
permite especificar o(s) jump host(s) diretamente na linha de comando.
1
ssh -J <usuario_bastion>@<host_bastion> <usuario_destino>@<host_destino>
No nosso exemplo, execute na Estação de Trabalho:
1
ssh -J user_kvm@192.168.0.254 user_eve@192.168.122.50
-J user_kvm@192.168.0.254
: Especifica que devemos primeiro conectar ao Servidor KVM comouser_kvm
.user_eve@192.168.122.50
: O destino final.
O cliente ssh
fará o seguinte:
- Conecta-se a
192.168.0.254
comouser_kvm
(pedirá autenticação - senha ou chave/agente). - Uma vez conectado, instrui o
sshd
no KVM a estabelecer uma conexão TCP para192.168.122.50
na porta 22. - Encaminha a comunicação entre sua máquina local e a VM EVE-NG através do túnel estabelecido com o KVM.
Você será solicitado a autenticar para o destino final (user_eve@192.168.122.50
) como se estivesse conectando diretamente (novamente, usando senha ou chave/agente).
Método 2: Usando ~/.ssh/config
(Recomendado)
Como vimos no Tutorial 5, podemos definir isso de forma permanente e mais limpa no nosso arquivo ~/.ssh/config
usando a diretiva ProxyJump
.
Relembrando nossa configuração:
1
2
3
4
5
6
7
8
9
10
11
# ~/.ssh/config
Host kvm-server
HostName 192.168.0.254
User user_kvm
Host eve-ng-vm
HostName 192.168.122.50
User user_eve
# Especifica o alias do bastion host
ProxyJump kvm-server
Com esta configuração, basta executar na Estação de Trabalho:
1
ssh eve-ng-vm
O cliente ssh
lerá a configuração, verá a diretiva ProxyJump kvm-server
, resolverá kvm-server
para suas configurações (HostName 192.168.0.254
, User user_kvm
) e realizará o salto automaticamente.
Vantagens de usar ~/.ssh/config
:
- Não precisa lembrar a sintaxe do
-J
ou os detalhes do bastion host. - Funciona transparentemente com outras ferramentas SSH como
scp
,sftp
,rsync
:1 2
scp meu_arquivo.txt eve-ng-vm:/caminho/remoto/ # Funciona! rsync -avz local_dir/ eve-ng-vm:~/remote_dir/ # Funciona!
Conectando Através de Múltiplos Saltos
O ProxyJump
e a flag -J
suportam elegantemente múltiplos saltos intermediários. Basta listar os jump hosts na ordem em que devem ser atravessados, separados por vírgula.
Vamos ao nosso exemplo de dois saltos: conectar da Estação de Trabalho (192.168.0.10
) para o Dispositivo Simulado (10.240.0.50
) passando primeiro pelo Servidor KVM (192.168.0.254
) e depois pela VM EVE-NG (192.168.122.50
).
Método 1: Usando a Flag -J
1
ssh -J <user_bastion1>@<host_bastion1>,<user_bastion2>@<host_bastion2> <user_destino>@<host_destino>
No nosso exemplo, execute na Estação de Trabalho:
1
ssh -J user_kvm@192.168.0.254,user_eve@192.168.122.50 user_device@10.240.0.50
O cliente ssh
fará:
- Conecta ao
kvm-server
. - A partir do
kvm-server
, conecta àeve-ng-vm
(usando osshd
do KVM para encaminhar). - A partir da
eve-ng-vm
, conecta aosimulated-device
(usando osshd
da EVE-NG para encaminhar).
Você será solicitado a autenticar em cada salto, se necessário (KVM, depois EVE-NG, depois Dispositivo Simulado).
Método 2: Usando ~/.ssh/config
O ~/.ssh/config
lida com isso de forma ainda mais transparente. Se um host especificado em ProxyJump
também tiver sua própria diretiva ProxyJump
, o cliente encadeará os saltos automaticamente.
Relembrando nossa configuração completa do Tutorial 5:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ~/.ssh/config
Host kvm-server
HostName 192.168.0.254
User user_kvm
Host eve-ng-vm
HostName 192.168.122.50
User user_eve
ProxyJump kvm-server # Salto 1
Host simulated-device
HostName 10.240.0.50
User user_device
ProxyJump eve-ng-vm # Salto 2 (que por sua vez usa Salto 1)
Com esta configuração, para conectar ao destino final (Dispositivo Simulado), basta executar na Estação de Trabalho:
1
ssh simulated-device
O cliente ssh
resolverá a cadeia: simulated-device
precisa pular por eve-ng-vm
, e eve-ng-vm
precisa pular por kvm-server
. Ele então executará a sequência de conexões necessária automaticamente.
Menção: Método Legado com ProxyCommand
Antes da introdução do ProxyJump
(OpenSSH 7.3), a maneira padrão de configurar jump hosts no ~/.ssh/config
era usando a diretiva ProxyCommand
. Ela é mais genérica e poderosa, mas também mais complexa e propensa a erros de configuração.
ProxyCommand
instrui o cliente ssh
a executar um comando específico para estabelecer a conexão com o servidor, em vez de fazer uma conexão TCP direta. O comando deve receber dados na entrada padrão (stdin) e enviar dados para a saída padrão (stdout), que o ssh
então usa para a comunicação.
Exemplo (equivalente a ProxyJump kvm-server
para eve-ng-vm
):
1
2
3
4
5
Host eve-ng-vm
HostName 192.168.122.50
User user_eve
# Método legado:
ProxyCommand ssh kvm-server -W %h:%p
ssh kvm-server
: Executa um novo comandossh
para conectar ao bastion host (kvm-server
, que deve estar definido em outro lugar no config ou ser resolvível).-W %h:%p
: Esta é a parte crucial. A flag-W
(disponível em versões mais recentes dossh
) instrui ossh
no bastion a encaminhar stdin/stdout para o host (%h
) e porta (%p
) do destino final (eve-ng-vm
neste caso), sem alocar um pty ou executar um shell no bastion.
Para múltiplos saltos com ProxyCommand
, a configuração se torna ainda mais complexa, muitas vezes exigindo encadear múltiplos ssh -W
ou usar ferramentas como netcat
(nc
) dentro do ProxyCommand
.
Quando usar ProxyCommand
hoje?
- Se você precisa de compatibilidade com versões do OpenSSH anteriores à 7.3.
- Em cenários muito específicos onde você precisa de lógica customizada para estabelecer a conexão que
ProxyJump
não cobre (ex: usar um túnel diferente, executar um script de autenticação customizado antes de conectar).
Para a maioria dos casos de uso de bastion/jump hosts, ProxyJump
(ou -J
) é a abordagem moderna, mais simples e recomendada.
Conclusão
Navegar por redes complexas com múltiplos segmentos e firewalls é um desafio comum. Os bastion hosts fornecem um ponto de acesso seguro, e o ProxyJump
do OpenSSH torna a conexão através desses intermediários uma tarefa transparente e eficiente.
Seja usando a flag -J
para conexões ad-hoc ou, preferencialmente, configurando a diretiva ProxyJump
no seu ~/.ssh/config
, você pode simplificar enormemente o acesso a hosts remotos que não estão diretamente acessíveis, fazendo com que múltiplos saltos pareçam uma conexão direta.
No próximo tutorial, abordaremos técnicas de hardening e melhores práticas de segurança para cliente e servidor SSH.