Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

05 - Túnel SSH e Port Forwarding (Local, Remoto, Dinâmico)

video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

Túnel SSH e Port Forwarding (Local, Remoto, Dinâmico)

1. Definição

O Port Forwarding (redirecionamento de portas) é uma capacidade do SSH que permite encapsular tráfego TCP arbitrário dentro do canal cifrado SSH, criando um túnel entre dois pontos da rede. O SSH atua como um proxy encriptado, transportando o tráfere de uma porta local para uma porta remota (ou vice-versa), sem que aplicativos intermediários vejam o conteúdo. Há três modos principais:

  • Local (-L): expõe uma porta remota na máquina local do cliente.
  • Remoto (-R): expõe uma porta local do cliente em um servidor remoto.
  • Dinâmico (-D): cria um proxy SOCKS5 que encaminha tráfere arbitrário.

Definido na RFC 4254 (SSH Connection Protocol, seção 7), é um dos recursos mais poderosos e versáteis do SSH, frequentemente usado para acessar serviços internos, contornar firewalls restritivos, criar VPNs improvisadas e expor portas locais à internet pública sem roteamento.

Comparação Rápida

Modo Flag Direção Quem escuta Quem conecta ao destino
Local -L Cliente → Servidor Cliente (porta local) Servidor SSH
Remoto -R Servidor → Cliente Servidor SSH Cliente (máquina local)
Dinâmico -D Cliente → Servidor (SOCKS) Cliente (porta SOCKS) Servidor SSH

2. Port Forwarding Local (-L)

O modo local expõe um serviço remoto em uma porta local do cliente. O SSH cria um socket TCP escutando na porta local; toda conexão recebida é encapsulada via SSH e entregue a um host:porta visível a partir do servidor SSH.

Sintaxe

ssh -L [bind_local:]porta_local:host_destino:porta_destino user@servidor_ssh

Caso Clássico: Acessar Banco de Dados Remoto

Cenário: PostgreSQL em db.interno.com:5432, acessível apenas internamente. Operador fora da rede acessa via jumphost bastion.empresa.com:

ssh -L 5432:db.interno.com:5432 user@bastion.empresa.com
# Depois: psql -h 127.0.0.1 -p 5432 -U admin dbname
[Operador]              [bastion]              [db.interno.com]
  psql → 127.0.0.1:5432 ──SSH──> bastion ──TCP──> db:5432
              (cifrado)              (interno, em claro)

O tráfego entre operador e bastion é cifrado (SSH). O tráfego entre bastion e db.interno.com vai em claro na rede interna (rede confiável). Pode-se mapear múltiplas portas em uma conexão: ssh -L 5432:db:5432 -L 6379:redis:6379 bastion.

Bind Address Restritivo

Por padrão, -L escuta apenas em 127.0.0.1. Para expor à LAN do cliente, use 0.0.0.0 e habilite GatewayPorts yes no servidor:

ssh -L 0.0.0.0:5432:db.interno.com:5432 user@bastion.empresa.com

3. Port Forwarding Remoto (-R)

O modo remoto faz o inverso: expõe um serviço local do cliente em uma porta do servidor SSH. Útil para: expor serviço de casa para servidor na nuvem, acessar máquina atrás de NAT sem IP público, permitir que terceiros conectem a serviço local.

Sintaxe

ssh -R [bind_remoto:]porta_remota:host_local:porta_local user@servidor_ssh

Casos Práticos

# Expor servidor web local (porta 3000) para colega externo via nuvem
ssh -R 8080:localhost:3000 user@nuvem.exemplo.com
# Colega acessa: http://nuvem.exemplo.com:8080

# Reverse shell: máquina atrás de NAT abre túnel para suporte
ssh -R 2222:localhost:22 suporte@servidor-suporte.com -N
# Suporte conecta (no servidor-suporte): ssh usuario@localhost -p 2222

GatewayPorts no Servidor

Por padrão, -R escuta apenas em 127.0.0.1 do servidor. Para que terceiros acessem externamente, habilitar GatewayPorts clientspecified (ou yes) no sshd_config e o cliente usa 0.0.0.0:

ssh -R 0.0.0.0:8080:localhost:3000 user@nuvem.exemplo.com

4. Port Forwarding Dinâmico (-D) — Proxy SOCKS

O modo dinâmico cria um proxy SOCKS4/SOCKS5 na porta local do cliente. O SSH aceita conexões SOCKS, encapsula cada uma via canal SSH, e no servidor SSH abre conexão TCP ao destino solicitado dinamicamente pelo cliente SOCKS. Permite acessar múltiplos destinos sem configurar túneis individuais.

Sintaxe

ssh -D [bind_local:]porta_local user@servidor_ssh

