SSH sem porta 22 aberta: Cloudflare Tunnel e ProxyJump
O fail2ban não deu conta dos bots na porta 22. O que resolveu foi tirar o SSH da internet: entrada pelo Cloudflare Tunnel e ProxyJump para o resto.
- Publicado
- Leitura
- 5 min

Quem deixa a porta 22 aberta para a internet conhece a cena: o log de autenticação enche de tentativas de login vindas do mundo inteiro, o tempo todo. Eu sofri bastante com isso. Instalei o fail2ban, coloquei uma aplicação para monitorar os acessos e gerar relatórios dos bloqueios, e mesmo assim os bots continuavam batendo.
O que resolveu de verdade não foi bloquear melhor, foi parar de expor a porta. Hoje o meu SSH entra só pelo Cloudflare Tunnel e, de lá, eu pulo para as outras máquinas com ProxyJump. Neste post mostro como montar esse esquema.
Por que o fail2ban não basta #
O fail2ban lê os logs e bane, no firewall, os IPs que erram a senha várias vezes. Ele funciona e ajuda, mas tem um limite: ele reage a ataques que já estão chegando. Com a porta aberta, cada IP novo tem direito a algumas tentativas antes do banimento, e existem muitos IPs novos.
A solução mais limpa é não ter porta nenhuma para o bot encontrar.
Como fica o desenho #
O caminho de um acesso meu, de fora de casa, fica assim:
- O meu notebook chama
sshnormalmente. - Um
ProxyCommandno~/.ssh/configfaz ocloudflaredlevar a conexão até a Cloudflare. - A Cloudflare entrega a conexão pelo tunnel ao
cloudflaredque roda num container LXC no meu Proxmox. - O
cloudflaredrepassa para a porta 22 do jump server, a única máquina que recebe SSH de fora. - Do jump server, o
ProxyJumpme leva a qualquer outro container da rede.
Como o tunnel é uma conexão de saída do meu homelab para a Cloudflare, não preciso de nenhum redirecionamento de porta no roteador. Para quem varre a internet atrás da porta 22, o meu IP simplesmente não tem SSH.

Lado do servidor: a rota no tunnel #
Considerando que você já tem um Cloudflare Tunnel funcionando, o passo é publicar o SSH como uma rota. Segundo a documentação da Cloudflare, no painel:
- Abra o tunnel em Networking > Tunnels e vá na aba Routes.
- Clique em Add route e escolha Published application.
- Defina um subdomínio, por exemplo
ssh.seudominio.com. - Em Service, escolha SSH e informe o destino. Use
localhost:22se ocloudflaredroda na mesma máquina do SSH, ouIP-do-servidor:22se roda em outra, como é o meu caso com ocloudflarednum container separado.
Lado do cliente: o ProxyCommand #
No computador de onde você acessa, instale o cloudflared e adicione ao ~/.ssh/config:
Host ssh.seudominio.com
ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h
O caminho do cloudflared muda conforme o sistema e o gerenciador de pacotes. Confira com which cloudflared.
A partir daí, ssh [email protected] funciona como qualquer SSH, só que passando pelo tunnel. Se a rota estiver protegida pelo Access, o cloudflared abre o navegador para você fazer login antes da sessão começar.
ProxyJump: um só ponto de entrada #
Com o jump server acessível pelo tunnel, não faz sentido publicar cada container. O OpenSSH resolve isso com ProxyJump: você pede para entrar numa máquina interna e ele passa primeiro pelo jump server, de forma transparente.
Um ~/.ssh/config nessa lógica fica assim (nomes e IPs são exemplos):
Host jump
HostName ssh.seudominio.com
User bruno
ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h
Host app-*
User root
ProxyJump jump
Host app-blog
HostName 192.168.1.50
Com isso, ssh app-blog sai do meu notebook, atravessa o tunnel até o jump server e de lá chega ao container do blog, tudo num comando só. Para uma conexão pontual, o equivalente na linha de comando é ssh -J jump [email protected].
Esse desenho tem um bônus: toda conexão externa passa pelo mesmo lugar. É no jump server que fica a monitoria de acessos, então tenho um único ponto para olhar.
Endurecendo o jump server #
Mesmo escondido, o ponto de entrada merece cuidado. No sshd_config do jump server, o básico é:
PasswordAuthentication no
PermitRootLogin no
Com chave SSH obrigatória e root bloqueado, mesmo alguém que chegue até o servidor precisa da sua chave privada. Depois de editar, valide a configuração antes de reiniciar, para não se trancar para fora:
sshd -t && systemctl reload ssh
Resumindo #
- O fail2ban reage; esconder a porta evita. Os dois podem conviver, mas a porta fechada resolve a raiz do problema.
- O Cloudflare Tunnel publica o SSH sem redirecionamento de porta no roteador.
- Proteja a rota com Cloudflare Access para exigir login antes do SSH.
- ProxyJump dá um único ponto de entrada para todas as máquinas internas.
- Chave obrigatória e root bloqueado no jump server.
Desde que o SSH passou a entrar só pelo tunnel, os bots sumiram do meu log. Não porque eu bloqueio melhor, mas porque não há mais nada para eles encontrarem.