SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-31

Cloudflare Tunnel sem portas abertas no VPS

Configure um tunnel nomeado, credenciais, regras ingress e systemd. Depois feche 80 e 443 e faça a aplicação escutar apenas em localhost.

O que o Cloudflare Tunnel faz e o que significa realmente não ter portas abertas

O Cloudflare Tunnel instala um pequeno daemon chamado cloudflared no seu VPS. Esse daemon abre uma ligação de saída para o Cloudflare e mantém-na aberta. Os pedidos para o seu hostname chegam à edge do Cloudflare e são encaminhados por essa ligação já existente. Assim, nada precisa de estabelecer uma ligação de entrada ao seu servidor.

O passo que a maioria dos guias nunca aborda: instalar o tunnel não fecha nenhuma porta. Se as portas 80 e 443 continuarem abertas na firewall e a sua aplicação continuar a escutar em 0.0.0.0, adicionou uma segunda forma de acesso em vez de substituir a primeira. O seu IP de origem continua acessível, e qualquer pessoa que o descubra passa diretamente ao lado do Cloudflare. Fechar essas portas é um passo manual. É esse passo que torna útil tudo o que foi configurado anteriormente.

cloudflared precisa de acesso de saída a region1.v2.argotunnel.com e region2.v2.argotunnel.com na porta 7844. Usa UDP para o protocolo QUIC e recorre a TCP para HTTP/2. Numa rede com filtragem de saída, permita ambos ou force o caminho TCP com --protocol http2.

Antes de começar

  • Um domínio já adicionado a uma conta Cloudflare, com os nameservers da Cloudflare a servirem a zona. cloudflared tunnel route dns escreve registos nessa zona, por isso a zona tem de existir primeiro.
  • Acesso de saída na porta 7844 a partir do VPS, por UDP e TCP.
  • Uma aplicação já à escuta localmente, mesmo que seja apenas python3 -m http.server 8080 para o primeiro teste.
  • sudo no servidor e uma segunda sessão SSH aberta antes de alterar a firewall.

Instalar cloudflared no Ubuntu ou Debian

A Cloudflare anexa um pacote .deb a cada versão cloudflared, por isso a instalação requer um download e uma chamada dpkg.

curl -fsSL -o /tmp/cloudflared.deb \
  https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i /tmp/cloudflared.deb
cloudflared --version

Execute dpkg --print-architecture primeiro se não tiver a certeza sobre a arquitetura do sistema. Em ARM de 64 bits, o nome do ficheiro termina em arm64 em vez de amd64, e nada mais muda. cloudflared --version apresentar uma string de versão é a única confirmação necessária antes de prosseguir.

Um pacote instalado desta forma fica fora do fluxo de atualizações do apt, por isso apt-get upgrade nunca o atualizará e a manutenção das atualizações passa a ser sua responsabilidade. sudo cloudflared update transfere a versão mais recente e substitui o binário no local; depois de o serviço existir, execute sudo systemctl restart cloudflared para que o processo em execução use o novo binário. Inclua este procedimento no mesmo calendário das restantes correções, porque um daemon de túnel é software exposto à Internet, mesmo que não abra nenhuma porta.

Faça login e crie um túnel nomeado

cloudflared tunnel login

Num VPS sem interface gráfica, não é aberto nenhum navegador. Copie o URL apresentado para o navegador do seu portátil e selecione a zona. Quando o processo terminar, ~/.cloudflared/cert.pem existirá.

cert.pem é a credencial da sua conta. Ela autoriza a criação de túneis, a gravação de registos DNS nessa zona e a eliminação de túneis. O túnel em execução nunca a utiliza. Trate-a como uma palavra-passe, porque uma cópia desse único ficheiro é suficiente para alguém publicar novos nomes de host no seu domínio.

cloudflared tunnel create homelab

Uma execução bem-sucedida apresenta as duas linhas abaixo. O UUID apresentado nessas linhas é o valor que irá copiar para o ficheiro de configuração.

Tunnel credentials written to /home/you/.cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json. cloudflared chose this file based on where your origin certificate was found. Keep this file secret. To revoke these credentials, delete the tunnel.
Created tunnel homelab with id 6ff42ae2-765d-4adf-8112-31c55c1551ef

