Articles February 4, 2010 at 3:17 pm

Augmenting DNS Records Using dnsmasq

DNS can always bite you in the rear. in some case you run your own DNS server and you can correct the issues. In other cases, you're beholden to the powers that be to determine your fate. All is not lost, however, it is possible to run your own DNS proxy to override specific answers. It's not an ideal solution, and can certainly be accused of being a "hack" but it can be invaluable in some situations.

Read on for how to do this…

There are a number of Active Directory scenarios or edge cases inwhich your Mac OS X computer doesn't have access to certain DNSrecords, and this hinders your Mac's ability to join or reliably useActive Directory. Some scenarios are more, er, legitimate than others,and some scenarios are pretty ridiculous. And yes, it is better to fixAD than it is to work around poorly-designed AD implementations,augmenting DNS might be relatively quick workaround to make your Macswork with AD. Until the next AD issue crops up.

Possible trouble scenarios:
Possible scenarios in which the Mac OS X Active Directory connector won't reliably join or use AD include:

  • YourActive Directory site was designed with Branch Office Topology (seebelow), and certain DNS records are not purposely available to Mac OS X( _ldap._tcp.<domain>, _kerberos._tcp.<domain>,_kpasswd._tcp.<domain> and _kpasswd._udp.<domain>)
  • There is a network device that performs Network Address Translation (NAT) between you and the Domain Controller
  • Active Directory Sites isn't set up correctly

Some false solutions:

  • Youcan't just add your preferred domain controller to /etc/hosts, because/etc/hosts doesn't provide DNS service (SRV) records, which arerequired by the Active Directory connector. Bummer.
  • You can'tjust select the checkbox in the Active Directory connector for "Preferthis domain server", because that only prefers a Domain Controller thatis in the same Site you are a member of, but you first have to become amember of that Site.
  • You can't just enable DNS with ServerAdmin and create a zone for your AD domain and then create only the DNSrecords you need, because this doesn't provide the DNS records for allthe other hosts in the AD domain. Well, I guess you *could* try tohand-synchronize your Mac OS X Server-provided DNS service with theAD-provided DNS service, but this seems like a recipe for disaster.

Some better solutions:

  • Fix your Active Directory infrastructure;
  • use the DNS service from AD;
  • don't use NAT.

Another solution:
dnsmasqis an open source DNS service that can override the answers to certainDNS queries, and forward the rest of the DNS queries on to another DNSservice. Point your Mac's DNS requests at dnsmasq, and configurednsmasq to provide only the DNS SRV records that you want it to, sothat your Active Directory connector is happy. Use dnsmasq to hand outDNS records the way you want them. The beautiful thing about dnsmasq isthat you can override certain queries, but allow your regular DNSserver to handle the rest of the queries. Here's the man page fordnsmasq: http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html

A warning: These tools are great, but please don't let this get in the way of fixing the core of a problem scenario.

The pieces involved:

  1. Thednsmasq daemon needs to start as root, because dnsmasq listens on theprivileged port 53, but then it runs as a non-root user. Port 53 is thestandard port for DNS service, and you can't run any other DNS service(like the DNS service offered by Mac OS X Server). You can run this onMac OS X or Mac OS X Server (and many other platforms).
  2. Your Mac needs to make DNS requests to the IP address of the computer running dnsmasq.
  3. Notethat now in 10.6, if you're using DHCP, if you modify the DNSserver(s), this *overrides* the DNS server(s) assigned by DHCP (whereaspreviously, the value you entered in the DNS Servers field was usedfirst, but the DHCP-assigned DNS server(s) was also used). In moredetail: if you open the Network pane of System Preferences, clickAdvanced, and then click DNS, any DNS server you are assigned via DHCPwil appear in the DNS Servers field. If you enter any IP address intothe DNS field, this replaces the DHCP-supplied value.
  4. /etc/dnsmasq.conf:The dnsmasq configuration file. It doesn't have to exist, but you cancopy and edit the dsnmasq.conf.example from the dnsmasq distributionfiles to /etc/dnsmasq.conf
  5. /etc/hosts: dnsmasq will use/etc/hosts for IP address-to-host queries, but not the other wayaround. Note that you cannot use /etc/hosts to provide SRV records.
  6. /etc/resolv.conf:Unless you use the "servers=" line in the dnsmasq configuration file,dnsmasq will attempt to use the servers listed in /etc/resolv.conf forDNS requests you haven't told it to respond to. If you're not familiarwith /etc/resolv.conf on Mac OS X, Mac OS X automatically updates thisfile to include the IP address(es) of the DNS servers you want your Macto query, as well as the "search domains" to slap on to the end ofhostname to IP address resolution requests. More about search domains:if you enter www in your browser, and have afp548.com in your searchdomains, your browser will open www.afp548.com. You'll also see that ifyou enter the mistyped URL www.google.cm in your browser, your Mac willissue a DNS query for www.google.cm.afp548.com.

