---
title: "O perigo de substituir o ngrok por SSH reverso sem isolar o Nginx"
author: "Pedro Dalben"
date: "2026-10-05T11:03:57Z"
category: "DevOps & Cloud"
reading_time: "6 min"
canonical: "https://pedrodalben.com.br/blog/o-perigo-de-substituir-o-ngrok-por-ssh-reverso-sem-isolar-o-nginx"
---

# O perigo de substituir o ngrok por SSH reverso sem isolar o Nginx

> Expor portas locais com SSH e Nginx parece elegante, mas abre brechas graves na sua VPS se você ignorar permissões de loopback e ciclo de vida.

**Autor:** Pedro Dalben (CTO no Integrar Plus)  
**Publicado em:** 05 de October de 2026  
**URL Canônica Oficial:** [https://pedrodalben.com.br/blog/o-perigo-de-substituir-o-ngrok-por-ssh-reverso-sem-isolar-o-nginx](https://pedrodalben.com.br/blog/o-perigo-de-substituir-o-ngrok-por-ssh-reverso-sem-isolar-o-nginx)  

---


Toda vez que uma equipe decide parar de pagar por serviços como ngrok ou Cloudflare Tunnels para expor ambientes locais, alguém sugere a mesma receita. A fórmula parece limpa: você pega uma VPS barata com IP público, coloca o Nginx na frente recebendo HTTPS e usa o comando `ssh -R` para encaminhar o tráfego direto para a porta do seu framework de desenvolvimento.

A ideia voltou ao debate público recentemente a partir de um artigo de Vincent Bernat sobre túneis HTTP usando ferramentas padrão do sistema operacional. Imediatamente a comunidade se dividiu em dois extremos previsíveis.

De um lado estão os puristas das redes domésticas que acham qualquer camada de túnel um exagero desnecessário. O argumento deles é que basta abrir portas 80 e 443 no roteador de casa, apontar um DNS dinâmico para o IP residencial e servir os arquivos diretamente. Do outro lado estão os defensores da infraestrutura moderna que sugerem adotar daemons especializados em túneis, como o projeto `sish`, ou protocolos experimentais ponto a ponto baseados em relays criptografados.

Eu discordo do primeiro grupo com veemência. Encaminhar portas no roteador de casa até a sua máquina de trabalho ignora a realidade de quem programa: redes com CGNAT onde você sequer recebe um IPv4 público válido, provedores que bloqueiam tráfego de entrada em portas baixas e a imprudência de colocar a máquina que contém suas chaves privadas e credenciais pessoais direto na linha de tiro da internet pública.

Ao mesmo tempo, instalar mais um binário intermediário em Go ou Rust na sua VPS apenas para gerenciar túneis adiciona dependência operacional que a maioria das equipes pequenas não quer manter. A abordagem de usar SSH e Nginx puros faz sentido na teoria, mas ela esconde armadilhas graves na implementação prática.

## O furo no loopback que ninguém nota

A configuração ingênua de um túnel SSH reverso com Nginx costuma mapear um subdomínio dinâmico para uma porta local na VPS. O Nginx faz o proxy reverso para `127.0.0.1:$porta`, enquanto o desenvolvedor roda na sua máquina pessoal algo como:

```bash
ssh -N -R 8080:localhost:3000 deploy@sua-vps.com
```

O problema começa quando o Nginx aceita qualquer valor arbitrário de porta via cabeçalho ou subdomínio, ou quando a configuração do proxy encaminha requisições indiscriminadamente para o loopback da VPS. Se você tem um PostgreSQL ouvindo em `127.0.0.1:5432`, um Redis em `127.0.0.1:6379` ou um daemon de monitoramento sem autenticação ouvindo em portas internas, um usuário externo mal-intencionado consegue varrer a sua VPS por dentro. 

O túnel, criado para receber webhooks do Stripe ou testar uma tela no celular, transforma o Nginx em uma ferramenta de exploração interna. O tráfego externo ultrapassa qualquer firewall UFW ou regras de iptables configuradas para bloquear conexões vindas da interface pública, porque para o sistema operacional a requisição nasce dentro do próprio host.

Para evitar isso, o Nginx não pode permitir mapeamentos dinâmicos livres. Cada porta de túnel precisa de um bloco de servidor rígido ou de uma validação estrita com mapa explícito:

```nginx
map $http_x_tunnel_token $backend_port {
    default 0;
    "dev-pedro-auth-9812" 8081;
    "dev-ana-auth-4321"   8082;
}

server {
    server_name ~^(?<subdomain>.+)\.tunnel\.seudominio\.com$;

    location / {
        if ($backend_port = 0) {
            return 403;
        }

        proxy_pass http://127.0.0.1:$backend_port;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
    }
}
```

Isso impede que alguém alterne portas para descobrir serviços internos rodando no servidor. Se a porta não estiver na lista permitida, a requisição é descartada antes de encostar na pilha TCP interna.

## O perigo da sessão abandonada

Outra fragilidade operacional comum é o ciclo de vida da conexão. Quando o desenvolvedor fecha a tampa do notebook ou cai o sinal de Wi-Fi, o processo do OpenSSH na VPS muitas vezes não encerra a conexão de imediato. A porta permanece presa no loopback do servidor por minutos até que os timeouts de keepalive identifiquem a perda de pacotes.

Se você tenta reconectar, o SSH falha com erro de porta já em uso. Pior ainda: se outra pessoa conectar logo em seguida com permissão de alocação de porta, ela pode herdar ou colidir com o túnel anterior, gerando roteamento incorreto de tráfego confidencial.

No arquivo `/etc/ssh/sshd_config` da VPS, ajustes agressivos de detecção de clientes mortos e restrições de permissão são indispensáveis:

```text
Match Group devtunnels
    AllowTcpForwarding remote
    GatewayPorts no
    X11Forwarding no
    AllowAgentForwarding no
    PermitTTY no
    ForceCommand /bin/false
    ClientAliveInterval 10
    ClientAliveCountMax 3
```

A linha `GatewayPorts no` impede que o usuário force o SSH a escutar em interfaces públicas como `0.0.0.0`, garantindo que o binding fique restrito a `127.0.0.1`. A combinação de `ClientAliveInterval 10` com `ClientAliveCountMax 3` derruba sessões zumbis em trinta segundos após a queda de rede do desenvolvedor, liberando a porta sem exigir reinicialização manual de serviços.

## Onde a solução quebra e quando não insistir

Montar essa estrutura atende perfeitamente à demanda de testar webhooks locais, integrar APIs de pagamento em desenvolvimento ou demonstrar uma funcionalidade temporária para colegas sem pagar mensalidade em dólar. Eu utilizo esse padrão para testes rápidos com aplicações Rails, mantendo o controle das chaves e do domínio.

Ainda assim, existem limites técnicos claros. Essa solução não oferece console web com replay de requisições HTTP, que ferramentas proprietárias entregam prontas. Se o seu fluxo de depuração depende de inspecionar payloads brutos de webhooks com interface gráfica e reenviar requisições com um clique, você terá que implementar o log no próprio Nginx ou usar middlewares na aplicação de desenvolvimento.

A manutenção manual do mapeamento de portas e chaves públicas também se torna insustentável quando o time cresce além de três ou quatro engenheiros. Nesse estágio, o tempo gasto gerenciando arquivos de configuração do Nginx e atribuindo portas não compensa a economia da assinatura de um serviço gerenciado.

A solução própria com SSH e Nginx é barata e funciona com utilitários estáveis que já existem no Linux há décadas. Ela só deixa de ser vantajosa quando o desenvolvedor a trata como mero truque de linha de comando, esquecendo que expor tráfego externo para a memória local de uma máquina é uma decisão de segurança de rede.

## Fontes

- [https://vincent.bernat.ch/en/blog/2026-http-over-ssh](https://vincent.bernat.ch/en/blog/2026-http-over-ssh)