Esse ficheiro JSON é a identidade do túnel e é a única credencial de que o serviço em execução precisa. Qualquer pessoa que o possua pode registar-se como o seu túnel e receber o seu tráfego. Não é possível fazer a rotação dessa credencial isoladamente: revogá-la significa cloudflared tunnel delete homelab e criar um novo túnel.

Mantenha o ficheiro de credenciais num local adequado

O serviço é executado como root. Por isso, coloque o ficheiro num diretório pertencente a root, em vez de o deixar num diretório pessoal ao qual uma tarefa de backup ou uma conta de login partilhada possa aceder.

sudo install -d -m 700 -o root -g root /etc/cloudflared
sudo install -m 600 -o root -g root \
  ~/.cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json \
  /etc/cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json
rm ~/.cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json
sudo ls -l /etc/cloudflared
cloudflared tunnel list

ls -l deve mostrar -rw------- root root no ficheiro JSON. cloudflared tunnel listcert.pem, por isso continua a funcionar. O comando deve mostrar o nome do túnel, o respetivo UUID e o número de ligações que mantém atualmente.

Escreva config.yml com regras de ingress reais

Escreva a configuração em /etc/cloudflared/config.yml, não no seu diretório pessoal. O motivo é o seguinte. cloudflared service install copia qualquer configuração que encontre para /etc/cloudflared/config.yml e depois fixa --config /etc/cloudflared/config.yml na unidade systemd. Se criar o ficheiro em ~/.cloudflared/config.yml, essa cópia será apenas um instantâneo único. Todas as edições posteriores da cópia no diretório pessoal não terão efeito, o serviço continuará a servir as regras antigas e nada emitirá um aviso. Criar o ficheiro diretamente no local correto elimina todo o problema.

tunnel: 6ff42ae2-765d-4adf-8112-31c55c1551ef
credentials-file: /etc/cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json
loglevel: info

ingress:
  - hostname: app.example.com
    service: http://127.0.0.1:8080
  - hostname: files.example.com
    service: http://127.0.0.1:8081
  - hostname: grafana.example.com
    path: ^/api/
    service: http://127.0.0.1:3000
  - service: http_status:404

As regras são lidas de cima para baixo, e a primeira correspondência vence. Uma regra sem hostname corresponde a qualquer nome de host, por isso a regra abrangente tem de ficar no fim. Se a omitir, a configuração será rejeitada com The last ingress rule must match all URLs (i.e. it should not have a hostname or path filter). http_status:404 é um serviço integrado que responde com 404 e não faz mais nada. A sua presença é necessária: sem ele, um pedido para um nome de host que nunca pretendeu publicar passa para a regra real que estiver por acaso no fim.

Use 127.0.0.1 no URL de service: em vez de localhost. No Ubuntu, localhost resolve primeiro para ::1, e uma aplicação ligada apenas ao loopback IPv4 recusa essa ligação. A linha do log é dial tcp [::1]:8080: connect: connection refused e o visitante recebe um 502.

O http:// simples está correto neste caso porque o salto não sai da máquina. Use https:// apenas quando a aplicação local exigir TLS (transport layer security) e espere x509: certificate is valid for example.com, not localhost quando o respetivo certificado não corresponder ao nome utilizado na ligação. Corrija isso com originServerName em originRequest ou aceite o risco com noTLSVerify: true.

Verifique as regras antes de iniciar qualquer serviço:

sudo cloudflared --config /etc/cloudflared/config.yml tunnel ingress validate
sudo cloudflared --config /etc/cloudflared/config.yml tunnel ingress rule https://app.example.com/login

ingress validate indica se a configuração é válida ou identifica a regra que a invalidou. ingress rule recebe um URL e mostra a primeira regra que corresponde a esse URL. Esta é a forma mais rápida de confirmar que uma expressão regular path não corresponde ao que esperava.

Aponte o DNS para o túnel

cloudflared tunnel route dns homelab app.example.com
cloudflared tunnel route dns homelab files.example.com
cloudflared tunnel route dns homelab grafana.example.com

Cada chamada cria um registo CNAME com proxy ativado, apontado para 6ff42ae2-765d-4adf-8112-31c55c1551ef.cfargotunnel.com. Esse destino só é resolvido dentro da rede da Cloudflare. Por isso, a resposta DNS pública do seu nome de host contém um endereço da Cloudflare e o IP do seu VPS nunca aparece nela. Um curinga hostname em config.yml continua a exigir um registo DNS correspondente para cada nome que utilizar efetivamente.

