OPNsense and pfSense as a Hidden Primary
Host your public zone in the BIND plugin of your OPNsense or pfSense firewall, and let an external secondary answer the internet.
Before you start
Both firewalls offer BIND as a plugin with a web interface. It works well as a hidden primary: the firewall holds the zone, and only your secondary talks to it. The two plugins differ in three points that matter here, so read the section for your firewall to the end:
| Point | OPNsense (os-bind) | pfSense (BIND package) |
|---|---|---|
| Serial on record changes | Set automatically | Not changed; you must do it |
| NOTIFY to extra servers | Not in the interface | Via the zone's Custom Option |
| TSIG for transfers | Not usable in practice | No setting in the interface |
In both cases, you restrict transfers by IP address. Add the zone on hiddenprimary.ch without a TSIG key.
OPNsense
1. Create an ACL with the transfer addresses
Go to Services → BIND → Configuration, tab ACLs, and add an ACL.
Name it, for example, secondary, and enter the transfer addresses in Network
List. For hiddenprimary.ch:
Allow all four: two hosts can connect to your primary, the transfer node and the standby that takes over when the transfer node is unavailable, each with IPv4 and IPv6.
2. Create the primary zone
On the tab Primary Zones, add a zone. Select your ACL under Allow Transfer. Leave Allow RDNC key transfer off: it would hand out the firewall's own control key.
3. NOTIFY
The plugin has no field for extra NOTIFY targets. BIND then notifies the servers named in the zone's NS records. Once the zone lists our nameservers (step 4), the NOTIFY reaches us. Until then, we pick up changes at the next refresh.
4. NS records and serial
Add NS records for our nameservers to the zone, and set the same nameservers at your registrar. OPNsense sets
the serial automatically on every change, in the form YYMMDDhhmm. Two changes within the same
minute therefore get the same serial, and the second one reaches the secondary only with your next change.
If you make several edits in a row, wait a minute before the last one.
pfSense
1. Create an ACL with the transfer addresses
Go to Services → BIND DNS Server, tab ACLs. Add an ACL named, for
example, secondary, and add one row per address:
2. Create the zone and allow the transfer
On the tab Zones, add a zone with Zone Type Master. Under
allow-transfer, select your ACL (hold CTRL to select several). Do not write an
allow-transfer statement into the Custom Option field: the package already writes one, and a
second one breaks the configuration.
3. Send NOTIFY to the secondary
On the tab Settings, check Enable Notify. Then put the notify targets into the zone's Custom Option field:
4. Raise the serial on every change
The pfSense package does not change the serial when you edit records. The secondary then keeps its old copy, and your change never reaches the internet. On every edit, either raise the Serial field yourself or clear it before you save. An empty field makes the package set a new value.
5. NS records
Add NS records for our nameservers to the zone, and set the same nameservers at your registrar. The migration guide explains the order.
Firewall rules
The DNS server runs on the firewall itself, so you need a rule on the WAN interface: allow TCP and UDP port 53 from the transfer addresses to "This Firewall". Transfers use TCP. Allow only those addresses: port 53 open to the whole internet invites abuse of your firewall.
Check that it works
If the answer is old or missing, see zone transfer errors.
Next Steps
- Getting Started — add your zone on hiddenprimary.ch
- Technitium DNS Server as a hidden primary
- A hidden primary on a changing IP address