How to setup DNS to do local domains and forwarding only?

I would like to have my UCS server handle local DNS duties and forward to another server for everything else. It doesn’t seem to matter how I configure it I can only seem to get local only or local plus full recursion.

I tried playing with the fake root and forwarders options in UCR, but it doesn’t seem that I can set forward only. Even editing the config file and restarting bind didn’t seem to work.

Does anyone know how I can set it up so it will respond for it’s local domains and only use the forwarder for everything else?

ucr set dns/forwarder1= (this is a open DNS Server - better as Google’s
or use UMC Settings-Network_Settings-externalDNSServer

Do NOT edit the files under /etc/bind EXCEPT the local.* ones!
Once you made a change restart the daemon by systemctl restart bind9 - the message is misleading

you have also open port 53 on your firewall for the UCS server to reach internet DNS Servers


Just to clarify, DNS is working. I am getting resolution of queries. The problem is I can’t seem to get UCS’ bind to forward only.

So if I do a query on the forwarder which is my firewall I don’t get responses for things on it’s block list. It replies with “This query has been blocked”.

If I make the same query to my UCS box I get the actual IP. It’s bypassing the forwarder and resolving the query on it’s own. I don’t want that.

Do you have only one UCS server ?

check if you have more than one forwarder in the UCS network config

Hi @Kevo,

please post the output of

root@ucs:~# ucr search --brief ^nameserv dns/forward
dns/forwarder2: <empty>
dns/forwarder3: <empty>
nameserver/external: false
nameserver/option/timeout: 2
nameserver2: <empty>
nameserver3: <empty>

As far as I understand your needs your dns/forwarder1 should point to your firewall and the other two forwarders remain empty.

EDIT/: The namerserver1-3 always point to DNS servers of your own domain! Do not use them to point outside!

Here is what the search shows

root@ucs:~# ucr search --brief ^nameserv dns/forward
connector/s4/mapping/dns/forward_zone/.*/static/ipv4: <empty>
connector/s4/mapping/dns/forward_zone/.*/static/ipv6: <empty>
dns/forwarder3: <empty>
nameserver/external: false
nameserver/option/timeout: 2
nameserver2: <empty>
nameserver3: <empty>

I guess there is some sort of misunderstanding. A bind forwarding-only service is called as well a “caching” nameserver as it usually does not have zone information at all.

As soon as you have local zones (as in UCS) there is no chance to do bind forwarding only (obviously: either it uses it’s local zone information OR it requests the information from his forwarders). But the forwarders do not have any information about the local zones.

So as you have it configured everything is fine (and can not work in a different way):
Your clients ask exclusively UCS (not your router!) and get the information they need. Either bind has them on his own (local zone), in his cache (if requested earlier) or requests them from his configured forwarder.

That’s it!


That doesn’t seem to match what I’ve been reading about the forward only directive. I’ve looked several places now and it seems it should be possible to have local zones and forward only working at the same time. I feel there is something I’m missing about the way it’s setup but I just haven’t figured it out yet.

So after several strong attempts at a working config failed I started looking for other alternatives. The DNSCrypt plugin on my firewall offers a forwarders option, so now I have everything pointed to my firewall for DNS and it is forwarding my local domains to UCS. This seems to be a clean solution and it won’t require any custom config on the UCS server.

Unfortunately I don’t actually understand why the config change didn’t work, but with so many conflicting reports of success and failure using that option on various forums I didn’t want to spend a lot of time trying to track down exactly how bind works and what that option does. It seems there are quite a few options in bind that don’t have simple on off behavior. It also seems that many people go to views in this sort of situation and I don’t want to maintain a custom config so OPNsense to the rescue.

Well, in Germany we say for such a solution: “Von hinten durch die Brust ins Auge!” (which literally means: from back through chest into the eye)- you archive your goal (to hit the eye) in both ways (by just poking into it or use the way from back). But it is not difficult to guess which way is the easiest…

What your firewall does is more or less the same what UCS DNS usually does. It forwards (or tries to resolve directly) any unknown domains through the configured dns/forwarder1 (or starts to-down-resolving from “.” when no forwarder is configured). The well-known doamin (your local one) is resolved by UCS. Again, your firewall now forwards every unknown domain to forwarder and the local domain to UCS.

Well, yes. This should work (from back through…). As long as your firewall is indeed forwarding your local zone (and not caching!).

You should probably tell us what you want to achieve. Not in terms of technical terms but by description. Why do you think the way UCS does it (resolving UCS domain locally and forwarding all others) does not suit you?


My problem was that it would not simply forward all non-local requests to the forwarders. It would resolve things itself. So in my case I want to block certain things so I set up a DNS block list feature on my firewall. But UCS would resolve around it if it didn’t like the answer it got from the firewall.

I didn’t test with OpenDNS or any of the other DNS based services, but I presume the same thing could happen there. This renders the blocking or control of what gets resolved ineffective.

I hope that make sense.


got it so far.
Well it is as I alreaady wrote:
Configure UCS to use forwarders by

root@ucs:~# ucr set dns/forwarder1=<IP OF YOUR FIREWALL>
root@ucs:~# ucr unset dns/forwarder2
root@ucs:~# ucr unset dns/forwarder3
root@ucs:~# systemctl restart bind9

Thus, it will reply for his local zone and forward ALL other requests to the firewall- where you can easily configure your filtering! It will not try to reach any other servers except the configured forwarders!

Just make sure you have your DNS settings correct, too:

root@ucs:~# ucr set nameserver1=<IP OF UCS>
root@ucs:~# ucr unset nameserver2
root@ucs:~# ucr unset nameserver3
root@ucs:~# systemctl restart bind9

If you do not believe in my writing, just test yourself! Configure as “dns/forwarder1” an IP address of an host which does not exist (and thus does not reply to DNS queries)- your name resolution will fail hard.


So I did that. Put in for a forwarder and you are right. It fails. So then I put my firewall back in as the forwarder and it works again, fully resolving names my firewall responds with a blocked message. So I guess this is a quirk of some sort with the way bind works.


;; ANSWER SECTION: 1 IN	HINFO	"This query has been locally blocked" "by dnscrypt-proxy"

;; Query time: 0 msec

UCS Server using Firewall as forwarder

;	IN	A


;; AUTHORITY SECTION:	172762	IN	NS	172762	IN	NS	172762	IN	NS	172762	IN	NS

;; ADDITIONAL SECTION:		48007	IN	A		345562	IN	AAAA	2001:4860:4802:32::a		57473	IN	A		345562	IN	AAAA	2001:4860:4802:34::a		41792	IN	A		345562	IN	AAAA	2001:4860:4802:36::a		10073	IN	A		345562	IN	AAAA	2001:4860:4802:38::a

;; Query time: 94 msec

I guess this is something what your dnscrypto-proxy is able to configure somehow.
If you check here, sending a HINFO record usually sends as well the configured fake address…

Please post full command line (dig …) when getting the above results. As well as your ucr-variables I mentioned earlier. I guess you restarted bind9 after configuration change? Do you have any further UCS servers or is this a single server environment? What is in /etc/resolv.conf?


command was a simple “dig @ address” or for my UCS server.

UCR variables were as you suggested. Only the first forwarder was filled in and bind was restarted after each ucr change.

resolv.conf just has 3 lines, domain, nameserver and options timeout:2.

I was thinking if I wanted to get to the bottom of this at some point I would set up a vm with just bind installed and set it up from scratch to see if I can reproduce the behavior and maybe try a couple of different versions.