Implementando Encaminhamento de Portas SSH Local e Remoto para Túneis
Desbloqueie acesso seguro à rede e atravesse firewalls usando encaminhamento de portas SSH. Este guia abrangente detalha a implementação prática das técnicas de tunelamento SSH Local (`-L`) e Remoto (`-R`). Aprenda a sintaxe essencial, entenda as principais diferenças entre acessar serviços remotos versus expor serviços locais e veja exemplos claros para tarefas como proteger conexões de banco de dados ou compartilhar ambientes de desenvolvimento. Inclui as melhores práticas críticas para criar túneis persistentes e seguros em segundo plano usando autenticação baseada em chave.
Implementando Encaminhamento de Portas SSH Local e Remoto para Túneis
O encaminhamento de portas SSH é uma daquelas ferramentas que você esquece até que um firewall, uma sub-rede privada ou uma rede estranha de fornecedor bloqueie o caminho simples. Então se torna a correção limpa mais rápida. Você pode usá-lo para alcançar um banco de dados através de um host bastião, testar uma página de administração privada do seu laptop ou expor um servidor de desenvolvimento local para uma máquina que não consegue alcançar seu laptop diretamente.
A ideia básica é simples: o SSH abre uma porta de escuta em um lado da conexão e transporta o tráfego através da sessão SSH criptografada para um destino do outro lado. A parte que confunde as pessoas é a direção. O encaminhamento local com -L permite que sua máquina alcance algo próximo ao servidor SSH. O encaminhamento remoto com -R permite que algo próximo ao servidor SSH alcance algo próximo à sua máquina.
Encaminhamento local: traga um serviço remoto para seu laptop
Use o encaminhamento local quando o serviço que você precisa estiver acessível a partir do servidor SSH, mas não da sua estação de trabalho.
ssh -L 15432:db.internal.example:5432 [email protected]
Após conectar, seu laptop escuta em 127.0.0.1:15432. Quando você aponta psql, DBeaver ou uma configuração de aplicativo para essa porta local, o SSH envia o tráfego para bastion.example.com, e o bastião abre uma conexão para db.internal.example:5432.
Leia o comando da esquerda para a direita:
porta local na minha máquina : host de destino visto pelo servidor SSH : porta de destino
Esse detalhe "visto pelo servidor SSH" é importante. Se o banco de dados for nomeado db.internal.example apenas dentro da rede privada, seu laptop não precisa resolver esse nome. O bastião o faz. Se o banco de dados escuta apenas em localhost no bastião, use isto:
ssh -L 15432:127.0.0.1:5432 [email protected]
O encaminhamento local geralmente é o padrão mais seguro porque a porta de escuta está na sua estação de trabalho. Por padrão, o OpenSSH vincula as portas encaminhadas localmente à interface de loopback, então outras máquinas na sua rede Wi-Fi ou de escritório não podem usar o túnel. Você pode ser explícito:
ssh -L 127.0.0.1:15432:db.internal.example:5432 [email protected]
Evite vincular a 0.0.0.0 a menos que você realmente queira compartilhar o túnel com outros hosts. Um comando como este transforma seu laptop em um proxy para o banco de dados privado para qualquer um que possa alcançar a porta 15432 no seu laptop:
ssh -L 0.0.0.0:15432:db.internal.example:5432 [email protected]
Isso pode ser útil em um laboratório. Raramente é o que você deseja em uma estação de trabalho normal.
Encaminhamento remoto: exponha um serviço local através do servidor
O encaminhamento remoto inverte o lado da escuta. Use-o quando um serviço estiver rodando na sua máquina, mas alguém ou algo próximo ao servidor SSH precisar alcançá-lo.
ssh -R 18080:127.0.0.1:3000 [email protected]
Isso pede que public.example.com escute na porta 18080. Conexões para essa porta são transportadas de volta através do SSH para 127.0.0.1:3000 no seu laptop. Isso é útil quando você está testando um receptor de webhook, compartilhando uma demonstração temporária ou depurando um callback de um sistema de staging que não pode chamar seu laptop diretamente.
Há uma surpresa comum: portas encaminhadas remotamente geralmente se vinculam ao loopback no servidor SSH por padrão. Isso significa que curl http://127.0.0.1:18080 funciona quando executado em public.example.com, mas http://public.example.com:18080 do seu navegador pode não funcionar.
Para tornar uma porta encaminhada remotamente acessível a partir de outras máquinas, o servidor SSH deve permitir isso. Em /etc/ssh/sshd_config, a configuração relevante é comumente:
GatewayPorts clientspecified
Então você pode solicitar um vínculo público:
ssh -R 0.0.0.0:18080:127.0.0.1:3000 [email protected]
Use isso com cuidado. Você está publicando um serviço local através do servidor. Coloque um firewall na frente dele, use uma porta alta aleatória e não exponha ferramentas de administração, bancos de dados de desenvolvimento ou aplicativos não autenticados à internet.
Mantenha os túneis estáveis e confiáveis
Para um túnel de longa duração, geralmente você não quer um shell no host remoto:
ssh -N -L 15432:db.internal.example:5432 [email protected]
-N significa "não execute um comando remoto". Adicione keepalives quando o túnel atravessar NAT, VPN ou balanceadores de carga em nuvem que descartam sessões TCP ociosas:
ssh -N \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-L 15432:db.internal.example:5432 \
[email protected]
Para uso não supervisionado, prefira um serviço systemd de usuário, autossh ou seu supervisor de processo em vez de um comando ssh -f puro. Colocar em segundo plano com -f funciona, mas torna falhas de inicialização e túneis obsoletos mais difíceis de notar.
ssh -fN -L 15432:db.internal.example:5432 [email protected]
Se você usar -fN, teste o mesmo comando sem -f primeiro. Solicitações de senha, solicitações de chave de host desconhecida e conflitos de porta são muito mais fáceis de diagnosticar em primeiro plano.
Lista de verificação de solução de problemas
Quando um túnel conecta, mas o aplicativo ainda falha, verifique cada salto em vez de adivinhar.
Primeiro, confirme se o ouvinte local existe:
ss -ltnp | grep 15432
Depois, teste o destino a partir do servidor SSH:
ssh [email protected] 'nc -vz db.internal.example 5432'
Se isso falhar, o encaminhamento SSH não é o problema. O bastião não consegue alcançar o serviço, o nome não resolve lá, um grupo de segurança bloqueia a porta ou o serviço está vinculado à interface errada.
Se o ouvinte não iniciar, a porta local pode já estar em uso:
lsof -iTCP:15432 -sTCP:LISTEN
Se o encaminhamento remoto falhar com uma mensagem como remote port forwarding failed, o servidor pode bloquear o encaminhamento TCP. Verifique AllowTcpForwarding em sshd_config e verifique se a porta solicitada já está ocupada.
Hábitos de segurança que valem a pena manter
Use autenticação baseada em chave e restrinja a conta usada para túneis. Para um usuário de túnel dedicado, você pode combinar acesso limitado ao shell, regras de firewall e opções SSH como PermitOpen ou PermitListen, dependendo da direção necessária. Esses controles impedem que um túnel de conveniência se transforme em amplo acesso à rede.
Nomeie os túneis em suas anotações ou runbooks pela intenção, não apenas pelo comando. "Laptop 15432 para réplica de relatórios de produção através do bastião" é mais fácil de auditar do que uma linha misteriosa ssh -L no histórico do shell.
O encaminhamento local ajuda você a alcançar para dentro. O encaminhamento remoto permite que outros alcancem de volta para você. Uma vez que essa distinção esteja clara, a maioria dos problemas de tunelamento SSH se torna uma questão de verificar qual lado escuta, qual lado resolve o destino e qual firewall está entre eles.
Alguns padrões reais que você verá
Um padrão comum de produção é o túnel de manutenção de banco de dados. Você tem uma réplica de relatórios em uma sub-rede privada, um host bastião com acesso SSH restrito e uma ferramenta de análise no seu laptop. O encaminhamento local se encaixa perfeitamente:
ssh -N -L 127.0.0.1:15432:reporting-db.internal:5432 [email protected]
O aplicativo no seu laptop deve usar 127.0.0.1, não o nome do host do banco de dados privado. Se a ferramenta insistir na verificação do nome do host SSL contra o host do banco de dados, você pode precisar conectar com o nome do host do banco de dados e adicionar uma entrada de hosts local, ou configurar o cliente com o modo SSL correto. O túnel apenas move bytes TCP; ele não reescreve detalhes do protocolo do banco de dados.
Outro padrão é um receptor de webhook temporário:
ssh -N -R 127.0.0.1:19090:127.0.0.1:9090 [email protected]
Nessa versão, a porta encaminhada é intencionalmente utilizável apenas a partir do próprio gateway. Você pode então configurar um serviço de staging no gateway para chamar http://127.0.0.1:19090/hook. Isso é mais seguro do que publicar a porta para toda a rede.
Para uma demonstração pública curta, use um vínculo público apenas após adicionar uma regra de firewall:
ssh -N -R 0.0.0.0:19090:127.0.0.1:3000 [email protected]
Em seguida, restrinja o gateway:
sudo ufw allow from 203.0.113.40 to any port 19090 proto tcp
Sem essa restrição, qualquer um que possa alcançar o gateway pode tentar o serviço encaminhado.
O que o tunelamento SSH não resolve
O encaminhamento SSH não substitui a autenticação do serviço. Se o banco de dados aceitar conexões locais sem senha, um túnel pode estender esse limite de confiança fraco mais longe do que o pretendido. Se um aplicativo de desenvolvimento local não tiver uma página de login, o encaminhamento remoto pode publicá-lo como está.
Também não torna um destino instável confiável. Se o bastião não conseguir resolver o nome interno, se o serviço estiver inativo ou se um grupo de segurança bloquear o caminho, o túnel ainda pode ser estabelecido com sucesso enquanto o aplicativo falha. É por isso que testar a partir do servidor SSH é tão útil.
Finalmente, os túneis são fáceis de esquecer. Um túnel obsoleto em um host de salto compartilhado pode deixar uma porta inesperada aberta. Para qualquer coisa de longa duração, coloque o comando em um arquivo de serviço com um nome claro, proprietário e política de reinicialização. Para qualquer coisa temporária, feche-o quando o trabalho estiver concluído e verifique se o ouvinte desapareceu com ss -ltnp.