Version française

/etc/resolv.conf Tips and Tricks under GNU/Linux

By default, DNS resolution is done by using the UDP transport layer. However I have noticed that on some network with a WiFi connection, this often yields a 5-second timeout before the resolution is automatically retried, whatever the DNS servers, including the DNS server provided by the ADSL modem router. I sometimes got two timeout in a row, so that DNS resolution could take 10 seconds! This issue is worsened by the fact that GNU/Linux does not use a local DNS cache by default.

Thus I wanted to try DNS with the TCP transport layer. For that, one can use the undocumented use-vc option. However not all DNS servers support TCP, and in particular, this did not work with the DNS server of the modem router or the ones of the ISP. Fortunately, this works with Google Public DNS. Here is the corresponding /etc/resolv.conf file:

options use-vc
nameserver 8.8.8.8
nameserver 8.8.4.4

Then, one may want to use this configuration (or another one) only on some given networks. While some network management tools allow one to specify the name servers for some given networks, I have not seen a way to give options like the use-vc one. There are several alternative solutions. Except when mentioned, resolvconf is assumed not to be used, otherwise there may be some clashes. Ditto for local DNS caches.

Now, for DHCP (usual case), there is another problem: the /etc/resolv.conf file is normally rewritten when the lease is renewed, meaning that the user's configuration done above is overwritten. For Internet Software Consortium's DHCP client, a solution is to prevent this from occurring on the concerned networks by redefining the make_resolv_conf shell function in an enter hook script for RENEW.

Here is an example of a DHCP hook script for both BOUND and RENEW (one may need to add other reasons, but they do not occur for me, so that I could not test them), to be used as both an enter hook script and an exit hook script. The make_resolv_conf function is executed by dhclient-script just after the enter hook scripts; for BOUND, when this script is run as an exit hook script, we do the same thing and execute this function.

#!/bin/sh

if [ ! -L /etc/resolv.conf ]; then

  logger "$1 with reason=$reason"

  # the MAC address of the router
  mac=00:1f:33:89:73:4e

  case "$reason" in
    BOUND)
      # The ping has an effect to fill the ARP table "/proc/net/arp".
      # This trick is inspired by:
      #   https://www.debian-fr.org/serveur-dns-timout-resolv-conf-et-dhclient-t24401.html
      # In 2015-08, this was working as an enter hook, but in 2016-08,
      # the ping fails (ditto with arping, after trying various options).
      # So, this script should be used as an exit hook too.
      ping -n -c 1 -I "$interface" "$new_routers" > /dev/null
      if grep -i -q $mac /proc/net/arp; then
        logger "Google Public DNS with TCP to avoid recurrent timeout"
        make_resolv_conf()
        {
          logger "creating /etc/resolv.conf (Google Public DNS with TCP)"
          cat > /etc/resolv.conf <<EOF
options use-vc
nameserver 8.8.8.8
nameserver 8.8.4.4
EOF
        }
        case $1 in
          */dhclient-exit-hooks.d/*) make_resolv_conf;;
        esac
      fi
      ;;
    RENEW)
      case $1 in
        */dhclient-enter-hooks.d/*)
          if grep -i -q $mac /proc/net/arp; then
            logger "do not overwrite /etc/resolv.conf"
            make_resolv_conf() { : ; }
          fi;;
      esac
      ;;
  esac

fi

Note: For the RENEW case, instead of testing the MAC address, one can also test the presence of some text in the /etc/resolv.conf file, e.g. do not overwrite on lease renewal, if such a text was written when the file was created.



webmaster@vinc17.org