TL;DR

Clean option (split DNS): Services → DNS Resolver → Host Overrides → app.example.com → the server’s internal IP (192.168.1.50). LAN clients must use the firewall as their DNS.

NAT reflection option: System → Advanced → Firewall & NAT:

  • NAT Reflection mode for port forwards: Pure NAT
  • Enable NAT Reflection for 1:1 NAT: ✔
  • Enable automatic outbound NAT for Reflection: ✔

Save and test from a LAN client against the public IP.

The problem

The port forward WAN:443 → 192.168.1.50:443 works from the Internet. From a machine on the same LAN, https://app.example.com (which resolves to the public IP) answers with the pfSense GUI, a certificate error, or Potential DNS Rebind attack detected.

The packet leaves the client towards the public IP, reaches the firewall through the LAN interface, and stops there: the port forward rule listens on the WAN, not the LAN, and the destination IP is one of the firewall’s own addresses. It never “goes out and comes back in”.

Option 1: split DNS

This is what Netgate recommends: the name resolves to the internal IP inside and to the public one outside. Traffic goes direct, the server sees the client’s real IP, and the firewall touches nothing.

  1. Services → DNS Resolver → Host Overrides → Add: host app, domain example.com, IP 192.168.1.50. If the service has several names, add Additional Names.
  2. Clients must use the firewall as DNS (the norm if DHCP hands it out). A client with 8.8.8.8 hardcoded will keep going to the public IP.
  3. nslookup app.example.com from the LAN → 192.168.1.50.

Requirement: the internal and external ports must be the same (if outside you forward 8443 → 443, the internal client will have to use 443 directly).

If you run the DNS Forwarder (dnsmasq) instead of the Resolver, the equivalent setting is under Services → DNS Forwarder → Host Overrides.

Option 2: NAT reflection

When you do not control the clients’ DNS, or there are lots of ports, the firewall can “reflect” the connection: it rewrites the destination to the internal IP and, with automatic outbound NAT, the source too, so the reply comes back through the firewall.

System → Advanced → Firewall & NAT, Network Address Translation section:

SettingValueWhy
NAT Reflection mode for port forwardsPure NATPF rules only: every protocol, no port limit. NAT + Proxy uses a daemon, TCP only and at most 500 ports per rule
Enable NAT Reflection for 1:1 NAT✔If you have 1:1 NAT besides port forwards
Enable automatic outbound NAT for Reflection✔Without it, when client and server share a subnet the server replies straight to the client, which does not recognize the connection and drops it
Reflection Timeout(NAT + Proxy only)Ignore it in Pure NAT

It can also be enabled per rule: Firewall → NAT → Port Forward → edit → NAT reflection → Enable (Pure NAT), leaving the global setting on Disable.

Costs: the server sees the firewall’s LAN IP as the source (not the client’s), and all that traffic crosses the firewall even when client and server sit on the same switch.

OPNsense

Same idea, other menus:

  • Split DNS: Services → Unbound DNS → Overrides → Host Overrides.
  • Reflection: Firewall → Settings → Advanced → Reflection for port forwards, Reflection for 1:1, Automatic outbound NAT for Reflection.

Traps

  • DNS rebinding. If instead of a host override you point the Resolver at an external DNS that returns private IPs (an internal DNS at another site, a provider with views), Unbound drops those answers as rebinding protection. Do not untick Disable DNS Rebinding Checks under System → Advanced → Admin Access: add private-domain: "example.com" under Services → DNS Resolver → Custom options and only that domain is exempt.
  • A client with hardcoded DNS bypasses split DNS. Either force it through DHCP, catch it with a port 53 NAT rule, or use reflection.
  • Pure NAT needs to know the interface and gateway when rules load; with dynamic WANs that change IP, a Filter Reload after the IP change fixes it.
  • Different ports inside and outside only work with reflection; split DNS does not translate ports.
  • Certificates: with split DNS the browser still sees app.example.com, so the server’s certificate works as is. When reflecting through the public IP, too. The certificate error at the start was the firewall GUI’s, not the server’s.

References: Port Forwards from Local Networks and NAT Reflection in the Netgate documentation.