This is part 5 of the router series; part 1, part 2, part 3 and part 4 are also available.
In the fifth part of this tutorial I am going to show how to configure dnsmasq to hand out IP addresses to your LAN clients as well as setting up dnsmasq to act as a DNS caching server. It basically combines dhcpd and bind (or unbind) into a single executable. Although the latter are obviously battle-tested for large networks in the context of a home office or a small business it is probably easier to start with dnsmasq.
The configuration of dnsmasq resides in a single file, usually
/etc/dnsmasq.conf
. What we want to achieve is basically three things
- Hand out IP addresses to the clients that use DHCP.
- Cache DNS queries for the LAN
- Assign dynamic DNS entries for the DHCP clients.
dnsmasq configuration: /etc/dnsmasq.conf
The absolute minimum configuration to do the above is
# Interface to listen to
interface=eth1
# Default DNS servers
server=8.8.8.8
server=8.8.4.4
server=2001:4860:4860::8888
server=2001:4860:4860::8844
# Always expand the domain name
domain-needed
expand-hosts
bogus-priv
# The actual domain name
domain=home.net
domain-suffix=home.net
# Router advertisements for IPv6
enable-ra
# DHCP address allocation
# v4: START, END, NETMASK, LEASE DURATION
dhcp-range=192.168.1.50,192.168.1.150,255.255.255.0,24h
# and v6: START, END, MODE, LEASE DURATION
dhcp-range=2001:db8:0:0::a:0,2001:db8:0:0::a:ffff,ra-names,24h
# or if you have a dynamic IPv6 prefix it will be generated
# from the interface dnsmasq is bound to
# dhcp-range=::a:0,::a:ffff,constructor=eth1,ra-names,24h
# if you only want SLAAC then uncomment the following
# dhcp-range=::,slaac,ra-only
# Static DHCP configuration
# v4 example: MAC-ADDRESS, HOSTNAME, ADDRESS, LEASE DURATION
dhcp-host=00:11:22:33:44:55,host01,192.168.1.5,72h
# v6 example: id=DUID, HOSTNAME, ADDRESS, LEASE DURATION
dhcp-host=id:aa:bb:cc:dd:ee:ff:00:11:22:33:44:55,host01,[2001:db8::7],72h
The configuration is practically split into two things: DNS and DHCP. The
most straightforward option is the interface that dnsmasq binds to and that is
given through the interface=eth1
option, eth1
being the LAN-facing card. I
will explain the rest options in the following sections. You might also want to
add your domain name using the domain=
option. If you don’t own one just
make it up!
DNS caching
We will use dnsmasq as a kind of DNS caching proxy. Instead of having the
clients resolve hostnames directly on the external DNS server we will have
dnsmasq do the task. This takes advantage of caching and once a name has been
resolved it will be done instantly the next time is requested again. The
difference between 1 and 40 ms might not be significant but remember that web
pages nowadays can do easily upwards of 60 DNS queries for a single page load
(yes I lament that too, but oh well). In that case every bit counts. The
upstream DNS servers are configured in the server=
entries. In this case we
are using the Google DNS but feel free to use anyone you like, for example your
ISP’s. In contrast to the requirement of some C libraries that
/etc/resolv.conf
can hold a limited amount of nameserver
entries there is
no such restriction for dnsmasq.
In order to finalise the DNS caching configuration you must ensure that there
is one and only one nameserver
entry in the /etc/resolv.conf
. This will
ensure that all DNS queries made will pass through dnsmasq. If a hostname is
cached it will be returned instantly; if not it will be forwarded upstream. You
now only have to point the LAN members to use the IP address of your router as
a DNS server. That is for the hosts that have static IP configurations. If you
are using DHCP (up next!) dnsmasq will care of that!
And that’s it basically; you can now take advantage of the DNS caching feature of dnsmasq.
DHCP server: IPv4 edition
The reset of the configuration deals with DHCP and DHCPv6. The IPv4 case is
really straighforward: through the dhcp-range
option you just specify the
initial address, final address, netmask and lease duration. For 90% of your
IPv4 needs you are practically set. If you have more elaborate setup feel free
to read the
manpage (warning:
although thorough, it’s huge). The nice thing is that dnsmasq will also
generate fully qualified domain names (FQDNs) for your DHCP hosts if their
hostname is known. For example if the computer with hostname foo
connects
through DHCP it will have the FQDN foo.home.net
assigned. No need to remember
these pesky numerical addresses. You also have the option of “pinning” some IP
addresses to hosts if you know their MAC address using the dhcp-host
option.
IPv6 address assignment: SLAAC and DHCPv6
At this point I would like to digress a bit and talk about automatic address
assignment on IPv6. There are practically two ways to autoconfigure the IP
addresses of the hosts. The first one is Stateless
Autoconfiguration (SLAAC). In sort SLAAC
allow hosts to configure themselves automatically without the use of a DHCP
server. To do so the router has to send out Router Advertisements ie. let the
hosts know some relevant details about the network the most important of which
is the IPv6 prefix (which is assigned with DHCPv6-PD; see part
3) on the LAN-facing interface, eth1
.
Then through the builtin IPv6 stack on your operating system’s kernel an
address will be generated automatically based on the MAC address of the host.
That is unless you have configured the so called Privacy
Extensions. In that case the actual
address is randomised by hashing the MAC address and the current timestamp.
Windows by default enable privacy extensions but on Linux (where they are
called temporary addresses) it depends on a sysctl parameter:
net.ipv6.conf.default.use_tempaddr
. This parameter takes three possible
values:
≤0
: No privacy extensions=1
: Enable but prefer a public address over the temporary>1
: Enable and prefer temporary addresses over any other
Basically if use_tempaddr
is 1 privacy extensions will be enabled but if
there is any other address available (remember interfaces can have many IPv6
addresses) it will be preferred. When use_tempaddr
is >1 privacy extensions
are always enforced and any other address is ignored when talking to the
internet.
DHCPv6, on the other hand, is a bit more complicated. In a sense it works similarly to DHCP for IPv4 however there are two different modes of operation stateless DHCPv6 and stateful DHCPv6. In the first case address allocation is done through SLAAC, as described above, and DHCP is only used to convey additional network information. Personally, I do not find any specific advantage of stateless DHCPv6 over SLAAC so I have not investigated further.
Stateful DHCPv6 works similarly to its IPv4 counterpart. You can allocate a block of addresses similar to the IPv4 and they are handed out as you would expect. In an ideal world DHCPv6 should cover your dynamic address needs. However things are never that easy and there are some caveats to stateful DHCPv6 most important of which is that ANDROID DOES NOT SUPPORT IT at ALL in any version! You can read more about it in this -now legendary- bug report over at Android’s issue tracker.
In conclusion the only viable way to have DHCPv6 support in your network is to
have both SLAAC and stateful DHCPv6 support in your gateway. In that case every
host will be assigned two IPv6 addresses one through SLAAC and one through the
DHCPv6 allocation pool. If you set use_tempaddr
to be 0 or 2 in linux you
will get to use that one instead of the SLAAC address, although your host will
reachable by both. Devices that do not support DHCPv6 will only get the SLAAC
address. Fortunately dnmsasq will generate DNS domain names for both of these
cases.
So we have the following distinct cases for SLAAC/DHCPv6.
SLAAC only
You need the following options for this configuration.
enable-ra
dhcp-range=::,ra-only
SLAAC/Stateless DHCPv6
This case is a hybrid between SLAAC and DHCPv6. Address assignment will be done through SLAAC and dnsmasq will try to assign a domain name. This is a good compromise if you want only SLAAC but some degree of domain name assignment.
enable-ra
dhcp-range=::,ra-stateless,ra-names
SLAAC and Stateful DHCPv6
Hosts will have two addresses, one from SLAAC and one from DHCPv6. dnsmasq will
try to assign a domain name through the DHCP assigned address or if it’s not
ping
able through the autogenerated SLAAC address. Of course this will not work
with privacy extensions.
enable-ra
# slaac is optional here as it has no additional effect
dhcp-range=2001:db8:0:0::a:0,2001:db8:0:0::a:ffff,ra-names,slaac,24h
If you do not have a static IPv6 prefix dnsmasq can generate a range of
addresses by using the prefix of your LAN-facing interface. If that is the case
with your network replace the dhcp-range
with the following
# again slaac is optional
dhcp-range=::a:0,::a:ffff,constructor=eth1,ra-names,slaac,24h
Stateful DHCPv6 only
If you are not going to have any Android hosts on your network you can switch
dnsmasq to stateful DHCPv6 operation. To do so just do not use any option in
the dhcp-range
line and remove enable-ra
.
dhcp-range=2001:db8:0:0::a:0,2001:db8:0:0::a:ffff,24h
Finally there is the issue of static IPv6 assignment. You should be now aware that address pinning is not as straightforward with IPv6 as in the IPv4 case. It should be clear that is impossible to do so with SLAAC as the address is configured on the client side so this can only be achieved with DHCPv6. Once again things are not that straightforward. In contrast to DHCP there is no MAC address propagation when a client contacts the DHCPv6 server. There is, however, the so-called DHCP Unique Identifier (DUID) which is sent by the client to request an IPv6 address from the DHCPv6 server. The DUID is generated by the dhcp client so its value depends on what dhcp cliet you are using.
- For dhclient it’s
/etc/dhcp/dhclient6.conf
- For dhcpcd it’s
/etc/dhcpcd.duid
- For dibbler it’s
/var/lib/dibbler/client-duid
- If you are using NetworkManager you will find it in
/var/lib/NetworkManager/dhclient6
. In contrast to all the other cases NetworkManager is using octal representation but you can decode it using the script found in this askubuntu.com thread. - On Windows is found in the registry under
HKLM > System > CurrentControlSet > services > TCPIP6 > Parameters
although I never managed to make static DHCPv6 assignment work properly.
If you find your DUID you can use it similarly to how you use the MAC address
for DHCP but don’t forget to prefix it with id:
.
dhcp-host=id:aa:bb:cc:dd:ee:ff:00:11:22:33:44:55,host01,[2001:db8::7],72h
That’s pretty much it for DNS and DHCP. Although things are pretty straightforward with IPv4 the complexity of the many IPv6 layers make address assignment more complicated. If you want to keep things simple go just with SLAAC and don’t look back. In any case I strongly urge you to take a look at the dnsmasq manpage as there is a wealth of information to manage your network.
This concludes part 5. As usual if you are following this guide with Alpine
linux don’t forget to commit your changes with lbu commit
.