Skip to content
Search Rocky Linux

    Browse this documentation

    Rocky 10: a dnsmasq forwarder that would not cache

    A Rocky Linux 10.2 Server VM with dnsmasq-2.90-7.el10_2.

    This host is authoritative for nothing; it forwards to the LAN resolver (192.168.2.241) and caches the answers. Screenshot: public/evidence/dnsmasq/rocky-forwarder.png.

    /etc/dnsmasq.d/lab.conf
    listen-address=192.168.2.243
    bind-interfaces
    server=192.168.2.241
    no-resolv
    cache-size=1000
    log-queries
    • server=: the only upstream;
    • no-resolv: ignore /etc/resolv.conf so the system cannot override it;
    • cache-size=1000: cache entry limit;
    • log-queries: writes every query and cache hit to the journal — the switch that makes this debuggable.
    $ dig @192.168.2.243 c1.lab.test A +short
    $ dig @192.168.2.243 c1.lab.test A +short
    $ journalctl -u dnsmasq --since "-40s" --no-pager | grep -E "c1"
    ... dnsmasq[11792]: query[A] c1.lab.test from 192.168.2.243
    ... dnsmasq[11792]: forwarded c1.lab.test to 192.168.2.241
    ... dnsmasq[11792]: query[A] c1.lab.test from 192.168.2.243
    ... dnsmasq[11792]: cached c1.lab.test is 192.168.2.241

    Two query[A] lines, the first forwarded, the second cached — that is the reliable proof a cache works. dig’s Query time cannot show it: on a LAN both read 0 msec.

    In the first run both queries were forwarded, with no cached at all. The cause was upstream:

    $ dig @192.168.2.241 web.lab.test A +noall +answer
    web.lab.test. 0 IN A 192.168.2.241

    Records generated by address=/lab.test/… carry TTL 0, which downstream caches must not store — so every query goes back to the source.

    After adding local-ttl=60 upstream:

    $ dig @192.168.2.241 web.lab.test A +noall +answer
    web.lab.test. 60 IN A 192.168.2.241
    $ journalctl -u dnsmasq | grep c1 | tail -2
    ... query[A] c1.lab.test from 192.168.2.243
    ... cached c1.lab.test is 192.168.2.241

    Conclusion: when a forwarder “does not cache”, check the upstream TTL before touching cache-size.

    Rocky Linux 10.2: forwarded versus cached in the journal

    1) ss -lunp | grep ':53 ' # which address is bound (bind-interfaces = one)
    2) dig @<host> <name> A +noall +answer # what TTL the upstream really returns
    3) journalctl -u dnsmasq -n 20 # forwarded / cached / refused sources
    4) nft list ruleset | grep 53 # is the firewall dropping it

    Without log-queries, step 3 shows nothing — the most common time sink here.

    • Judging from a single query: cache hits need a second one;
    • Testing via 127.0.0.1: queries outside listen-address are refused and never even logged;
    • Upstream TTL 0: as above;
    • Writing only one of server= / no-resolv: the former missing means asking the system resolver, the latter means NetworkManager may override it.
    Terminal window
    for i in 1 2; do dig @192.168.2.243 d1.lab.test A +short; done
    sudo journalctl -u dnsmasq --since "-30s" --no-pager | grep -E "d1"
    sudo systemctl restart dnsmasq
    dig @192.168.2.243 d1.lab.test A +short # first query after restart is always forwarded

    Checks:

    1. At least the second of the two queries is cached;
    2. After a restart the first query is always forwarded (the cache is memory only);
    3. Changing the upstream TTL changes caching behaviour directly;
    4. No query line at all means the request never arrived (address or firewall).

    常见问题

    What cache-size should I use?

    A few thousand entries is plenty for small networks; the limiting factor is TTL, not capacity.

    Can different domains use different upstreams?

    Yes, dnsmasq 2.86+ supports per-domain forwarding: server=/example.com/1.1.1.1.

    Why is it slow right after a restart?

    The cache is in memory, so the first query always goes upstream — that is expected.