12 - Aug - 2026

I enabled DNS caching on my router and stopped waiting for pages to load

DNS lookups mean web pages can absolutely waste my time before they even download a single image. Typing in one address triggers DNS lookups for the site itself, images, analytics, advertisements, and whatever content delivery network it sits on.

On my home Starlink connection, every single upstream DNS trip adds latency. Browsers and operating systems do cache the answers privately, but those answers are local and not shared with the rest of the network.

I tried my hand at network-level caching using an OpenWRT router VM and a Windows 11 client. I measured what router-level caching actually achieves and what it removes in real-world testing.

The results were an eye-opener. Repeated lookups fell from a median of 24.35ms to 0.98ms. Most interesting of all was that Firefox actually exposed one modern DNS record that really needs to be cached to make a difference.

I started with a router that had nowhere to hide an answer

One fixed resolver and a cache-free baseline kept VMware from helping behind the scenes

My test router was a modest VM running an X86-64 version of OpenWRT and dnsmasq 2.93. Its WAN interface was set to receive an IP address 192.168.91.133 from VMware NAT, while its isolated LAN used 192.168.24.254. I also put a Windows 11 VM on the same VMnet as the router’s LAN adapter to act as the client.

Here’s how the setup looked:

Windows 11 VM: 192.168.24.138  [OpenWrt LAN: 192.168.24.254 | OpenWrt WAN: 192.168.91.133]  VMware NAT  Starlink

Windows received an IPv4 address and its fd25:b0d6:47f::1 ULA as DNS servers. That meant both IPv4 and IPv6 protocols were pointed at the same dnsmasq instance, but the upstream side introduced a common hurdle. VMware supplied 192.168.91.2 as a DNS proxy to OpenWRT, which cemented it in its automatically generated resolver file. If it remained this way, testing one cache through another would make the results look better than they were.

I configured Cloudflare’s 1.1.1.1 as the only upstream resolver and told dnsmasq to flat-out ignore that file. I also disabled DNS over HTTPS in Firefox, so the browser wouldn’t secretly bypass my OpenWRT configuration:

uci add_list dhcp.@dnsmasq[0].server='1.1.1.1'
uci set dhcp.@dnsmasq[0].noresolv='1'
uci set dhcp.@dnsmasq[0].cachesize='0'
uci set dhcp.@dnsmasq[0].logqueries='1'
uci commit dhcp
service dnsmasq restart

The zero-entry cache became my baseline, while query logging provided proof. I then tested the setup with two consecutive lookups for example.com, which sent fresh A and AAAA requests to Cloudflare both times. Logging confirmed that no responses were cached, and I could continue with the test.

Repeated DNS lookups fell from 24 milliseconds to under one

A 1,000-entry cache removed 96% of the resolver delay

With the network path under my control, I created a PowerShell script benchmark that covered 25 real domains, including but not limited to:

  • Wikipedia
  • GitHub
  • Netflix
  • MakeUseOf
  • PayPal
  • IMDB
  • Discord
  • Reddit

The script sent A-record queries directly to OpenWRT at 192.168.24.254, bypassing any uncertainty about which IPv4 or IPv6 DNS servers Windows happened to favor.

Each configuration received two passes through the same domain list in the same order. Before executing the script, I cleared Windows’ DNS cache with Clear-DnsClientCache, measured each request with a scripted stopwatch, and exported all 50 results to CSV. Everything else in the network chain remained unchanged.

$Timer = [System.Diagnostics.Stopwatch]::StartNew()