Quando já existe um registo, o comando falha da seguinte forma:

Failed to add route: code: 1003, reason: Failed to create record app.example.com with err An A, AAAA, or CNAME record with that host already exists.

Esse registo existente é quase sempre o antigo registo A apontado para o IP público do seu VPS. É precisamente esse registo que pretende remover. Elimine-o no painel da Cloudflare e execute o comando novamente. Se o deixar no lugar, o DNS continuará a publicar o IP de origem e o túnel não ocultará nada.

Instale-o como um serviço para que continue ativo após um reboot

Execute-o uma vez em primeiro plano, porque é muito mais fácil ler um erro no seu próprio terminal do que no journal.

sudo cloudflared --config /etc/cloudflared/config.yml tunnel run homelab

Um arranque normal regista várias linhas Registered tunnel connection, uma por localização de edge, cada uma com o seu próprio connIndex. Abra um dos seus nomes de host num browser e confirme se as regras de ingress o encaminham para o destino esperado. Depois, pare-o com Ctrl-C.

sudo cloudflared --config /etc/cloudflared/config.yml service install
systemctl status cloudflared

Isto grava /etc/systemd/system/cloudflared.service juntamente com cloudflared-update.service e cloudflared-update.timer. Depois, executa systemctl enable cloudflared.service e systemctl start cloudflared.service por si. enable é a parte relevante aqui, porque é o que repõe o túnel depois de um reboot. O ExecStart da unidade é cloudflared --no-autoupdate --config /etc/cloudflared/config.yml tunnel run. Por isso, esse caminho de configuração não pode ser alterado.

Há três falhas possíveis nesta etapa, com mensagens exatas. possible conflicting configuration in /home/you/.cloudflared/config.yml and /etc/cloudflared/config.yml significa que os dois ficheiros existem e que o cloudflared se recusa a escolher: apague o ficheiro que não pretende usar. configuration file ... must contain entries for the tunnel to run and its associated credentials (tunnel: TUNNEL-UUID, credentials-file: CREDENTIALS-FILE) significa que a configuração usa a abreviatura rápida url: em vez das chaves do túnel nomeado. Essa abreviatura não pode ser executada como serviço. cloudflared service is already installed significa que ainda existe uma unidade antiga. Nesse caso, execute primeiro sudo cloudflared service uninstall.

Não existe reload. Depois de editar /etc/cloudflared/config.yml, execute sudo systemctl restart cloudflared. Em seguida, confirme a afirmação sobre o reboot em vez de a assumir:

sudo reboot
# once it is back
systemctl is-enabled cloudflared
systemctl is-active cloudflared
journalctl -u cloudflared -n 50 --no-pager
curl -sI https://app.example.com

A apresentação de enabled por is-enabled e de active por is-active é o objetivo desta secção. Depois de as rotas existirem e de o serviço estar em execução, cert.pem já não tem outra função no servidor: rm ~/.cloudflared/cert.pem. Para adicionar um nome de host mais tarde, basta executar novamente cloudflared tunnel login.

Feche as portas 80 e 443, ou o túnel será apenas um caminho adicional

São necessárias duas alterações, e ambas devem ser feitas. Fazer apenas uma deixa a origem acessível.

Primeiro, associe a aplicação ao endereço de loopback. No nginx, isso significa usar listen 127.0.0.1:8080; em vez de listen 80;, como explicado em esta explicação da configuração de reverse proxy do nginx. No Docker Compose, isso significa ports: - "127.0.0.1:8080:80". A forma simples "8080:80" publica em todas as interfaces, e o Docker escreve as próprias regras de NAT (network address translation), que os pacotes encontram antes de o ufw os processar. Por isso, uma regra deny do ufw não o impedirá. Esta armadilha é explicada em por que as portas publicadas pelo Docker ignoram o ufw.

sudo ss -lntp

Cada serviço que moveu deve agora apresentar 127.0.0.1:8080 na coluna Local Address. Uma linha com 0.0.0.0:8080 ou *:8080 continua a aceitar ligações de qualquer origem.

Em segundo lugar, feche as portas.

sudo ufw status numbered
sudo ufw delete allow 'Nginx Full'
sudo ufw status