The flow:
It is pretty simple.
You send a DNS query to dnsmasq (by configuring your Mac to use a computer running dnsmasq, which could be itself).
If you configured dnsmasq to give a specific answer, it will give that answer.
Ifyou didn't give dnsmasq any information about the request, dnsmasq willforward that request to the DNS service that you tell it to use.

An an example:
Ihave a Mac OS X computer, and I want to use any of the three DomainControllers in the Chicago Branch Office, chicago-dc[1-3].ssh22.com,which have IP addresses of 10.1.100.1, 10.1.100.2, and 10.1.100.3. Idon't want to use the other Domain Controllers, like the ones below.

Beforeusing dnsmasq, I might get a huge number of replies for_ldap._tcp.ssh22.com, including from DCs in Gothenburg, Gunma, andGent, but I can edit my dnsmasq.conf to return only certain results.

When I issue a query for the DNS SRV record _ldap._tcp.ssh22.com, I'd like the answer to return those three DCs above.
clientx:~ localadmin$ host -t SRV _ldap._tcp.ssh22.com
_ldap._tcp.ssh22.com has SRV record 0 100 389 chicago-dc3.ssh22.com.
_ldap._tcp.ssh22.com has SRV record 0 100 389 chicago-dc2.ssh22.com.
_ldap._tcp.ssh22.com has SRV record 0 100 389 chicago-dc1.ssh22.com.

client:~ localadmin$ host -t SRV _kerberos._tcp.ssh22.com
_kerberos._tcp.ssh22.com has SRV record 0 100 88 chicago-dc3.ssh22.com.
_kerberos._tcp.ssh22.com has SRV record 0 100 88 chicago-dc2.ssh22.com.
_kerberos._tcp.ssh22.com has SRV record 0 100 88 chicago-dc1.ssh22.com.

client:~ localadmin$ host -t SRV _kpasswd._tcp.ssh22.com
_kpasswd._tcp.ssh22.com has SRV record 0 100 464 chicago-dc3.ssh22.com.
_kpasswd._tcp.ssh22.com has SRV record 0 100 464 chicago-dc2.ssh22.com.
_kpasswd._tcp.ssh22.com has SRV record 0 100 464 chicago-dc1.ssh22.com.

client:~ localadmin$ host -t SRV _kpasswd._udp.ssh22.com
_kpasswd._udp.ssh22.com has SRV record 0 100 464 chicago-dc3.ssh22.com.
_kpasswd._udp.ssh22.com has SRV record 0 100 464 chicago-dc2.ssh22.com.
_kpasswd._udp.ssh22.com has SRV record 0 100 464 chicago-dc1.ssh22.com.

I'll have to edit the dnsmasq configuration file to specify SRV records.

The sample configuration file notes that you can add a SRV record in the form:
<name>,<target>,<port>,<priority>,<weight>
<name> is what will be requested
<target> is the host name part of the answer you want dnsmasq to return
<port> should be 389 for ldap, 88 for kerberos, and 464 for kpasswd (and 3268 for gc if you use that).
<priority> and <weight> can be anything, I'm going to use 0 and 100, default values for these SRV records in AD.

