Cloudflare Proxy with Unifi Firewall
In addition to moving this blog to cloudflare, I decided to take advantage of enabling Cloudflare’s proxy at the DNS level for my other (non-blog) services. Basically, this makes Cloudflare act as a reverse proxy.
However, handling Firewall & Port Forwarding rules was a bit more complicated.
Table of Contents
- Easy Way: Port Forwarding Ports 80 & 443
- Cloudflare IPs
- Creating Port/IP Groups in Unifi Network
- Firewall & Port Forwarding: IPv4
- Firewall: IPv6
First, why use Cloudflare proxy:
- They have much more sophisticated attack detection and anti-bot monitoring than I ever could
- Some stuff will be cached fairly significantly, which helps since I’m hosting these services on a slower connection.
Point #2 is a bit unnecessary, since these services are mostly used by me or family, so there shouldn’t be significant bandwidth concerned. However, #1 is important. While I can keep on top of patching and updates, I can’t keep on top of the latest bot or attack activity. Cloudflare does this, though. And with the flip of a switch I can disable the page at Cloudflare’s end (or add a captcha for access).
Easy Way: Port Forwarding Ports 80 & 443
The easy way to do this is the same as any hosting internally:
- IPv4: Port Forward ports 80 & 443 to your internal web server
- IPv6: Add a firewall rule allowing ports 80 & 443 to talk to your web server’s IPv6 address (Rejoice: no NAT!)
However, since my primary motivation in adding Cloudflare is for an extra layer of security & proxying, allowing connections to bypass that isn’t ideal.
I spent a good several minutes looking for “Cloudflare proxy values”, “Cloudfare address ranges”, etc. Turns out “Cloudflare IPs” takes you where you want: A list of Cloudflare IP addresses. Also available in plain text for IPv4 and IPv6.
Creating Port/IP Groups in Unifi Network
If you’re not using a Unifi router, your configuration will, obviously, be different. That said, the same concepts probably apply.
Within the Network app, I navigated to Settings, then Profiles, then scrolled down to Port/IP Groups. You’ll need to create a few groups:
A IPv4 group for all Cloudflare IPv4 IPs:
We’ll use this in the IPv4 firewall rules.
An IPv6 group for all Cloudflare IPv6 IPs.
No screenshot. Like above, but six-ier.
You can’t mix IPv4 & IPv6 in one list.
We’ll use this in the IPv6 firewall rule.
An IPv6 Group for your web server’s public IPv6 address.
We’ll use this in the IPv6 firewall rule.
A Port Group with Ports 80 & 443 in it.
We’ll use this in the IPv4 & IPv6 firewall rules.
Firewall & Port Forwarding: IPv4
You’ll still need to configure an IPv4 Port Forward. This is because NAT sucks, and the router still needs to do work to handle readdressing. Ugh.
This will open Ports 80 & 443 to the Entire Internet. This works (and I’ve been doing it for years), but is not my ideal end state with Cloudflare.
Note that while you can change From: Any to Limited, that gives you a very small plain text box, which is annoying. You can probably enter multiple IP ranges? Maybe? I didn’t try, because a small text box is annoying and hard to maintain.
I decided to implement an “Allow” rule for Cloudflare IPs, and a “Block” rule as a catch-all. This is because you can’t inverse a list of IP addresses (match things not in the list). So, two rules:
Allow HTTP(S) from Cloudflare over IPv4
This explicitly allows Cloudflare to talk on ports 80 & 443.
Block HTTP(S) from Internet over IPv4
This rule will block all traffic over ports 80 & 443, from anywhere. But because the Cloudflare addresses were already matched, they still get in.
The ordering is important. You’ll want your Allow rule before the Block rule.
As is so often the case, everybody worries that IPv6 is going to be so much harder, when the reverse is actually true. Only one Firewall rule is needed:
No Port Forwarding, no multiple rules, no order considerations. Just Done.
Don’t forget to test with external hosts to ensure the rules behave as expected.
Also, you may want to follow-up with rules to restore the original (non-Cloudflare) request IP in your web server of choice. If you’re doing this, it’s probably important to not allow general Internet traffic, else a bad actor could spoof the CF-Connecting-IP header.