Highlighted
New Member
Posts: 25
Registered: ‎03-11-2017
Kudos: 27
Solutions: 1

Advanced DNS Setup on a Unifi Security Gateway - HowTo

I recently had cause to disable the DNS server on my Synology NAS.  The problem is that when the NAS was busy (like doing a raid5 data scrub), the delay before the name server would respond was causing service failures in all sorts of things.  My security gateways are lightly loaded, and I don't have a huge set of host names, so I decided to make my security gateways do my internal DNS as well as external lookups.  I got it to work, but it required some under the hook tinkering, so I thought some other people might find the instructions here helpful.

 

The only package on the security gateway for resolving names is dnsmasq.  This is suboptimal.  ISC's bind would have been much better and would have allowed me to make things actually work correctly.  But, since dnsmasq is what we've got, we'll work with it.  The only problem is that dnsmasq will report that answers for the internal domains are not authoritative when they really should be.  But the second we tell dnsmasq it's authoritative for the internal domains, it switches from being a caching server to a standalone authoritative server that refuses to do recursive lookups of domains it doesn't handle (aka, all name resolution for domains outside of what you define suddenly stops working).

 

So let's get started.  I'm going to jump ahead a little bit.  Most of the work you need to do will happen on the gateway itself.  You'll need to ssh to the gateway, scp some files over, put those files in various places, etc.  There is only one item that happens on your controller instead of the gateway itself.  I'll cover that first.

 

If you need multiple domains, then you'll want the dhcp server to provide a valid domain-search return to your clients.  There is no way to configure the domain-search field in the controller gui right now (although it would be easy to add to the network definition, just make the domain field stay like it is, and immediately below it add a domain search field that is a space delimited list of additional domains to search, then concatenate the two fields together and pass it to the vyatta dhcpd-config.pl script and it will do the rest), so we'll use the config.gateway.json trick to add one.  I don't want to go into all the gory details of where to find the right site directory for the file, that's been covered in other help topics, just search for config.gateway.json and read up on it.  But I've attached a file that has the right json syntax for creating a domain-search option in the dhcpd.conf file (it also has the snippets to enable NoIP's DDNS since that's not supported in the gui).  Modify the file to suit your needs and place it in the right site directory on your controller.

 

That's all you have to do on the controller, everything else will happen on the gateway itself (and will likely need to be redone, at least partially, if you update the gateway's firmware).

 

First, log into the gateway, and go ahead and just sudo su to get a root shell.  The first thing you'll have to do is fix a bug in the vyatta router dhcpd-config.pl script.  It universally created a domain-search item containing just your actual domain.  It shouldn't do that.  It should only create a domain-search entry if there is more than one domain present.  To fix that, you need to edit the file /opt/vyatta/sbin/dhcpd-config.pl.  You need to go to line 500 or so in the file, and right there is sets the 'my $domain_search' stuff.  That line and the two $genout .= lines beneath it simply need wrapped with 'if ( scalar (@domain_names) > 1 ) { ... }.  I've attached both a diff for people that know how to read diffs, and a fixed version of the file itself to this so people can reference what needs done.

 

The next thing to do is create a series of files to configure dnsmasq.  You'll want to create these files on your computer and copy them over to the security gateway.  That way, if the gateway looses the files during a firmware update or something like that, you have backup copies and can easily restore the custom gateway setup.

 

The first thing to create is a new resolv.conf file.  Let's call it resolv.upstream.  It needs to contain whatever name server lines are currently in the /etc/resolv.conf file on the gateway.  Normally, they are the ones that the gateway got from the dhcp responses from the ISP.  We need dnsmasq to know about them so it can know who to forward things to first.  You can easily enough just copy /etc/resolv.conf to /etc/resolv.upstream and then edit it using vi.  Remove any lines that aren't nameserver entries, then maybe add a couple backup nameserver entries pointing to google's nameservers (8.8.8.8 and 8.8.4.4).  Mine ended up looking like this:

 

/etc/resolv.upstream:

nameserver aa.bb.cc.1 # ISP's nameserver
nameserver 192.168.1.254 # AT&T Router's internal DNS resolver
nameserver 8.8.8.8 # google nameserver
nameserver 8.8.4.4 # backup google nameserver

 

The next file, let's call it mydomain.conf, should  have contents that look something like this:

 

