V2: Reverse Proxy setup : help required

DNS rebind attack protection kicks in whenever you try to access pfSense’s HTTP server with a hostname that isn’t pfSense’s self-configured hostname.

The issue is that, internally (i.e. on LAN), a DNS A query for bw.tabala.com returns your external IP address.

Externally, this is fine. On the outside of your pfSense - i.e. the WAN interface - the firewall listens to all. A packet comes in for port 443. You’re probably forwarding it to Caddy (with NAT → Port Forward configuration). All is probably well from outside.

Internally, it’s a problem that can be a bit difficult to understand if you’re not familiar with it already. Think about the packet your browser sends: it looks up the website you requested and the DNS says (EXTERNAL IP). So, you’re on LAN, and our little packet has been told to go find this internet address. Your PC sends it in the direction of the gateway - your pfSense - and says “the internet is that way, go forth”. Our little packet reaches the pfSense and says, “I was sent for (EXTERNAL IP), do you know him?”, and the pfSense goes, “Well of course I know him, he’s me!”

So our packet has technically reached its destination and needs travel no further. Problem: what does the pfSense do with it now? YOU want pfSense to send our little packet onwards to Caddy; you’ve likely set up a port forward to enable this. But the packet didn’t come in from WAN, it actually came from the LAN interface. There’s no firewall and no NAT happening on the LAN side. Instead, pfSense is running its web server there!

So your browser sent a request for bw.tabala.com, it technically made it most of the way to where you want it, but it’s getting handled by pfSense instead of being sent to Caddy and now pfSense’s web server is upset because you forgot it’s name, how could you?


So that’s the problem. What’s the answer?

Well, there are two. The first is hairpinning, a.k.a. NAT loopback.

You flick a switch, and pfSense starts taking all the packets it receives on LAN and feeding them back through the WAN interface firewall - just in case there’s a NAT rule that applies! This approach pretty much instantly solves this problem (and a lot of problems like it). So why isn’t it on by default?

Well, it involves double-handling all those packets. It’s slightly less than ideal. Actually, though, it’s relatively common for consumer modem/routers to have hairpinning enabled by default. pfSense doesn’t, though, because it’s targeted at users with more technical expertise and they expect you’ll know to set it up if you want it.

The other option: split DNS.

Configure pfSense to return a different IP address for DNS requests that originate internally. Specifically, have pfSense return the local IP address of Caddy (rather than the external address of your pfSense) for a DNS request for your domain name. Then, those little packets don’t even need to even go to pfSense and loop around to Caddy; they can go straight to the Caddy host server.

This is what I do. There’s a few ways about it; you can either use a domain that pfSense has configured, with the subdomain CNAME’d to the server’s hostname, which is externally CNAME’d to your pfSense and internally resolves directly to the LAN IP of the server. The other way is to just set manual host overrides in the DNS resolver (unbound).

Check out Netgate’s own docs, which cover both methods in pfSense:

https://docs.netgate.com/pfsense/en/latest/nat/accessing-port-forwards-from-local-networks.html

3 Likes