When you sit behind Cloudflare, you should only allow traffic from Cloudflare’s IP ranges on ports 80 and 443. Cloudflare periodically updates these ranges, so the UFW rules need to be refreshed automatically. The script from cloudflare‑ufw, by Paul Reed, does exactly that.
1. Download and make the script executable
bashsudo wget -O /usr/local/bin/cloudflare-ufw.sh \
https://raw.githubusercontent.com/Paul-Reed/cloudflare-ufw/refs/heads/master/cloudflare-ufw.sh
sudo chmod +x /usr/local/bin/cloudflare-ufw.sh
2. Inspect current UFW rules (before changes)
bashsudo ufw status verbose
You’ll likely see something like:
textTo Action From
-- ------ ----
22/tcp ALLOW Anywhere
80/tcp ALLOW Anywhere
443 ALLOW Anywhere
...
3. Remove the overly‑permissive 80/443 rules
These rules currently allow any IP to reach your web ports. We’ll replace them with Cloudflare‑only rules.
bashsudo ufw delete allow 80/tcp
sudo ufw delete allow 443/tcp
If UFW asks for confirmation, type y and press Enter.
Check the status again:
bashsudo ufw status verbose
You should no longer see 80/tcp or 443 with ALLOW from Anywhere.
4. Run the Cloudflare‑UFW script
bashsudo /usr/local/bin/cloudflare-ufw.sh
What the script does:
- Fetches the latest Cloudflare IPv4 and IPv6 ranges from
https://www.cloudflare.com/ips-v4and.../ips-v6. - Deletes any existing UFW rules for ports 80 and 443 that allow
Anywhere. - Adds new
ALLOWrules only for each Cloudflare IP range on ports 80 (HTTP) and 443 (HTTPS). - Optionally reloads UFW so the new rules take effect immediately.
After it finishes, verify:
bashsudo ufw status verbose
You should now see multiple lines like:
textTo Action From
-- ------ ----
80/tcp ALLOW 173.245.48.0/20
80/tcp ALLOW 103.21.244.0/22
...
443 ALLOW 173.245.48.0/20
443 ALLOW 103.21.244.0/22
...
All other IPs are implicitly denied for ports 80/443.
5. Automate daily updates with cron
Cloudflare can change its IP ranges at any time. To keep your firewall in sync, schedule the script to run daily (e.g., at 03:00).
Edit the root crontab:
bashsudo crontab -e
If prompted, choose your preferred editor (e.g., nano).
Add the following line at the end:
text0 3 * * * /usr/local/bin/cloudflare-ufw.sh >> /var/log/cloudflare-ufw.log 2>&1
This does:
- Runs the script every day at 03:00 server time.
- Appends output and errors to
/var/log/cloudflare-ufw.logfor auditing.
Save and exit the editor.
6. Verify the cron job
List root’s crontab to confirm:
bashsudo crontab -l
You should see the new line.
Optionally, force an immediate run and check the log:
bashsudo /usr/local/bin/cloudflare-ufw.sh
sudo tail -n 20 /var/log/cloudflare-ufw.log
7. Ongoing maintenance
To manually refresh rules at any time:
bashsudo /usr/local/bin/cloudflare-ufw.sh
To inspect the log:
bashsudo less /var/log/cloudflare-ufw.log
If you ever need to revert to “allow anywhere” (not recommended in production):
bashsudo ufw delete allow from any to any port 80 proto tcp sudo ufw delete allow from any to any port 443 proto tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp
With this setup, your UFW firewall will always only accept HTTP/HTTPS traffic from current Cloudflare IP ranges, dramatically reducing the attack surface while ensuring your sites stay reachable through Cloudflare.
Leave a Reply