How to Allow HTTP/HTTPS From Cloudflare Only Using UFW
If your website uses Cloudflare, simply enabling the orange-cloud proxy does not necessarily mean attackers can only reach your server through Cloudflare.
If someone discovers your server's origin IP address, they may be able to connect directly to the server and bypass Cloudflare entirely. That can bypass protections you were relying on Cloudflare to provide, including its proxy layer, WAF rules, rate limiting, bot controls, and Layer 7 DDoS mitigation.
One way to harden the origin is to configure your server firewall so ports 80 (HTTP) and 443 (HTTPS) accept connections only from Cloudflare's network.
This tutorial uses UFW on Ubuntu.
Important: Cloudflare's published IP ranges can change. Before using the commands below, compare them against Cloudflare's current official list:
Cloudflare IP Ranges
Before You Start
This assumes:
- Your server runs Ubuntu
- UFW is installed and enabled
- Your website is actually proxied through Cloudflare
- You have SSH access
- You already have an SSH firewall rule so you don't lock yourself out
Check your current firewall:
sudo ufw status
You may see something like:
OpenSSH ALLOW IN Anywhere
Nginx Full ALLOW IN Anywhere
Nginx Full allows anyone on the Internet to connect directly to ports 80 and 443.
We're going to replace that broad web access with Cloudflare-only access.
Step 1 — Allow Cloudflare IPv4 Addresses
At the time this tutorial was written, Cloudflare publishes the following IPv4 ranges.
for ip in \
103.21.244.0/22 \
103.22.200.0/22 \
103.31.4.0/22 \
104.16.0.0/13 \
104.24.0.0/14 \
108.162.192.0/18 \
131.0.72.0/22 \
141.101.64.0/18 \
162.158.0.0/15 \
172.64.0.0/13 \
173.245.48.0/20 \
188.114.96.0/20 \
190.93.240.0/20 \
197.234.240.0/22 \
198.41.128.0/17
do
sudo ufw allow from "$ip" to any port 80 proto tcp
sudo ufw allow from "$ip" to any port 443 proto tcp
done
This creates separate rules allowing Cloudflare to reach HTTP and HTTPS.
Step 2 — Allow Cloudflare IPv6 Addresses
Don't forget IPv6.
for ip in \
2400:cb00::/32 \
2606:4700::/32 \
2803:f800::/32 \
2405:b500::/32 \
2405:8100::/32 \
2a06:98c0::/29 \
2c0f:f248::/32
do
sudo ufw allow from "$ip" to any port 80 proto tcp
sudo ufw allow from "$ip" to any port 443 proto tcp
done
Again, verify Cloudflare's current list before blindly copying these ranges.
Step 3 — Verify the New Rules BEFORE Removing Anything
Run:
sudo ufw status numbered
You should now see numerous rules resembling:
80/tcp ALLOW IN 103.21.244.0/22
443/tcp ALLOW IN 103.21.244.0/22
80/tcp ALLOW IN 103.22.200.0/22
443/tcp ALLOW IN 103.22.200.0/22
You should also see the IPv6 Cloudflare networks.
Do not remove your existing HTTP/HTTPS rule until you've confirmed the Cloudflare rules are present.
Step 4 — Remove Public HTTP/HTTPS Access
If you're using the standard UFW Nginx profile, you may currently have:
Nginx Full ALLOW IN Anywhere
Nginx Full ALLOW IN Anywhere (v6)
Once the Cloudflare rules are confirmed, remove the broad Nginx rule.
One way is:
sudo ufw delete allow 'Nginx Full'
Then check:
sudo ufw status
You want SSH to remain permitted, while ports 80 and 443 are allowed only from Cloudflare's networks.
Keep your existing SSH session open while making firewall changes. If you make a mistake, that existing connection may save you from locking yourself out.
Step 5 — Test Your Website
Visit your website normally through its Cloudflare-proxied domain.
Test several areas of the site, including logging in and any application/API functionality.
If everything is configured correctly, the path becomes:
Visitor
│
▼
Cloudflare
│
▼
UFW
│
├── Cloudflare → 80 ✓
├── Cloudflare → 443 ✓
│
└── Everyone else → 80/443 ✗
│
▼
Nginx/Apache
│
▼
Your Website
Why Is This Worth Doing?
Cloudflare is most useful when traffic is forced to pass through it.
Without origin protection, your architecture could effectively be:
Normal Visitor → Cloudflare → Server
Attacker ───────────────────→ Server
If the attacker knows the origin IP, they may simply target it directly.
After restricting the web ports:
Normal Visitor → Cloudflare → Server
Attacker ───────────────X──→ Server
That makes Cloudflare substantially harder to bypass at the network level.
One More Important Step: Restore Real Visitor IPs
There's a side effect.
Because every web connection reaching your server now comes through Cloudflare, Nginx may record Cloudflare's proxy IP instead of the visitor's actual IP.
For Nginx, you can configure its Real IP module to trust Cloudflare's networks and use the CF-Connecting-IP header:
real_ip_header CF-Connecting-IP;
along with set_real_ip_from entries for Cloudflare's current IP ranges.
This is important for accurate logs, moderation, abuse detection, application-level rate limiting and tools such as Fail2ban.
Cloudflare provides documentation specifically for restoring original visitor IP addresses:
Restoring Original Visitor IPs with Cloudflare
Going One Step Further
UFW protects the server itself, but many VPS providers also offer an upstream/cloud firewall.
For example, on DigitalOcean you can create a Cloud Firewall with essentially the same policy:
SSH / TCP 22 → your chosen SSH sources
HTTP / TCP 80 → Cloudflare IP ranges only
HTTPS / TCP 443 → Cloudflare IP ranges only
That gives you two layers:
Cloudflare
↓
Provider Cloud Firewall
↓
UFW
↓
Web Server
The provider firewall can reject unwanted traffic before it reaches the VPS at all.
Final Thoughts
Putting a website behind Cloudflare is useful, but protecting the origin server is an important part of the setup.
Restricting ports 80 and 443 to Cloudflare means that even if someone discovers your origin IP, they shouldn't be able to simply connect to the web server directly.
Just remember that this configuration depends on Cloudflare's published network ranges. Periodically verify that your firewall rules match Cloudflare's current IP list, especially if Cloudflare announces changes.
And, as with any remote firewall modification, make sure you have a recovery method available before changing access rules.