I'll enter 12 additional SRV records; I have three DCs, and each DC has four SRV records
(ldap, kerberos, kpasswd over tcp, and kpassdwd over udp).

I'll add the following lines to /etc/dnsmasq.conf:
srv-host=_ldap._tcp.ssh22.com,chicago-dc1.ssh22.com,389,0,100
srv-host=_ldap._tcp.ssh22.com,chicago-dc2.ssh22.com,389,0,100
srv-host=_ldap._tcp.ssh22.com,chicago-dc3.ssh22.com,389,0,100
srv-host=_kerberos._tcp.ssh22.com,chicago-dc1.ssh22.com,88,0,100
srv-host=_kerberos._tcp.ssh22.com,chicago-dc2.ssh22.com,88,0,100
srv-host=_kerberos._tcp.ssh22.com,chicago-dc3.ssh22.com,88,0,100
srv-host=_kpasswd._tcp.ssh22.com,chicago-dc1.ssh22.com,464,0,100
srv-host=_kpasswd._tcp.ssh22.com,chicago-dc2.ssh22.com,464,0,100
srv-host=_kpasswd._tcp.ssh22.com,chicago-dc3.ssh22.com,464,0,100
srv-host=_kpasswd._upd.ssh22.com,chicago-dc1.ssh22.com,464,0,100
srv-host=_kpasswd._upd.ssh22.com,chicago-dc2.ssh22.com,464,0,100
srv-host=_kpasswd._upd.ssh22.com,chicago-dc3.ssh22.com,464,0,100

Ineed to stop and start the dnsmasq daemon in order for it to re-readthe configuration file and use these new SRV records (a SIGHUP signalto dnsmasq only re-reads /etc/hosts, but not the configuration file).Because I set up a launchd item for dnsmasq, I use launchctl to unloadand load the launchd item, rather than kill the daemon directly.
clientx:~ localadmin$ sudo launchctl unload /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq
clientx:~ localadmin$ sudo launchctl load /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq

Elements to install:

  • /usr/local/sbin/dnsquery
  • /etc/dnsmasq.conf
  • /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist

If you want to just get going:
Download the dnsmasq package installer from me at http://www.arekdreyer.com/file_download/7/dnsmasq-2.52.dmg, which installs:

  • dnsmasq in /usr/local/sbin/dnsmasq
  • dnsmasq man page in /usr/local/share/man/man8/dnsmasq.8
  • A sample dnsmasq.conf in /private/etc/dnsmasq.conf
  • A launchd item for dnsmasq in /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
  • The dnsmasq source in /usr/local/shared/src

Skip the next step, and continue with configuring dnsmasq.

If you want to compile and install it yourself:

  1. Install the Mac OS X Developer tools from the installation disc that comes with your Mac.
  2. Download dnsmasq
    1. Visit http://www.thekelleys.org.uk/dnsmasq/doc.html
    2. Download the latest version (I wrote this with version 2.52)
  3. Make and install dnsmasq from the dnsmasq folder
    1. cd; cd Downloads
    2. gunzip dnsmasq-2.52.tar.gz
    3. tar -xvf dnsmasq-2.5.2.tar
    4. cd dnsmasq-2.52
    5. make
    6. sudo make install
  4. Installthe launchd item from contrib/ folder if it is available in the 2.52release of dnsmasq), according to the directions in thelaunchd-README.txt file
    1. cd contrib/MacOSX-launchd
    2. If you don't already have a /Library/LaunchDaemons folder, create one:
      1. sudo mkdir /Library/LaunchDaemons
      2. sudo chown root:admin /Library/LaunchDaemons
      3. sudo chmod 775 /Library/LaunchDaemons
    3. sudo cp uk.org.thekelleys.dnsmasq.plist /Library/LaunchDaemons/
    4. sudo chown root:admin /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
    5. sudo chmod 644 /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist

