The debate of Cloudflare Tunnel vs port forwarding comes down to a single question: should you punch inbound holes in your firewall to reach a service, or let an outbound-only daemon do the work while every port stays closed? For UK developers, sysadmins and self-hosters running a VPS, that choice shapes how exposed your origin server is to scanners, brute-force bots and DDoS traffic. This guide breaks down how each works, the security trade-offs, and how to set up a Zero-Trust tunnel step by step.
What Is Port Forwarding?
Port forwarding is the traditional way to make a service on your VPS reachable from the public internet. You open an inbound port on the server firewall (and, on a home network, forward it through your router) so that traffic arriving on that port is delivered to the application listening behind it. Want a web app reachable? You open ports 80 and 443. Need remote administration? You expose 22 for SSH or 3389 for RDP. The service then answers directly on your server’s public IP address.
It is simple, universal and works with any protocol, which is why it has been the default for decades. The catch is real: the moment a port is open to the world, your origin IP is exposed and automated scanners find it within minutes. Open SSH and RDP ports are hammered by relentless brute-force login attempts, and because clients connect straight to your box, you are also a direct DDoS target.
Port forwarding can be done responsibly, but it demands ongoing hardening: a strict firewall, tools such as fail2ban or CrowdSec, key-only authentication and constant patching. If you go this route, our guide to hardening SSH on a Linux VPS is essential reading.
What Is a Cloudflare Tunnel?
A Cloudflare Tunnel takes the opposite approach. Instead of opening inbound ports, you run a lightweight daemon called cloudflared on your VPS. That daemon makes only outbound connections to Cloudflare’s global edge network and holds them open. When a visitor requests your app, Cloudflare accepts the request at its edge and hands it back down the existing tunnel to cloudflared, which forwards it to the local service. Cloudflare effectively becomes a secure reverse proxy in front of your origin.
Because every connection is initiated from your server outward, you can close all inbound ports entirely. There is nothing for an attacker to port-scan and no public listener to brute-force. Your origin IP never appears in DNS, so it stays hidden behind Cloudflare’s addresses, shrinking your attack surface to almost nothing. The tunnel is available on Cloudflare’s free tier; the only real prerequisite is having your domain on Cloudflare.
This model pairs naturally with Cloudflare’s wider security stack, from its CDN to its firewall. If you already use Cloudflare for caching, our walkthrough on setting up the Cloudflare CDN for WordPress covers the DNS and proxy basics a tunnel builds upon.
Cloudflare Tunnel vs Port Forwarding
Both methods get traffic to your service, but they expose you very differently. Port forwarding trades convenience for a permanently open front door, while a tunnel trades a Cloudflare dependency for a fully closed one. The table below summarises where they diverge.
Cloudflare Tunnel vs Port Forwarding at a Glance
| Factor | Port Forwarding | Cloudflare Tunnel |
|---|---|---|
| Inbound ports | Open (80/443/22/3389…) | None required |
| Origin IP | Publicly exposed | Hidden behind Cloudflare |
| Attack surface | Large; continuously scanned | Minimal; nothing to scan |
| Brute-force exposure | Direct on open services | Blocked at the edge |
| DDoS exposure | Direct target | Absorbed by Cloudflare |
| Protocol support | Any TCP/UDP protocol | HTTP/S first; TCP/UDP via WARP/Spectrum |
| Setup effort | Low, but heavy hardening | Moderate one-off setup |
| External dependency | None | Cloudflare account and domain |
The headline in any Cloudflare Tunnel vs port forwarding comparison is exposure. Port forwarding keeps a listener open to the entire internet; a tunnel keeps everything closed and lets Cloudflare filter, absorb and authenticate traffic before it ever reaches you. The cost is a reliance on Cloudflare and a proxy that is built primarily for web protocols.
Why Zero-Trust Access Matters
Closing your ports is only half the story. Once traffic reaches a service, who is allowed to use it? The traditional model assumed anyone inside the network perimeter could be trusted. Zero-Trust discards that assumption entirely: “never trust, always verify.” Every request must prove who it is, regardless of where it comes from.
Cloudflare Access applies this principle by placing identity-based policies in front of your applications. Before a user can even see a login page for an admin dashboard, internal tool or SSH endpoint, they must satisfy a policy: a one-time email code, Google or GitHub SSO, or membership of an allow-list. This is transformative for sensitive endpoints, because the usual first line of attack, hammering a public login form, is removed. There is no exposed login to brute-force in the first place.
Combined with a tunnel, Zero-Trust means an attacker faces no open port, no visible origin IP, and no reachable login without passing identity verification. That layered posture is far stronger than a hardened-but-open server on its own.
How to Set Up a Cloudflare Tunnel
Setting up a tunnel takes a handful of commands on your UK VPS. The full reference lives in the official Cloudflare Tunnel documentation, but the core flow is straightforward. First, make sure your domain is added to Cloudflare and its nameservers are active.
Install cloudflared from Cloudflare’s repository, then authenticate it against your account:
# Install cloudflared (Debian/Ubuntu)
curl -L https://pkg.cloudflare.com/cloudflare-main.gpg
| sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg]
https://pkg.cloudflare.com/cloudflared any main"
| sudo tee /etc/apt/sources.list.d/cloudflared.list
sudo apt update && sudo apt install cloudflared
# Authenticate and create the tunnel
cloudflared tunnel login
cloudflared tunnel create my-tunnel
Next, tell the tunnel which local service each hostname maps to using ingress rules in a config.yml:
# ~/.cloudflared/config.yml
tunnel: my-tunnel
credentials-file: /root/.cloudflared/<TUNNEL-ID>.json
ingress:
- hostname: app.example.com
service: http://localhost:8080
- hostname: dash.example.com
service: http://localhost:3000
- service: http_status:404
Point DNS at the tunnel and install it as a system service so it starts on boot:
cloudflared tunnel route dns my-tunnel app.example.com
cloudflared tunnel route dns my-tunnel dash.example.com
sudo cloudflared service install
With the tunnel proxying traffic, you can now remove every inbound rule you no longer need. Set the firewall to deny incoming by default and let cloudflared’s outbound connection do the rest:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable
How to Protect Access with Zero-Trust Policies
A tunnel hides your service; a Zero-Trust policy decides who may use it. In the Cloudflare Zero Trust dashboard, create an Access application for a hostname such as dash.example.com, then attach a policy that defines who is allowed in.
- Identity providers: require Google, GitHub, Microsoft or one-time email PIN before the app loads.
- Allow-lists: restrict access to specific email addresses, domains or country locations.
- Device posture: insist on the WARP client or a valid certificate for higher-risk tools.
- SSH in the browser: expose SSH through Access so administrators authenticate with identity rather than an open port 22.
Keep policies least-privilege: grant each person only the apps they genuinely need, and prefer short session lifetimes for admin tooling. This turns a public dashboard into an invitation-only one without touching the application’s own code.
When to Use Each Approach
When a Cloudflare Tunnel Wins
Reach for a tunnel when you are exposing web apps, admin dashboards, APIs or self-hosted home-lab services over HTTP/S. It is ideal whenever hiding your origin IP matters, when you want DDoS absorption for free, or when you would rather not maintain a hand-tuned inbound firewall. For most modern web workloads on a VPS, a tunnel plus Access is the stronger default.
When Port Forwarding Still Makes Sense
Port forwarding remains the right tool for services Cloudflare’s proxy is not designed to handle. The free proxy is HTTP/S-oriented; arbitrary TCP and UDP need WARP or the paid Spectrum product. Mail servers are the clearest example, as SMTP should not be routed through the HTTP proxy and needs its own reachable IP and reputation. You might also prefer port forwarding when you deliberately want no third-party dependency, or for large media streaming where a proxied path adds caveats. In those cases, open only what you must and harden aggressively.
Best Practices for Securing Your VPS
Whichever method you choose, a tunnel is a layer of defence, not a replacement for good server hygiene. You still own the operating system underneath, so the fundamentals matter.
- Write least-privilege ingress rules and end your
config.ymlwith a catch-allhttp_status:404. - Close every unused inbound port with a default-deny firewall policy.
- Keep cloudflared updated so you receive edge and security fixes promptly.
- Combine the tunnel with Cloudflare Access policies rather than relying on obscurity alone.
- Continue to harden the OS and SSH, following a full Linux server hardening checklist.
- Monitor logs and traffic, and layer in DDoS protection and a web application firewall as needed.
A UK VPS from UK Speed gives you a low-latency origin and full root access to run cloudflared, tighten the firewall and manage your own Zero-Trust posture. How much maintenance you take on is worth weighing when choosing between managed and unmanaged VPS hosting.
Conclusion
In the Cloudflare Tunnel vs port forwarding decision, the tunnel wins on security for most web-facing workloads: no open ports, a hidden origin IP and DDoS absorbed at the edge. Port forwarding still earns its place for non-HTTP services, mail and cases where you want zero third-party dependency. The best posture often combines both mindsets: close what you can, and harden whatever must stay open.
What to do next:
- Audit your VPS for any currently open inbound ports.
- Install cloudflared and move web apps and dashboards behind a tunnel.
- Add Cloudflare Access policies to every admin and internal endpoint.
- Keep hardening the OS and SSH regardless of your chosen method.