Elimine as regras allow para 80 e 443 em vez de adicionar regras deny por cima delas, porque o ufw para na primeira regra correspondente e uma regra allow antiga, colocada mais acima na lista, terá precedência. Mantenha a regra de SSH. O guia básico da firewall ufw explica o restante desse conjunto de regras. A maioria dos fornecedores de VPS também executa uma firewall de rede separada no painel de controlo. Essa firewall não é o ufw, por isso feche também as portas 80 e 443 nela.

Verifique agora a partir de outro local, porque curl http://127.0.0.1:8080 no próprio servidor não prova nada sobre o acesso a partir do exterior.

# run these from a different machine
nc -vz 203.0.113.10 443
curl -sI https://app.example.com

Um nc recusado ou expirado contra o IP direto, juntamente com um 200 através do nome de anfitrião, é o resultado pretendido. Como verificar se uma porta está realmente aberta apresenta outras formas de fazer este teste.

O túnel fornece transporte, não autenticação. Tudo o que publicar através dele ficará acessível publicamente, a menos que coloque um início de sessão à frente: Cloudflare Access na extremidade ou um proxy OAuth2 à frente da aplicação no servidor. O SSH também precisa de uma solução própria, porque o túnel não o cobre: mantenha a porta 22 aberta, mas restrita aos seus próprios endereços de origem.

O que o Cloudflare Tunnel oferece e quais são os custos

Os benefícios são concretos. O IP de origem deixa de ser publicado, nenhuma porta de entrada fica exposta, a configuração funciona numa máquina sem qualquer IP público, e o certificado público passa a ser responsabilidade da Cloudflare. Assim, nenhum cliente ACME (ambiente de gestão automática de certificados) precisa de ser executado no seu servidor. Os ataques volumétricos são absorvidos na edge, em vez de consumirem o limite da sua largura de banda.

Os custos também são concretos. A Cloudflare termina o TLS na sua edge: o pedido do visitante é desencriptado nesse ponto e novamente encriptado para entrar no túnel. Por isso, a Cloudflare consegue ler o tráfego. É isso que permite usar a firewall, a cache e as regras do Access. Nenhuma definição desativa esse comportamento enquanto continuar a usar o proxy da Cloudflare. Se for inaceitável que um terceiro tenha acesso ao texto simples, pare aqui e escolha outra solução.

A Cloudflare também passa a ser uma dependência obrigatória para a acessibilidade. Quando cloudflared não está ligado, os visitantes recebem a página de erro 1033 da Cloudflare em vez da sua aplicação. Além disso, elimina deliberadamente a rota direta que poderia servir como alternativa.

A partir de um navegador comum, só HTTP, HTTPS e WebSocket conseguem chegar a um hostname público. Qualquer outro protocolo TCP, como SSH, RDP (protocolo de ambiente de trabalho remoto) ou um servidor de jogos, também precisa de software no lado do cliente: cloudflared access tcp para encaminhar uma porta local ou o cliente WARP. Não existe uma alternativa sem cliente para esses protocolos.

Os corpos dos pedidos têm um limite na edge, e um upload que ultrapasse esse limite é rejeitado com HTTP 413 antes de chegar à aplicação. Em agosto de 2026, esse limite é de 100 MB nos planos Free e Pro e superior nos planos pagos. Consulte a página atual de limites da Cloudflare antes de basear o projeto num valor específico. Os termos de autoatendimento da Cloudflare também restringem o uso do proxy principalmente para servir vídeo e outros ficheiros grandes que não sejam HTML. Leia esses termos antes de apontar uma biblioteca multimédia para um tunnel gratuito.

Cloudflare Tunnel, um túnel SSH reverso ou o Tailscale Funnel

Todos os três funcionam apenas com ligações de saída. Por isso, todos funcionam num servidor sem portas de entrada e sem um IP público. A diferença está em quem tem acesso ao texto não cifrado e no hostname que fica visível para o público.

Um túnel SSH reverso precisa de uma segunda máquina com um IP público. Essa máquina torna-se a porta de entrada: o certificado, o reverse proxy e a firewall dessa máquina ficam sob a sua gestão. Nenhuma entidade externa desencripta os dados. A configuração tem mais componentes e precisa de autossh ou de uma unidade systemd com Restart=always para continuar a funcionar depois de uma interrupção breve da rede. O guia do túnel SSH reverso para CGNAT explica essa configuração.