Configure dnsmasq

  1. Ifyou don't already have /etc/dnsmasq.conf, copy dnsmasq.conf.examplefrom the source files to a new file named /etc/dnsmasq.conf
    1. sudo cp dnsmasq.conf.example /etc/dnsmasq.conf
  2. Edit /etc/dnsmasq.conf
    1. If your AD DNS servers are 172.16.20.4 and 172.16.24.5, you'd add the line:
      •  server=172.16.20.4,172.16.24.5
    2. Youcan send logging information to its own logfile with the –log-facilityoption in the command line, or with the following line in/etc/dnsmasq.conf:
      • log-facility=/var/log/dnsmasq.log
    3. Create the SRV records, each on its own line, as I listed above
      • srv-host=_ldap._tcp.ssh22.com,chicago-dc1.ssh22.com,389,0,100

Start dnsmasq

  1. sudo launchctl load /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
  2. Look in /var/log/system.log – you should see an entry from com.apple.launchd that your dnsmaq job started.

Configure Mac OS X to use your dnsmasq service and Test

  1. Ifyou're running dnsmasq on … yourself, then use the Network systempreference to set DNS to 127.0.0.1 followed by at least one other DNSserver (unless you use the directive "server=" in dnsmasq.conf)
  2. If you're running dnsmasq on another computer, use Network system preference to set DNS to the IP address of the dnsmasq server.
  3. Test dnsmasq resolution of addresses
    1. host -t SRV _ldap._tcp.ssh22.com
    2. host -t SRV _kerberos._tcp.ssh22.com
    3. host -t SRV _kpasswd._tcp.ssh22.com
    4. host -t SRV _kpasswd._udp.ssh22.com
  4. Bind your Macs to AD, using the AD DCs you want to use.

Reconfiguring/updating dnsmasq information

  1. If you edit /etc/hosts directly; dnsmasq will immediately use your changes
  2. If you edit /etc/dnsmasq.conf, you'll need to stop and start dnsmasq (for security)
    1. Stop dnsmasq:
      1. sudo launchctl unload /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
    2. Restart dnsmasq:
      1. sudo launchctl load /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
    3. If you want to permanently stop the launchd job, so it doesn't start even after a reboot, unload it with the -w flag:
      1. sudo launchctl unload -w /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist

More About AD Branch Office Topology
See http://technet.microsoft.com/en-us/library/cc749944.aspx
Planning Active Directory for Branch Office
"Inthe branch office scenario, it is important that clients that cannotfind a domain controller in their own site find a domain controller intheir hub site, but never a domain controller in another branch or hub.In many deployments, clients from one branch cannot connect to machinesin another branch, because the network is not fully routed (for exampleone-way dial-up lines are used). Even if connectivity is possible,however, it is still undesirable to initiate network connectionsbetween branches. Such network traffic would always go through the hubsite; therefore it is better to restrict the traffic to branch-to-hubonly."

"To avoid the situation where clients in one branchcontact a domain controller in another branch, the Net Logon service onall branch office domain controllers must be configured to publish onlysite specific locator records, but not generic domain controllerlocator records. The result is that only the hub domain controllerspublish the generic locator records in addition to their site-specificrecords. Clients that cannot find a domain controller in their own sitewill now only find generic domain controller locator records for hubdomain controllers."

About

Arek Dreyer has been an Apple Certified Trainer since 2002. Originally an expert in Sun Systems, Dreyer shifted his professional focus to Mac OS X shortly after it came out. President of Dreyer Network Consultants Inc., Arek has been delivering courses and providing training around the world, both in the classroom and at events like the Apple Channel Camp and the Macworld Conference and Expo. Dreyer also provides integration and troubleshooting services for his own customers and for Apple.

1 Comment

  • The article suggests that is is possible to concat multiple servers with comma, like so:

    server=193.75.75.75,193.75.75.193

    But a statement like this leads to a startup error (at least in MacPorts dnsmasq @2.55_0+no_dhcp+no_tftp):

    Jul 13 23:01:45 slsmini org.macports.dnsmasq[40774]: dnsmasq: error at line 35 of /opt/local/etc/dnsmasq.conf

    As soon as I split the line (one line per server), everything works fine and the log file shows that both servers are added.

Leave a reply

You must be logged in to post a comment.