Encaminhamento de Porta SSH: Túneis Local, Remoto e Dinâmico

Encaminhamento de Porta SSH: Túneis Local, Remoto e Dinâmico

O Que Você Vai Aprender

  • A diferença entre encaminhamento -L (local), -R (remoto) e -D (dinâmico)
  • Como acessar um banco de dados atrás de um bastion, expor um app local e executar um proxy SOCKS
  • Como solucionar problemas quando um túnel "não conecta"

Resumo Rápido

  • Acessar um serviço remoto da sua máquina -> -L (encaminhamento local)
  • Expor um serviço local para um host remoto -> -R (encaminhamento remoto)
  • Enviar todo o tráfego de um app pelo SSH -> -D (dinâmico / SOCKS)

Premissas

  • SO: Ubuntu (cliente / servidor OpenSSH)
  • Você já consegue fazer login via SSH
  • Os números de porta são exemplos; adapte para sua configuração

O Que é Encaminhamento de Porta SSH?

Conclusão: Ele cria túneis para conexões TCP arbitrárias dentro da sessão SSH criptografada, permitindo acessar portas que você não consegue alcançar diretamente, desde que consiga fazer SSH.

Serviços atrás de um firewall ou dentro de uma rede privada não podem ser alcançados diretamente de fora. Mas se você conseguir fazer SSH, pode transportar outra conexão TCP dentro dessa sessão SSH. Isso é encaminhamento de porta (tunelamento).

Existem três tipos. Eles diferem apenas na direção e em qual lado escuta; a ideia é a mesma.

Tipo Opção Escuta em Caso de uso
Local -L Seu lado Usar um serviço remoto da sua máquina
Remoto -R Remoto Expor um serviço local para o remoto
Dinâmico -D Seu lado Enviar todo o tráfego de um app pelo túnel

Como Usar Encaminhamento Local (-L)?

Conclusão: O formato é -L portaLocal:hostDestino:portaDestino. Conexões na sua porta local são encaminhadas ao destino visto pelo servidor SSH. Acessar um BD através de um bastion é o caso clássico.

Formato básico

$ ssh -L 8080:localhost:80 user@server

Agora uma conexão ao seu localhost:8080 alcanca localhost:80 visto pelo server. Abra http://localhost:8080 no navegador e funciona como se estivesse acessando a porta 80 do servidor.

O hostDestino é resolvido do ponto de vista do servidor SSH. localhost significa o próprio servidor; outro nome significa um host que o servidor consegue alcançar.

Exemplo: acessar um BD através de um bastion

O banco de dados (db.internal:5432) está atrás de um bastion e não é alcançável diretamente da sua máquina.

$ ssh -L 15432:db.internal:5432 user@bastion

Em outro terminal, trate sua porta local 15432 como se fosse o BD real.

$ psql -h localhost -p 15432 -U dbuser appdb

Somente túnel (-N / -f)

Se você não precisa de um shell de login e quer apenas o túnel, adicione -N; para colocar em segundo plano, adicione -f.

$ ssh -fN -L 15432:db.internal:5432 user@bastion
  • -N: não executar um comando remoto (somente encaminhamento)
  • -f: ir para segundo plano após autenticação

Um túnel em segundo plano continua rodando. Pare-o quando terminar.

$ ps aux | grep "ssh -fN"
$ kill <PID>

Como Usar Encaminhamento Remoto (-R)?

Conclusão: O formato é -R portaRemota:hostDestino:portaDestino. O lado remoto escuta e encaminha para um destino visto pela sua máquina. Compartilhar temporariamente um servidor de desenvolvimento local é o uso comum.

Essa é a direção reversa. Uma conexão na porta remota alcanca o destino visto pela sua máquina (a que está executando ssh).

Formato básico

$ ssh -R 8080:localhost:3000 user@server

Uma conexão ao localhost:8080 no server é encaminhada ao seu localhost:3000. Seu servidor de desenvolvimento local (porta 3000) se torna alcançável a partir do servidor.

O detalhe para acesso público: GatewayPorts

Por padrão, -R escuta apenas no loopback remoto (127.0.0.1). O próprio servidor consegue alcançá-lo, mas nada fora do servidor consegue. Para escutar em todas as interfaces, o /etc/ssh/sshd_config do servidor precisa de:

GatewayPorts yes

Recarregue após alterar: sudo systemctl reload ssh.

O Que é Encaminhamento Dinâmico (-D)?

Conclusão: -D porta abre um proxy SOCKS local. Em vez de um túnel por destino, o tráfego de um app sai pelo servidor SSH.

-L é "uma porta, um destino", mas -D não fixa um destino. Ele cria um proxy SOCKS localmente; qualquer app apontado para ele envia tráfego pelo servidor SSH.

$ ssh -D 1080 user@server

Agora localhost:1080 é um proxy SOCKS5. Aponte seu navegador ou curl para ele.

$ curl --socks5-hostname localhost:1080 https://example.com

--socks5-hostname resolve nomes no lado do proxy. Use-o para alcançar hosts que somente o DNS do servidor SSH consegue resolver. O simples --socks5 resolve localmente.

Por Que Meu Túnel Não Conecta?

Conclusão: A maioria das falhas é por conflito de porta, mal-entendido sobre onde o nome de destino é resolvido, ou configurações de exposição remota ausentes. O texto do erro aponta qual.

bind: Address already in use

A porta de escuta no seu lado (ou no remoto, para -R) já está em uso. Use outra porta ou encontre o processo que a está ocupando.

$ ss -tlnp | grep :8080

channel ... open failed: connect failed

O túnel está ativo, mas o servidor SSH não consegue alcançar o destino. Verifique o host de destino, porta e alcançabilidade a partir do servidor.

$ ssh user@server
$ nc -vz db.internal 5432

-R funciona mas hosts externos não conseguem conectar

Geralmente é o GatewayPorts mencionado acima. Mesmo -R 0.0.0.0:8080:... não vai ajudar se a configuração do servidor ainda estiver em no.

Confusão comum: qual lado resolve o nome de destino?

  • Em -L 15432:db.internal:5432, db.internal resolve no servidor SSH
  • Em -R 8080:localhost:3000, localhost:3000 resolve na sua máquina

Quando "resolve localmente mas não conecta", você provavelmente confundiu o lado de resolução.

Como Salvar Túneis no ~/.ssh/config?

Conclusão: Em vez de opções longas toda vez, coloque LocalForward / RemoteForward / DynamicForward na sua config e execute apenas ssh host.

Host db-tunnel
    HostName bastion.example.com
    User user
    LocalForward 15432 db.internal:5432

Host socks
    HostName server.example.com
    User user
    DynamicForward 1080

A partir daí, basta nomear o host.

$ ssh -fN db-tunnel

Para mais sobre o arquivo de configuração, veja Dicas de SSH config.

Resumo e Modelos Seguros

Conclusão: Escolha -L ou -R pela direção, e -D quando o destino não é fixo. Não deixe túneis abertos; pare-os quando terminar.

Modelos para copiar e colar

# Encaminhamento local (BD remoto para sua maquina)
ssh -fN -L 15432:db.internal:5432 user@bastion

# Encaminhamento remoto (seu servidor dev para um host remoto)
ssh -R 8080:localhost:3000 user@server

# Encaminhamento dinamico (proxy SOCKS)
ssh -D 1080 user@server

Próximas Leituras