resolv-file=/etc/resolv.upstream
localmx
mx-target=nas.dmz.nc.xsintricity.com
localise-queries
no-hosts
domain-needed

 

As you can see, we are going to directly include the resolv.upstream file.  We need to do that because when we are all done, you need to go into the GUI for the controller and bring up your security gateway, then go to the config tab, then to WAN1, and set the preferred DNS to 127.0.0.1.  We want the gateway to be able to see the names that dnsmasq is serving, so we need the localhost entry as our preferred DNS.

 

The localmx and mx-target make all the local names have an MX entry pointing to the mx-target.  If you don't have a mail server, you can skip them.

 

The localise-queries is useful for the gateway itself.  The gateway will have interfaces in multiple networks.  And let's assume you just named them all the same thing (I use firewall myself, so I have firewall.nc.example.com and firewall.dmz.nc.examle.com for the corporate and guest interfaces respectively).  If someone does a lookup on firewall, it could return either of the addresses.  This option tells dnsmasq to return the address that is on the same subnet as the person asking for the address, if possible.

 

The no-hosts option is really there because the current controller and gateway firmware do not do a good job of tracking entries in the hosts file.  When you specify a static mapping it throws something in there, when you specify an alias for a machine it throws something in there, when dhcp gets a client-hostname it throws something in there.  In the end, you have a bunch of untracked cruft in there.  Since we are going to provide actual host files with complete addresses, let's ignore this junk.

 

The final item is optional.  I use it to force FQDN lookups.  But you need that domain-search working or else this can be counterproductive.

 

Once you have this file, copy it into the /etc/dnsmasq.d directory on the gateway itself.  The dnsmasq program reads all of the files in that directory on startup.

 

Next you need a domain file (you can put all your domain items in one file if you wish, but I find it easier to give each domain its own file, that way I can delete just a single domain easily if I want).  I should note here that this entire setup is really only suitable for internal domains.  These are not domains that you expect to resolve from the Internet, they only resolve when inside your network.  So here's a sample config in nc.example.com.conf:

 

interface-name=nc.example.com,eth2
auth-zone=nc.example.com
addn-hosts=/etc/nc.example.com.hosts

 

The interface name in this example points to the WAN1 interface of the Security Gateway 4 Pro.  For a Security Gateway, the WAN interface is eth0 instead.  This causes the domain "glue record", as the dnsmasq documents call it, to point to the WAN interface IP address.  Don't be tempted to put an auth-server line in here!  If you do, dnsmasq stops working for any domains that it is not authoritative for.

 

You also need to create that nc.example.com.hosts file.  It has the same format as the /etc/hosts file.  IP address<whitespace>hostname.  You can put a comma separated list of hostnames on each IP address if you want.  Here's a sample hosts file as well:

 

192.168.2.1 vpn-gw-lan.mo.example.com
192.168.2.4 imac-wifi.mo.example.com
192.168.2.5 imac-lan.mo.example.com
192.168.2.6 macbook.mo.example.com
192.168.2.20 cannon-printer.mo.example.com
192.168.2.249 hallway-wifi-ap.mo.example.com
192.168.2.250 office-switch.mo.example.com
192.168.2.254 firewall.mo.example.com

 

Once you have these files, one per domain, copy all of the .conf files to /etc/dnsmasq.d and put all of the .hosts files into /etc (don't put the .hosts files in the /etc/dnsmasq.d directory, they aren't in conf file format and will cause a startup failure).

 

When you've copied all the files into the right locations and you are reasonably sure that they have proper syntax, you can run dnsmasq --test to see if they really are good to go.  If they are, then you are ready to kill dnsmasq on the gateway and restart it.  If you know how to restart dnsmasq on your own, great.  I'm not going to go into detail about that here.  If you don't know, just use the controller GUI to restart the gateway and that will get it done.

 

Assuming all your config files were good, and put in the right place, you should now be able to resolve all of your internal DNS names properly from any machine that is pointing it's DNS to your security gateway.  You can now go into the controller GUI and do the last step: set the Preferred DNS on the gateway to 127.0.0.1 so it can see the internal names too (this is especially important if your controller entry in the site setup uses an internal name).

 

If you do a firmware upgrade on the security gateway, you are likely to need to replace the dhcpd-config.pl fixup.  The various conf files and hosts files *should* stick around, but you might have to copy them across again too.  And if you upgrade the firmware on a cloud key controller then you would need to replace the config.gateway.json stuff too.