I've been using pdnsd for DNS caching for quite a while now and I can feel the speed up while browsing the web (at least I can go on believing so ;)) or checking for updates in the AUR.

The problem with pdnsd in conjunction with mobile devices (like the netbook I'm typing this on) is that in the basic setup it only uses static DNS servers described in /etc/pdnsd.conf. So if you happen to get behind some firewall that doesn't permit DNS queries to nameservers other than the ones advertised by DHCP, you have to change your setup manually - and switch back when you're out.

It would be great if pdnsd took the DNS your machine got via DHCP and use it as upstream for cache misses. This would also make use of eventually existing DNS caches of the local infrastructure instead of bypassing them.

Here's how I implemented that, using pdnsd and dhcpcd:

  1. Setup pdnsd as described in the Arch Wiki, but do not create a /etc/resolv.conf.head. Create a primary DNS source entry, mine looks like this:

    server {
        label="maindns";
        ip=8.8.8.8, 8.8.4.4;  # I use Google DNS as fallback
        proxy_only=on;        # Do not query any other name servers
        timeout=4;            # Server timeout
        uptest=none;          # No uptest
        purge_cache=off;      # Keep stale cache entries in case the ISP's
                              # DNS servers go offline.
    }
    
  2. In /etc/resolv.conf, the only nameserver should be your local machine:

    # /etc/resolv.conf
    nameserver 127.0.0.1
    
  3. In /etc/dhcpcd.conf, disable the resolv.conf-hook to prevent dhcpcd from changing the resolving scheme:

    [...]
    nohook resolv.conf
    
  4. In /usr/lib/dhcpcd/dhcpcd-hooks, we create a hook script (e.g. 21-pdnsd.conf) that uses pdnsd-ctl to override the nameserver IPs defined in /etc/pdnsd.conf with the ones received by DHCP:

    # Set the IP of "maindns" entry for pdnsd
    
    case "$reason" in
        BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC)
            SRVS=""
            for X in $new_domain_name_servers; do
                if [ -z "$SRVS" ]; then
                    SRVS="$X"
                else
                    SRVS="${SRVS},$X"
                fi
            done
            pdnsd-ctl server 0 up $SRVS
            ;;
        PREINIT|EXPIRE|FAIL|IPV4LL|NAK|NOCARRIER|RELEASE|STOP)
            # reset to values in /etc/pdnsd.conf
            pdnsd-ctl config
            ;;
    esac
    

If you find any issues or disadvantages with this setup, feel free to post them in the comments!