Buck DNS Monoculture with BIND Alternatives (Part 3)
With Dnsmasq, internal DNS and DHCP services are a snap.
We're cruising at highway speeds now – in part 1 and part 2 we learned the ins and outs of using MaraDNS, which is excellent for both public and private DNS services. Now we're moving on to Dnsmasq, which is a great choice for private DNS and DHCP services. Today we'll learn how to configure everything from the Dnsmasq server, even assigning static IP addresses. That's right, your days of running thither and yon to futz with network configurations are over– you can do it all from the server.
Dnsmasq is well-suited for LAN name services. Even on a tiny LAN with only three or four PCs it's a nice time-saver. It's lightweight, weighing in under 600 kilobytes. You can slim it down even more by deleting the document files and unneeded locale files, which makes it a good fit for embedded routers. In fact Dnsmasq is used in a lot of embedded devices and operating systems: Smoothwall, Pyramid Linux, IPCop, floppyfw, Firebox, LEAF, Freesco, CoyoteLinux, m0n0wall, dd-wrt, openwrt and Linksys wireless routers.
Best of all it's very easy to use. If you ever tried to work your way through even the simplest DNS setup with BIND, or became hopelessly confused trying to install djbdns, I'll bet you got so frustrated you drowned your sorrows in cheap booze, turned to a life of crime to fund your habit, and wound up living under a bridge with all the other bitter, traumatized system administrators. Well come on out from under that bridge, because Dnsmasq is this easy:
- Have static IPs already configured on your LAN hosts
- Install Dnsmasq
- Configure /etc/hosts on the Dnsmasq server
- Configure /etc/resolv.conf on the Dnsmasq server
- Point all of your clients to the Dnsmasq box
- Put your feet up and relax
The Long Version
Dnsmasq is standard on most Linux distributions, so you can install it with aptitude install dnsmasq or yum install dnsmasq. Here is a sample /etc/hosts that assigns fully-qualified domain names to LAN hosts:
127.0.0.1 localhost.localdomain localhost
192.168.1.10 dnsmasq.alrac.net dnsmasq
192.168.1.11 uberpc.alrac.net uberpc
192.168.1.12 stinkpad.alrac.net stinkpad
192.168.1.25 firewall1.alrac.net firewall1
192.168.1.26 asterisk1.alrac.net asterisk1
Leave the 127.0.0.1 localhost entries in /etc/hosts on all of your computers.
/etc/resolv.conf on the Dnsmasq server should look this, using the IP addresses of your own upstream DNS servers:
Then restart Dnsmasq:
# /etc/init.d/dnsmasq restart
How do you point your LAN hosts to your nice Dnsmasq server? In Linux, put the IP address of your Dnsmasq server in /etc/resolv.conf:
On Windows it's the "Preferred DNS Server" setting in TCP/IP Properties.
While this is slick and quick, wouldn't it be even better to have no client configuration at all? Read on to learn how.
Making DHCP Do The Work
Configuring static IP addresses on a small LAN isn't such a big deal. But you can escape even this trivial chore. The only client configuration necessary is to configure the client network interfaces for DHCP. This example is for Debian:
iface lo inet loopback
iface eth0 inet dhcp
On Fedora, each interface has its own separate configuration file:
One last chore before you leave your client PCs is to collect MAC addresses. Do this with the ifconfig command:
$ ifconfig -a|grep -i hwaddr
eth0 Link encap:Ethernet HWaddr 00:03:6D:00:83:CF
Record the MAC and the machine it belongs to, because it's the key to configuring all your PCs from Dnsmasq.
Auto-configuration From Dnsmasq
Always put static IP addresses on servers. Workstations and laptops don't need to have static addresses, but you can do what you want. /etc/hosts needs only hostnames, except localhost which you can leave as it's shown here:
127.0.0.1 localhost.localdomain localhost
Now edit /etc/dnsmasq.conf. This example shows how to use Dnsmasq to control all the client network configurations:
#match hostname to MAC address
Isn't this way more fun than messing with BIND and dhcpd3? In this tiny example a whole lot of things are happening:
domain-needed prevents hostnames from being forwarded- they must be fully-qualified domain names.
bogus-priv prevents non-routable addresses from being forwarded outside your network. These two options prevent bad DNS traffic from escaping your network and burdening public DNS servers with unresolvable inquiries.
expand-hosts and domain allow you to set your domain name in dnsmasq.conf, and it will be automatically appended to the hostnames in /etc/hosts. Because this is for private DNS only, your internal domain name can be anything you want, and you don't have to register it.
interface tells Dnsmasq which interface to listen to, since routers are multihomed. Don't leave it open to the outside world.
dhcp-range is the available pool of addresses. This example is rather small; you can make it whatever you want.
local is another directive that ensures private requests are handled internally. Any domains listed here will be answered only from /etc/hosts or DHCP.
The next directive always assigns the hostname "stinkpad" to the interface with the MAC address 11:22:33:44:55:66, with a 168-hour DHCP lease.
The last directive assigns the same hostname and IP address to the interface with the MAC address 22:33:44:55:66:77, with an infinite lease. This is just like configuring a static IP address directly on uberpc, with one important difference: if your Dnsmasq server is unavailable, uberpc won't have network.
Your Dnsmasq server can go on your Internet router, or it can be on a machine inside your LAN. The easy way is to put it on your router. If you're running an iptables firewall like a good Linux geek, you may need some rules to allow your LAN hosts access to Dnsmasq:
$ipt -A INPUT -p udp -i $LAN_IFACE -s 192.168.1.0/24 --dport 53 -j ACCEPT
$ipt -A INPUT -p tcp -i $LAN_IFACE -s 192.168.1.0/24 --dport 53 -j ACCEPT
$ipt -A INPUT -p udp -i $LAN_IFACE --dport 67 -j ACCEPT
Whatever firewall you are running, you may need to open to the LAN UDP and TCP ports 53 for DNS, and UDP port 67 for DHCP. Be careful you don't expose your Dnsmasq services to the outside world- limit it to the LAN interface.
Your LAN hosts should be able to ping each other by both hostname and fully-qualified domain name:
$ ping uberpc
$ ping uberpc.alrac.net
You should have Internet access, provided you had it before. Run netstat on the Dnsmasq server to verify that it is listening on ports 53 and 67:
# netstat -untap
Use dig to test the local caching resolver:
$ dig @dnsmasq yahoo.com
Now your internal hosts can communicate with each via their hostnames. You'll appreciate this all the more when you implement IPv6, and have those long hexadecimal addresses to deal with.
Other DNSmasq Abilities
Dnsmasq supports all the usual DNS records: MX, SRV, SPF, and it automatically caches A, AAAA, and PTR records. You may use it as only a caching resolver and use a different server, like MaraDNS, for authoritative public DNS services. It supports BOOTP for netbooting and diskless clients. See the good documentation and configuration files to learn all about these.