Uso Prático

ssh -D 1080 -C -N user@servidor_ssh.com   # Proxy SOCKS5 na porta 1080
curl --socks5-hostname 127.0.0.1:1080 http://site-interno.empresa.com
export ALL_PROXY=socks5h://127.0.0.1:1080  # Para aplicativos Python/curl
# Firefox: about:config → network.proxy.socks_remote_dns = true

Vantagens e Limitações

  • Não precisa saber de antemão quais destinos acessar; DNS é resolvido no servidor (evita vazamento).
  • Funciona como VPN "leve" para aplicações que suportam SOCKS.
  • Limitação: apenas TCP (não UDP). Aplicações sem suporte nativo a SOCKS usam wrapper proxychains (proxychains nmap -sT host-interno).

5. Flags Complementares

Flag Função
-N Não executar shell remoto (apenas túnel)
-f Ir para background após autenticação
-T Desabilitar TTY (útil com -N)
-C Compressão zlib (bom para texto; ruim para já comprimido)
-g Permitir conexões de hosts remotos ao bind local
-o ExitOnForwardFailure=yes Abortar se túnel falhar
-o ServerAliveInterval=30 Keepalive a cada 30s
-o ServerAliveCountMax=3 3 falhas = desconexão
-o TCPKeepAlive=yes Manter TCP vivo

Exemplo canônico:

ssh -fN -L 5432:db:5432 -o ExitOnForwardFailure=yes \
    -o ServerAliveInterval=30 user@bastion

6. ProxyJump (Jump Host) — -J

Introduzido no OpenSSH 7.3 (2016), -J simplifica conexões via bastion. Em vez de túnel manual, o SSH conecta-se ao destino através do bastion automaticamente, sem expor portas locais.

ssh -J user@bastion.com user@host-interno.com

# Em ~/.ssh/config
Host interno
    HostName 10.0.0.50
    ProxyJump bastion.com
    User admin

Vantagens sobre -L manual: não cria túnel persistente, não expõe portas, usa SSH nativo para o salto, mantém agente local (mais seguro que ForwardAgent).

7. Manter Túnel Persistente (autossh)

Túneis SSH quebram com flutuações de rede. autossh monitora e reconecta automaticamente:

autossh -M 0 -fN -L 5432:db:5432 \
    -o "ServerAliveInterval=30" -o "ServerAliveCountMax=3" user@bastion

-M 0 desabilita monitoramento próprio do autossh (porta extra) e usa apenas ServerAlive*. Em produção, criar unit systemd com Restart=always e ExecStart=/usr/bin/autossh -M 0 -N -L 5432:db:5432 -o ServerAliveInterval=30 user@bastion.

8. Diagnóstico e Problemas Comuns

Sintoma Causa Solução
bind: Address already in use Porta local ocupada Trocar porta ou matar processo
remote port forwarding failed Porta remota em uso ou GatewayPorts=no Verificar GatewayPorts no servidor
Conexão cai após inatividade NAT/firewall dropa conexão idle ServerAliveInterval=30
DNS vaza no modo dinâmico Cliente resolve DNS localmente socks5h:// ou proxy_dns no Firefox
Permission denied (port forwarding) AllowTcpForwarding no no servidor Habilitar no sshd_config
ss -tnp | grep ssh        # Inspecionar túneis ativos
lsof -i -n -P | grep ssh  # Portas escutadas pelo cliente ssh

9. Boas Práticas e Segurança

Prática Recomendação
AllowTcpForwarding Habilitar apenas para usuários que precisam
PermitTunnel Manter no a menos que VPN sobre SSH seja necessária
Bind local Sempre 127.0.0.1, nunca 0.0.0.0 em estações compartilhadas
GatewayPorts clientspecified para controle fino
Chaves para túnel Chave dedicada com comando forçado (command="...")
Senha Desabilitar; só chave SSH
Logs LogLevel VERBOSE para auditoria

Em ~/.ssh/authorized_keys, restringir chave apenas a túnel remoto na porta 8080 sem shell:

command="echo tunnel-only",no-pty,no-X11-forwarding,permitlisten=8080 ssh-ed25519 AAAA...

10. Conclusão

O Port Forwarding é um dos recursos mais elegantes do SSH: com um único comando, transforma uma conexão cifrada em túnel TCP reversível, proxy SOCKS ou jump host. Dominar -L, -R e -D é essencial para engenheiros que precisam acessar infraestrutura interna, contornar restrições de firewall ou criar VPNs improvisadas. Para cenários produtivos, combinar com autossh (resiliência) e ProxyJump (simplicidade) é o padrão moderno. Em servidores expostos, restringir AllowTcpForwarding e usar chaves com comando forçado reduz o risco de abuso.