How to configure DNS caching server with dnsmasq in RHEL

Solution Verified - Updated -

Environment

  • Redhat Enterprise Linux 6
  • Redhat Enterprise Linux 7
  • Redhat Enterprise Linux 8
  • Redhat Enterprise Linux 9
  • dnsmasq package

Issue

  • How to configure DNS caching server with dnsmasq in RHEL

Resolution

Preparation

  1. Ensure that dnsmasq is installed

    # yum -y install dnsmasq
    
  2. Choose a way to run dnsmasq for DNS caching:

Configure dnsmasq as a standalone service

  1. Create the configuration files /etc/dnsmasq.conf and /etc/resolv.dnsmasq. An example of each file is provided below. The /etc/resolv.dnsmasq file has the IP addresses of upper DNS servers which the dnsmasq service forwards queries to and caches replies from .

    • /etc/dnsmasq.conf

      domain-needed
      bogus-priv
      interface=lo
      bind-interfaces
      listen-address=127.0.0.1
      cache-size=1000
      resolv-file=/etc/resolv.dnsmasq
      no-poll
      ## Can append below two parameters to log host queries
      log-queries
      log-facility=/var/log/dnsmasq.log
      

      NOTE: In this configuration, we use the bind-interfaces option to make dnsmasq listen only on interface lo (address 127.0.0.1). This prevents possible conflicts with the libvirt package, since libvirtd uses dnsmasq as DNS and DHCP server for its virtual guests.

    • /etc/resolv.dnsmasq

      nameserver <IP address of an upper DNS server>
      nameserver <IP address of an upper DNS server>
      
  2. Under some circumstances (due to DHCP or other network configurations) nameserver lines in /etc/resolv.conf may be updated. Follow the instructions in this solution to prevent such changes from happening.

  3. Change /etc/resolv.conf to send all DNS queries to the loopback interface. If the file contains multiple nameserver entries remove them so only the one entry is left.
    NOTE: If you write the DNS information in the primary network interface file, you need to update the DNS options in the network file also.

    • /etc/resolv.conf

      nameserver 127.0.0.1
      options edns0
      

Note: options edns0 allows receiving bigger responses over UDP. It is not strictly necessary, but dnsmasq has got better failover algorithm for UDP queries than for TCP retries. It has also higher performance. It is recommended to use it whenever it works.

  1. Enable and start the dnsmasq.service.

    • RHEL6

      # chkconfig dnsmasq on
      # service dnsmasq start
      

      It will likely show a message like this:

      dnsdomainname: Host name lookup failure
      

      This is harmless. It happens because the dnsmasq init script uses the dnsdomainname command, which in its turn depends on DNS resolution, creating a circular dependence.

    • RHEL7, RHEL8 and RHEL 9

      # systemctl enable dnsmasq.service
      # systemctl start dnsmasq.service
      

Configure dnsmasq to run under control of NetworkManager

  1. Create a /etc/NetworkManager/conf.d/dns.conf file, configuring NetworkManager to enable DNS caching via dnsmasq:

    [main]
    dns=dnsmasq
    
  2. Restart NetworkManager:

    # systemctl restart NetworkManager
    
  3. Ensure that NetworkManager started properly and is using dnsmasq

    # systemctl status NetworkManager
    

    The status must be loaded/active and the command /usr/sbin/dnsmasq must be running.

  4. Additional dnsmasq configuration can be placed into /etc/NetworkManager/dnsmasq.d/ directory

Root Cause

  • By default RHEL doesn't cache DNS queries.

Diagnostic Steps

  1. Install the tcpdump package on a terminal (Term A)

    # yum -y install tcpdump bind-utils
    
  2. Open another terminal session (Term B) and run the following command as root.

    # tcpdump -n port 53
    
  3. Run the following command twice on the terminal (Term A) and confirm that tcpdump shows 1 DNS query to your upper DNS server in Term B

    # getent ahosts www.redhat.com
    # getent ahosts www.redhat.com
    

If DNS caching is working there should be only one DNS query/response pair in the tcpdump output.

NOTE: Some websites or domain names have multiple IP address families associated with them. For that reason and other reasons, tcpdump may show multiple queries.

  1. Run following commands twice to see remaining time of record in the cache. Remaining time after the name should decrease the second time, which means original answer is still in the cache and were not forwarded again.

    # dig +ttlunits +noall +answer @127.0.0.1 example.org
    # sleep 5
    # dig +ttlunits +noall +answer @127.0.0.1 example.org
    
  2. If that is not enough, uncomment log-queries option in /etc/dnsmasq.conf and restart dnsmasq service. Then every query gets logged and explains which servers it were forwarded to or if the cached results were used.

NOTE: logging every query decreases dnsmasq performance and might also have privacy implications. It would also significantly increase the log size. Its use is recommended only when analysing issues with dnsmasq.

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

Comments