Update: I later figured out there are many other places pfSense restarts Unbound, so this is simply not worth the effort. I reversed the changes & moved Unbound to another box and using just DNS forwarder on pfSense — which is used by the Unbound server.
Having multiple broadband connections at home, I have a pfSense which takes care of load balancing and firewalling. pfSense is pretty good in almost everything, except one thing that was annoying me a lot — That it restarted the DNS Resolver (Unbound) every time either of my WAN connections restarted (one of my ISPs restarts the connection periodically), and the traffic originating from the box itself cannot be load balanced across multiple connections due to a limitation in FreeBSD’s implementation of pf itself – it is unable to set the correct source address.
It’s quite annoying that – even when you use the forwarding mode of Unbound, your DNS still goes through a single WAN interface. Moreover, Unbound doesn’t seem to do parallel querying across DNS servers. So if you have listed multiple DNS servers as forwarders it will try them one by one as they fail. Suppose, the WAN interface from which DNS traffic is outgoing is running at full capacity – a download or somebody is streaming a video, then your browsing becomes slow as well – but the browsing itself may go through another WAN connection. Notably, for having a stable multi-WAN setup in pfSense – you have to use forwarding mode. The gateway switching for the box itself doesn’t work reliably in my experience, due to which I’ve had to face “host not found” error messages even when one of the connections was up.
Solution: Use both DNS Forwarder (DNSMasq) and DNS Resolver together. Why not just forwarder? Because Unbound is a better DNS server – in terms of performance and security. And DNSMasq has an excellent feature that’s probably not available in any DNS Forwarder or Resolver – the ability to send parallel queries to the upstream servers. It’s called the all-servers option and what it does is – when it receives a query for domain X, it will send the query to all the servers and return the first response it receives – so you get the response extremely fast.
So go to Services => DNS Forwarder in pfSense and configure it with following settings:
Then in the custom options box, put the following:
no-negcache cache-size=0 resolv-file=/var/run/resolv.conf
You may be wondering why I’ve specified a different resolv.conf file here, it’s to prevent DNSMasq from using Unbound as a DNS server. That can be achieved by tweaking the “Disable DNS Forwarder” flag in System => General setup, but that would mean the box’s DNS will become slower. I want to use Unbound for the pfSense box too, but DNSMasq should not use Unbound.
Then in DNS Resolver settings:
Disable Forwarding Mode – Otherwise pfSense will put in the configured upstream DNS servers in Unbound’s configuration.
In custom options box:
server: do-not-query-localhost: no forward-zone: name: "." forward-addr: 127.0.0.1@5353
Further, to prevent Unbound from restarting whenever your WAN connection is restarted –
- SSH to your pfSense box
- Open /etc/rc.newwanip in your favorite editor, go to line 228 which calls a function services_unbound_configure(). Comment the line.
- Then open /etc/inc/system.inc, go to line 175 which opens /etc/resolv.conf for writing and replace it with:
$fd = fopen("/var/run/resolv.conf", "w");
Then in System => General setup, tick the box which says “Do not use the DNS Forwarder/DNS Resolver as a DNS server for the firewall”. Now, pfSense will write the real resolv.conf based on your configured DNS servers or whatever your ISP supplies (configurable in General Setup) to /var/run/resolv.conf and in /etc/resolv.conf just put one line:
This will ensure that the pfSense uses Unbound as it’s resolver, so immune to WAN failures.
So now, the DNS works something like this:
Client => Unbound => DNSMasq => Upstream DNS Server
Here, client can be any client on the LAN or pfSense itself. And because of the all-servers feature of DNSMasq, both WAN connections will get used for DNS traffic and choking of one line will not cripple DNS.