O Tailscale Funnel é a comparação mais próxima. Também funciona apenas com ligações de saída, e o TLS termina na sua própria máquina. Por isso, os relays do Tailscale nunca veem o texto não cifrado. A limitação está nos nomes e nas portas: o Funnel serve apenas nomes no domínio ts.net da sua tailnet e apenas nas portas 443, 8443 e 10000. A diferença entre Tailscale Serve e Funnel explica ambos os lados.

Escolha com base na limitação que realmente condiciona a solução. Escolha o Cloudflare Tunnel quando o público tiver de aceder ao seu próprio domínio e aceitar que o Cloudflare leia o tráfego. Escolha o Tailscale Funnel quando um hostname ts.net for aceitável e não quiser entregar o texto não cifrado a um proxy. Escolha um túnel SSH reverso quando já tiver um servidor público e não quiser qualquer entidade externa no caminho.

FAQ

Ainda preciso de ter a porta 443 aberta com o Cloudflare Tunnel?

Não. cloudflared estabelece uma ligação de saída para o Cloudflare na porta 7844, e todos os pedidos regressam por essa ligação. Por isso, não é usada nenhuma porta de entrada. No entanto, a instalação do tunnel não fecha nada por si só. Elimine as regras que permitem as portas 80 e 443 no ufw, feche-as na firewall de rede separada do seu fornecedor, associe a aplicação a 127.0.0.1 e elimine qualquer registo A restante que ainda publique o IP do seu VPS. Confirme com sudo ss -lntp no servidor e com nc -vz <your-ip> 443 a partir de outra máquina.

Porque é que o meu hostname mostra o erro 1033 do Cloudflare?

O erro 1033 significa que o Cloudflare mantém o registo DNS desse hostname, mas não encontra nenhum cloudflared saudável e ligado para receber o pedido. O processo pode estar parado ou pode estar a executar sem conseguir contactar o Cloudflare. Verifique systemctl status cloudflared e journalctl -u cloudflared -n 50. Depois, confirme que a porta de saída 7844 está permitida para UDP e TCP, porque uma firewall que bloqueia UDP e QUIC sem permitir o fallback para TCP produz exatamente este resultado. cloudflared tunnel info homelab mostra as ligações que o Cloudflare vê atualmente. Uma lista vazia indica que o problema está do seu lado.

Porque é que recebo um erro 502 Bad Gateway através do tunnel?

Um erro 502 significa que cloudflared foi alcançado, mas não conseguiu alcançar o seu serviço local. Por isso, o problema está entre esses dois pontos e não no Cloudflare. Leia o log. dial tcp [::1]:8080: connect: connection refused significa que não existe nenhum processo a escutar no endereço indicado. O [::1] nessa mensagem normalmente significa que escreveu localhost no URL de service:, enquanto a aplicação está associada apenas a IPv4. Nesse caso, escreva http://127.0.0.1:8080. HTTP/1.x transport connection broken: malformed HTTP response é o caso inverso: escreveu https:// numa origem que comunica através de HTTP simples.

Posso executar SSH, RDP ou um servidor de jogos através do Cloudflare Tunnel?

Não com um cliente simples. Um hostname público através de um tunnel transporta HTTP, HTTPS e WebSocket, que são os protocolos usados por um browser. Qualquer outro protocolo TCP também requer software na máquina cliente, seja cloudflared access tcp para encaminhar uma porta local, seja o cliente WARP. Se quiser usar SSH a partir de qualquer máquina sem instalar nada, o tunnel não é a ferramenta adequada. Mantenha a porta 22 aberta e restrita pelo endereço de origem.

O Cloudflare vê o meu tráfego através do tunnel?

Sim. O Cloudflare termina o TLS na sua edge, desencripta o pedido nesse ponto e volta a encriptá-lo no tunnel até ao seu servidor. Essa desencriptação permite que a firewall, a cache e as políticas do Access funcionem. Também significa que os dados em texto simples existem nas máquinas do Cloudflare. Não existe nenhuma configuração que evite isso enquanto utilizar o proxy deles. Se isso for inaceitável, use o Tailscale Funnel ou execute o seu próprio reverse proxy num servidor público.

#cloudflare-tunnel#cloudflared#zero-trust#firewall#self-hosting