System: Integrating resolvconf and pdnsd
In the 'good old days' your network was defined in /etc/network/interfaces, your DNS resolvers in /etc/resolv.conf, and if you wanted to install a DNS caching tool such as pdnsd it had its own stand-alone configuration.
More recently the picture has been complicated with the new resolvconf package which interacts in somewhat mysterious ways with networking and other services.
Updated network/interaces
If you have the resolvconf program installed DO NOT edit /etc/resolv.conf directly. Any changes you need to make there can be initiated by editing other configuration files as described below.
The main change is that your network settings now need to include details on name servers and search domains in /etc/network/interfaces:
# The primary network interface
auto eth0
iface eth0 inet static
address XX.XXX.XXX.XXX
netmask 255.255.255.0
gateway XX.XXX.XXX.1
dns-search example.net
dns-nameservers 8.8.8.8 8.8.4.4
The highlighted information was previously hardcoded into /etc/resolv.conf, but the idea now is that nameserver and search details can be bound to an interface. When an interface is brought up or down, resolv.conf will be automatically updated.
In this case we're using eth0.inet, but common variations can also include eth0.dhclient for DHCP interfaces, and eth0.inet6 for IPv6.
When the server is rebooted, networking restarted, or an interface activated using ifup or resolvconf -a (more on this later), these settings will be copied to /run/resolvconf/interface and used to generate a new /etc/resolv.conf.
For example, from the above definitions we get a new file generated:
/run/resolvconf/interface/eth0.inet
nameserver 8.8.8.8
nameserver 8.8.4.4
search example.net
All interface records in this directory are combined with the new resolvconf configuration files ('head', 'base' and 'tail') in /etc/resolvconf/resolv.conf.d to generate /etc/resolv.conf.
This is explained in more detail in the man page:
The dynamically generated resolver configuration file always starts with the contents of 'head' and ends with the contents of 'tail'. Between head and tail the libc script inserts dynamic nameserver information compiled from, first, information provided for configured interfaces; second, static information from 'base'.
There will be a limit of three (3) nameserver lines, and one (1) search line combining all search domains, making it into resolve.conf. The nameserver selection process is defined in /etc/resolvconf/interface-order, which you can explore at your own peril.
You should generally not edit 'head' or 'tail' and only use 'base' if you want to include option settings such as rotate or timeout.
If you've just upgraded to resolvconf there will also be a file 'original' containing a backup of your previous resolv.conf. This file is for your information only and is NOT active.
A lazy option is to just symlink 'tail' to 'original' so you never lose your pre-resolvconf settings. In this case you don't add dns-* lines to /etc/network/interfaces and instead just treat 'original' as if it was your old /etc/resolv.conf file.
Updating resolv.conf
There are at least three (3) recognised ways of updating /etc/resolv.conf which is now a symlink to the auto-generated file /run/resolvconf/resolve.conf.
- Reboot the server. This will take everything down, and when the interfaces are brought back up it will copy any new dns-* settings in /etc/network/interfaces to resolvconf;
- Bring the interface down and back up: ifdown eth0 && ifup eth0; or
- Add or overwrite the interface file using resolvconf -a as described below.
The old method of restarting networking has been deprecated and will not work, and running resolvconf -u will not recognise changes made in /etc/network/interfaces.
If you are working remotely then both rebooting and taking down your primary network interface are problematic as you can easily be locked out of the server. The third option is more complicated, but allows you to update resolv.conf without losing the network connection.
What you need to do is "echo" the relevant lines in resolv.conf format, and pipe it through resolvconf -a which will add or update the interface record and run the update scripts (assuming updating is enabled). For example:
echo "nameserver 8.8.8.8
nameserver 8.8.4.4
search example.net" | resolvconf -a eth0.inet
Make sure to include all relevant information (one entry per line) and to use the correct interface name at the end. You should have name server details assigned by your ISP or hosting provider. The name servers in the example above are for Google Public DNS.
Installing pdnsd
To speed up DNS queries on a busy server we install pdnsd as a proxy DNS server:
apt-get install pdnsd
At the prompt select Use resolvconf. You will see that the install files include:
- /etc/default/pdnsd
- /etc/pdnsd.conf
- /etc/resolvconf/update.d/pdnsd
First you need to edit /etc/default/pdnsd to enable the daemon by setting:
START_DAEMON=yes
We also edit /etc/pdnsd.conf to set:
server_ip = 127.0.0.3;
The effect on /etc/resolv.conf after starting or restarting pdnsd.service is as follows:
Before:
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 8.8.8.8
nameserver 8.8.4.4
search example.net
options rotate
options timeout:1
After:
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 127.0.0.3
search example.net
Note that we've removed the 'option' entries from the 'base' file as that functionality has been gazumped by pdnsd and no longer makes sense here as resolv.conf lists only one name server and we don't want it to time out.
What happened to the other name servers?
If you look in /run/resolvconf/interface you will see a new file lo.pdnsd containing just one line:
nameserver 127.0.0.3
Resolvconf detects 127.0.0.3 as a loopback address and according to the TRUNCATE_NAMESERVER_LIST_AFTER_LOOPBACK_ADDRESS environment variable no additional name servers are written after this address to /etc/resolv.conf because it's assumed the server knows what it's doing.
At the same time, when you (re-)start the pdnsd daemon it reads all the files in /run/resolvconf/interface (with the exception of lo.pdnsd) and adds them to the server with the label "resolvconf" in /etc/pdnsd.conf:
/etc/pdnsd.conf
...
server {
label="resolvconf";
proxy_only = on;
timeout = 2;
}
...
The highlighted lines here are optional.
You don't need to explicitly add name server addresses to /etc/pdnsd.conf as they will be taken from /run/resolvconf/interface, which in turn come from /etc/network/interfaces.
Checking your installation
To make sure that pdnsd is properly configured you can run pdnsd-ctl status and look in the output for:
...
Server 0:
------
label: resolvconf
ip: 8.8.8.8
server assumed available: yes
ip: 8.8.4.4
server assumed available: yes
...
If you don't see any ip addresses, or see 'no' in place of 'yes', then you have a problem. Start by checking the network settings, then resolvconf setting and finally pdnsd.
At the top of the output you will also see how much of the cache is being used. If it reaches 100% you need to increase the cache size to avoid cached entries being prematurely swapped out.
Finally, check that /etc/resolv.conf correctly lists the pdnsd ip address as the first, and ideally only, name server.
Dealing with IPv6
The resolvconf sorting rules in /etc/resolvconf/interface-order preference IPv6 addresses over IPv4, but by default pdnsd is not configured to recognise these addresses and will start in a broken state with no name servers.
The solution is to add to the /etc/pdnsd.conf 'global' configuration the line:
run_ipv4 = off;
The PDNSD server will now recognise IPv6 nameserver addresses, as well as prefixing any IPv4 addresses to convert them to IPv6. For example 127.0.0.3 becomes ::ffff:127.0.0.3.
Your /etc/resolv.conf output should now look like:
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver ::ffff:127.0.0.3
search example.net
If you have both IPv4 and IPv6 name servers they should all now appear in the output of pdnsd-ctl status in IPv6 notation.
In our case the server is not recognising ::ffff:127.0.0.3 as a loopback address so other IPv6 nameserver addresses are leaking into /etc/resolv.conf. This should be a matter of defining (somewhere??) ::ffff:127.0.0.3 as a loopback address.