Resolve-DnsName `
    -Name $Domain `
    -Server 192.168.24.254 `
    -Type A `
    -DnsOnly `
    -NoHostsFile | Out-Null

$Timer.Stop()

After recording the zero-cache results, I enabled a 1000-entry cache on OpenWRT and restarted dnsmasq, which also emptied any previous entries:

uci set dhcp.@dnsmasq[0].cachesize='1000'
uci commit dhcp
service dnsmasq restart

Configuration

Pass

Average

Median

Cache disabled

1

26.06ms

24.53ms

Cache disabled

2

26.77ms

24.35ms

Cache enabled

1

25.42ms

23.85ms

Cache enabled

2

1.01ms

0.98ms

Both cold (no previous lookup) medians remained near 24ms, so just enabling caching alone didn’t magically improve the first pass. The difference appeared only after the router knew the answers from the previous lookup. The warmed (cached DNS) median fell by a significant 23.37ms, or 95.98%, and every cached result landed between 0.84 and 1.52ms.

Dnsmasq’s logs confirmed the same. The first A and AAAA requests were forwarded upstream, while every subsequent request got marked as cached:

daemon.info dnsmasq[1]: 119 192.168.24.138/60273 query[A] openwrt.org from 192.168.24.138 
daemon.info dnsmasq[1]: 119 192.168.24.138/60273 cached openwrt.org is 64.226.122.113 
daemon.info dnsmasq[1]: 120 192.168.24.138/60274 query[AAAA] openwrt.org from 192.168.24.138
daemon.info dnsmasq[1]: 120 192.168.24.138/60274 cached openwrt.org is 2a03:b0c0:3:d0::1a51:c001 

Interestingly, Windows did add one small distraction by attempting openwrt.org.lan before the public hostname. I accounted for this by adding a trailing dot so it was marked as authoritative:

nslookup openwrt.org. 192.168.24.254

Firefox found a DNS record my router wasn’t caching

Modern HTTPS queries kept reaching Cloudflare until I added them explicitly

Firefox DevTools benchmarking DNS with example.com

The PowerShell benchmarking looked promising, but I also wanted to test loading speeds in a real-world browser setting. This required a whole lot more preparation and care. I disabled Firefox’s DNS over HTTPS, cleared out its internal DNS cache, and disabled HTTP caching in DevTools.

I also started each navigation request from the Console rather than typing into the address bar. This was to stop Firefox from trying to resolve the hostname through speculative loading (when the browser starts looking up domain names before you hit enter).

Even then, Firefox occasionally reported dns_ms: 0, even after OpenWRT had clearly forwarded it a request. So, I treated dnsmasq’s logs as the actual evidence for this data.

Those logs ended up exposing a DNS query I hadn’t actually considered:

query[HTTPS] example.com
forwarded example.com to 1.1.1.1

This was an HTTPS DNS record. Modern browsers use this record for service and endpoint information, especially to determine whether certain protocols, including HTTP/3, are supported. The issue here was that dnsmasq defaults to only caching A, AAAA, CNAME, and SRV records. I needed to manually tell OpenWRT to specifically cache HTTPS too.

OpenWRT DNS cache arbitrary RR with HTTPS selected

Without this, Firefox would continue to send its HTTPS queries to Cloudflare, even after OpenWRT had cached the IPv4 and IPv6 addresses. I added this rule using the terminal and verified it in LuCI:

uci add_list dhcp.@dnsmasq[0].cache_rr='HTTPS'
uci commit dhcp
service dnsmasq restart

Then I verified the configuration before starting any more tests:

grep -R "^cache-rr=" /tmp/etc/dnsmasq.conf*

Which returned:

cache-rr=HTTPS
Firefox DevTools console with DNS benchmark testing for makeuseof.com no cache results

After that, all it took was one warm-up request, and dnsmasq cached all of Firefox’s HTTPS, A, and AAAA requests.

The importance of this change became quite apparent when trying to load the MakeUseOf website. With caching disabled, it generated 190 queries across 58 hostnames:

  • 85 AAAA
  • 71 A
  • 34 HTTPS
  • 0 cached

The warmed test generated 45 queries across 14 hostnames, representing a significant drop. Cache hits were logged as image hosts, CDN endpoints, and various Valnet infrastructure:

  • 3 featureassets.org
  • 2 static0.makeuseofimages.com
  • 2 makeuseofimages.b-cdn.net
  • 1 valnetcdn.b-cdn.net
  • 1 images.valnetcdn.com

With caching enabled on the router, Firefox no longer asked Cloudflare’s DNS for every part of the page.

DNS caching removed one delay, not the rest of the internet

Faster answers still leave TLS, servers, scripts, advertisements, and expiring records

Firefox loads the OpenWRT website while dnsmasq serves its A and HTTPS records from the router cache

The browser result was dramatic for sure. In the end, the warmed MakeUseOf page loaded 47% faster than the uncached attempt:

Measurement

Cache disabled

Warmed cached

TTFB

641ms

385ms

DOMContentLoaded

3.225 seconds

1.614 seconds

Load

7.041 seconds

3.725 seconds

Unfortunately, I can’t credit DNS caching with the entire improvement. Firefox continued to report connect_ms: 0 and dns_ms: 0 on some attempts, indicating speculative loading was still helping out occasionally.

Saving 23ms on several lookups also doesn’t necessarily remove their combined duration from the final page-load time. There’s still TLS negotiation, server processing, scripts, content to download, and all the components web servers need to serve a page.

The DNS cache is also temporary by design. For example, when example.com reaches its authoritative TTL (Time-To-Live), dnsmasq forwards the next request to Cloudflare. The duplicated request then immediately receives the next cached answer. Essentially, OpenWRT was accelerating its valid records, but it doesn’t preserve old addresses indefinitely.

Of course, none of that changes the controlled result. Repeated router lookups fell by 96%, and every client on the network benefits from the same shared answers. For my home network, a 1,000-entry cache was more than enough to deliver noticeably faster page load times across all devices.

In the end, DNS caching didn’t make the internet faster. It just stopped my router from asking the same questions every time I open a page — which is the next best thing.

Leave a Reply

Your email address will not be published. Required fields are marked *