O encaminhamento de portas SSH é um daqueles recursos que as pessoas copiam do Stack Overflow, fazem funcionar uma vez e nunca entendem direito — então, na próxima vez em que precisam dele, voltam a adivinhar qual usar entre -L, -R e -D. As três flags não são difíceis; só têm nomes ruins. Aqui está o único modelo mental que as torna óbvias, um exemplo de cada uma e as flags e armadilhas que decidem se o túnel sobrevive à tarde.
A única pergunta que escolhe a flag
Todo túnel SSH abre uma porta de escuta em uma máquina e, discretamente, envia tudo o que chega nela para algum lugar alcançável a partir da outra máquina. Então a única pergunta é: qual lado abre a porta à qual você conecta?
-L(local) — a porta abre na sua máquina. Você conecta localmente; o tráfego sai pelo lado do servidor.-R(remoto) — a porta abre no servidor. Alguém conecta lá; o tráfego sai pelo seu lado.-D(dinâmico) — a porta abre na sua máquina, mas é um proxy SOCKS: o destino é decidido por conexão, não fixado de antemão.
Todo o resto é detalhe. Mantenha “qual lado abre a porta” na cabeça e você nunca mais vai pegar a flag errada.
Encaminhamento local (-L) — trazer um serviço remoto para o localhost
O mais comum. Um banco de dados, um painel interno, uma interface de métricas — algo vinculado a 127.0.0.1 no servidor, ou em uma máquina que só o servidor alcança. Você o quer no seu notebook como se fosse local.
ssh -L 5432:localhost:5432 deploy@db.example.com
Leia da esquerda para a direita: abra 5432 na minha máquina e encaminhe tudo o que chega para localhost:5432 como visto a partir do servidor. Agora psql -h 127.0.0.1 no seu notebook conversa com o Postgres do servidor (em inglês) — pela conexão SSH criptografada, sem expor o banco de dados à rede.
O host do meio é resolvido no lado do servidor, e é isso que torna o recurso poderoso:
# reach a database that only the bastion can see
ssh -L 5432:10.0.0.9:5432 deploy@bastion.example.com
Aqui 10.0.0.9 é um endereço privado que o seu notebook não consegue rotear — mas o bastion consegue. O túnel faz a ponte.
Encaminhamento remoto (-R) — expor a sua máquina ao lado do servidor
A imagem espelhada, e a que as pessoas acham invertida (ela tem o próprio mergulho — túneis SSH reversos). A porta abre no servidor; as conexões a ela voltam a sair na sua ponta. Dois usos clássicos:
# let the server (or its network) reach a dev server running on your laptop
ssh -R 8080:localhost:3000 deploy@app.example.com
Agora tudo que bate em localhost:8080 no servidor é encaminhado para localhost:3000 no seu notebook — útil para mostrar a um colega que está na máquina o seu trabalho em andamento, ou deixar um serviço remoto chamar de volta algo que só você está rodando.
Esse também é o truque para alcançar uma máquina presa atrás de NAT, sem acesso de entrada: faça com que ela abra um túnel reverso de saída até um servidor que você controla, e você conecta pelo servidor. A máquina que não consegue aceitar conexões faz a de saída, em vez disso.
Uma ressalva: por padrão o servidor vincula a porta encaminhada a localhost, então só o próprio servidor pode usá-la. Para deixar outras máquinas da rede do servidor a alcançarem, o sshd_config do servidor precisa de GatewayPorts yes (ou clientspecified) — uma configuração do lado do servidor, não algo que você possa forçar pelo cliente.
Encaminhamento dinâmico (-D) — um proxy SOCKS em uma flag
O -L encaminha para um único destino fixo. O -D abre, em vez disso, um proxy SOCKS, então o destino é escolhido por requisição:
ssh -D 1080 deploy@jump.example.com
Aponte o seu navegador (ou curl --socks5 127.0.0.1:1080) para 127.0.0.1:1080 e toda requisição é roteada a partir do servidor. É o jeito rápido de navegar por uma rede interna, testar como um serviço aparece a partir do IP de um datacenter, ou alcançar um punhado de hosts internos sem um -L para cada um.
As flags que o tornam utilizável
Um comando de túnel pelado também abre um shell que você não quer e morre no momento em que você o fecha. Na prática:
ssh -N -L 5432:localhost:5432 deploy@db.example.com
-N— não rode um comando remoto. Você só quer o túnel, não um shell.-f— joga o processo para segundo plano depois de conectar (use com o-N).-o ExitOnForwardFailure=yes— se a porta não puder ser vinculada (já em uso, permissão negada), falhe ruidosamente em vez de conectar assim mesmo e, em silêncio, não encaminhar nada.- Keepalives — um túnel de longa duração morre com os timeouts de ociosidade sem o
ServerAliveInterval 30. Acrescente-o ou o túnel cai no momento em que você para de usá-lo.
Torne-o permanente no ssh_config
Tudo o que você passaria com -L/-R/-D tem uma diretiva de configuração, então um host salvo carrega os próprios túneis:
Host db-tunnel
HostName db.example.com
User deploy
LocalForward 5432 localhost:5432
ServerAliveInterval 30
RequestTTY no
Agora ssh -N db-tunnel traz o banco de dados para 127.0.0.1:5432 sem flags para lembrar. RemoteForward e DynamicForward funcionam da mesma forma. (Mais sobre o próprio arquivo de configuração no guia do ~/.ssh/config (em inglês).)
Três armadilhas
- O endereço de bind importa.
-L 5432:...escuta apenas em127.0.0.1. Para deixar outros dispositivos da sua LAN usarem o túnel, prefixe um endereço de bind:-L 0.0.0.0:5432:...— e entenda que você acabou de expô-lo à sua rede local. - “Address already in use” significa que a porta local está ocupada (muitas vezes um túnel anterior que não encerrou). Escolha outra porta local ou mate o antigo; o
ExitOnForwardFailuretransforma a falha silenciosa em um erro que você de fato vai notar. - O host do meio é resolvido do lado de lá.
localhostem-L a:localhost:bsignifica o localhost do servidor, não o seu. Inverter isso é o erro mais comum de encaminhamento de portas.
Quando o túnel não vincula
Se o comando falha com bind: Address already in use ou bind: Permission denied, a porta de escuta nunca abriu — percorra a lista curta. Já em uso: algo segura a porta, muitas vezes o túnel esquecido de ontem — o ss -tlnp nomeia o processo, depois escolha outra porta ou mate o antigo. Permissão negada localmente normalmente significa uma porta privilegiada: qualquer coisa abaixo de 1024 precisa de root, então escute na 8443 em vez da 443. Na ponta remota (-R), o servidor tem veto: AllowTcpForwarding no no sshd_config bloqueia o encaminhamento por completo, e sem o GatewayPorts a porta de escuta remota vincula só a localhost, qualquer que seja o endereço de bind que você pediu. E em hosts endurecidos da família RHEL, o SELinux pode negar o bind ao sshd mesmo quando a configuração permite — confira o log de auditoria antes de culpar o seu comando.
Quando fazer malabarismo com túneis à mão cansa
O encaminhamento é uma ótima primitiva, e todo desenvolvedor deveria saber as três flags de cor. A fricção aparece depois: você mantém um rascunho de comandos ssh -N -L ... (em inglês), você os roda de novo depois de cada vez que o notebook dorme, você esquece qual porta local mapeia para qual serviço e não consegue dizer num relance se um túnel sequer continua de pé.
É aí que um cliente com um gerenciador de túneis de verdade ajuda. O Termalin mantém os encaminhamentos locais, remotos e dinâmicos presos ao host como configuração salva — inicie-os com um clique, veja quais estão ativos e deixe que se restabeleçam junto com a conexão, em vez de redigitar o comando. A mesma lista de hosts (com suas chaves, hosts de salto e keepalives) sincroniza entre as suas máquinas, criptografada de ponta a ponta, e cada servidor é verificado na primeira conexão. A linha de comando ensina como os túneis funcionam; um cliente evita que você os reconstrua à mão toda manhã.
De qualquer forma, o modelo é o truque inteiro: decida qual lado abre a porta, e o resto da flag se escreve sozinho.
O Termalin é um cliente SSH gratuito e multiplataforma, com túneis integrados, SFTP e um gerenciador de chaves — baixe o Termalin, ou veja como ele cuida das suas chaves com segurança.