+++ title = "using unbound and dnsmasq" date = "2014-12-09T22:13:58+00:00" author = "Gibheer" draft = false +++ After some time of using an [Almond](http://www.securifi.com/almond) as our router and always having trouble with disconnects, I bought a small [apu1d4](http://www.pcengines.ch/apu1d4.htm), an AMD low power board, as our new router. It is now running FreeBSD and is very stable. Not a single connection was dropped yet. As we have some services in our network, like a fileserver and a printer, we always wanted to use names instead of IPs, but not a single router yet could provide that. So this was the first problem I solved. FreeBSD comes with unbound preinstalled. Unbound is a caching DNS resolver, which helps answer DNS queries faster, when they were already queried before. I wanted to use unbound as the primary source for DNS queries, as the caching functionality is pretty nice. Further I wanted an easy DHCP server, which would also function as a DNS server. For that purpose dnsmasq fits best. There are also ways to use dhcpd, bind and some glue to get the same result, but I wanted as few services as possible. So my setup constellation looks like this: client -> unbound -> dnsmasq +-----> ISP dns server For my internal tld, I will use zero. The dns server is called cerberus.zero and has the IP 192.168.42.2. The network for this setup is 192.168.42.0/24. ## configuring unbound For this to work, first we configure unbound to make name resolution work at all. Most files already have pretty good defaults, so we will overwrite these with a file in `/etc/unbound/conf.d/`, in my case `/etc/unbound/conf.d/zero.conf`. server: interface: 127.0.0.1 interface: 192.168.42.2 do-not-query-localhost: no access-control: 192.168.42.0/24 allow local-data: "cerberus. 86400 IN A 192.168.42.2" local-data: "cerberus.zero. 86400 IN A 192.168.42.2" local-data: "2.42.168.192.in-addr.arpa 86400 IN PTR cerberus.zero." local-zone: "42.168.192.in-addr.arpa" nodefault domain-insecure: "zero" forward-zone: name: "zero" forward-addr: 127.0.0.1@5353 forward-zone: name: "42.168.192.in-addr.arpa." forward-addr: 127.0.0.1@5353 So what happens here is the following. First we tell unbound, on which addresses it should listen for incoming queries. Next we staate, that querying dns servers in localhost is totally okay. This is needed to later be able to resolve addresses on the local dnsmasq. If your dnsmasq is running on a different machine, you can leave this out. With `access-control` we allow the network `192.168.42.0/24` to query the dns server. The next three lines tell unbound, that the name cerberus and cerberus.zero are one and the same machine, the DNS server. Without these two lines unbound would not resolve the name of the local server, even if its name would be stated in `/etc/hosts`. With the last line we enable name resolution for the local network. The key domain-insecure tells unbound, that this domain has no support for DNSSEC. DNSSEC is enabled by default on unbound. The two `forward-zone` entries tell unbound, where it should ask for queries regarding the `zero` tld and the reverse entries of the network. The address in this case points to the dnsmasq instance. In my case, that is running on localhost and port 5353. Now we can add unbound to `/etc/rc.conf` and start unbound for the first time with the following command $ sysrc local_unbound_enable=YES && service local_unbound start Now you should be able to resolve the local hostname already $ host cerberus.zero cerberus.zero has address 192.168.42.2 ## configuring dnsmasq The next step is to configure dnsmasq, so that it provides DHCP and name resolution for the network. When adjusting the config, please read the comments for each option in your config file carefully. You can find an example config in `/usr/local/etc/dnsmasq.conf.example`. Copy it to `/usr/local/etc/dnsmasq.conf` and open it in your editor: port=5353 domain-needed bogus-priv no-resolv no-hosts local=/zero/ except-interface=re0 bind-interfaces local-service expand-hosts domain=zero dhcp-range=192.168.42.11,192.168.42.200,255.255.255.0,48h dhcp-option=option:router,192.168.42.2 dhcp-option=option:dns-server,192.168.42.2 dhcp-host=00:90:f5:f0:fc:13,0c:8b:fd:6b:04:9a,sodium,192.168.42.23,96h First we set the port to 5353, as defined in the unbound config. On this port dnsmasq will listen for incoming dns requests. The next two options are to avoid forwarding dns requests needlessly. The option `no-resolv` avoids dnsmasq knowning of any other dns server. `no-hosts` does the same for `/etc/hosts`. Its sole purpose is to provide DNS for the local domain, so it needn't to know. The next option tells dnsmasq for which domain it is responsible. It will also avoid answering requests for any other domain. `except-interfaces` tells dnsmasq on which interfaces _not_ to listen on. You should enter here all external interfaces to avoid queries from the wide web detecting hosts on your internal network. The option `bind-interfaces` will try to listen only on the interfaces allowed instead of listening on all interfaces and filtering the traffic. This makes dnsmasq a bit more secure, as not listening at all is better than listening. The two options `expand-hosts` and `domain=zero` will expand all dns requests with the given domain part, if it is missing. This way, it is easier to resolv hosts in the local domain. The next three options configure the DHCP part of dnsmasq. First is the range. In this example, the range starts from `192.168.42.11` and ends in `192.168.42.200` and all IPs get a 48h lease time. So if a new hosts enters the network, it will be given an IP from this range. The next two lines set options sent with the DHCP offer to the client, so it learns the default route and dns server. As both is running on the same machine in my case, it points to the same IP. Now all machines which should have a static name and/or IP can be set through dhcp-host lines. You have to give the mac address, the name, the IP and the lease time. There are many examples in the example dnsmasq config, so the best is to read these. When your configuration is done, you can enable the dnsmasq service and start it $ sysrc dnsmasq_enable=YES && service dnsmasq start When you get your first IP, do the following request and it should give you your IP $ host $(hostname) sodium.zero has address 192.168.42.23 With this, we have a running DNS server setup with DHCP.