惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

I
InfoQ
S
SegmentFault 最新的问题
N
Netflix TechBlog - Medium
B
Blog
Jina AI
Jina AI
人人都是产品经理
人人都是产品经理
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园 - 聂微东
Last Week in AI
Last Week in AI
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
V2EX
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
大猫的无限游戏
大猫的无限游戏
U
Unit 42
J
Java Code Geeks
IT之家
IT之家
aimingoo的专栏
aimingoo的专栏
博客园 - 叶小钗
T
The Blog of Author Tim Ferriss
博客园 - 【当耐特】
Hugging Face - Blog
Hugging Face - Blog
WordPress大学
WordPress大学
腾讯CDC

dnsmasq-discuss

[Dnsmasq-discuss] Announce: dnsmasq-2.92rc2 Re: [Dnsmasq-discuss] [PATCH] Fix arguments order for chaos subdomain check Re: [Dnsmasq-discuss] patch: block-file/allow-file - for review/feedback Re: [Dnsmasq-discuss] patch: block-file/allow-file - for review/feedback Re: [Dnsmasq-discuss] patch: block-file/allow-file - for review/feedback Re: [Dnsmasq-discuss] patch: block-file/allow-file - for review/feedback [Dnsmasq-discuss] patch: block-file/allow-file - for review/feedback Re: [Dnsmasq-discuss] server= with interface parameter changes behavior over time [Dnsmasq-discuss] NFTsets and hosts-files [Dnsmasq-discuss] [PATCH] Allow expired RRSIGs when stale caching is enabled [Dnsmasq-discuss] [PATCH] Fix local host records being overridden by upstream NXDOMAIN [Dnsmasq-discuss] [PATCH] Fix arguments order for chaos subdomain check Re: [Dnsmasq-discuss] Malformed RRSIG Can Crash dnsmasq [Dnsmasq-discuss] Malformed NSEC/NSEC3 Can Hang dnsmasq [Dnsmasq-discuss] Malformed RRSIG Can Crash dnsmasq [Dnsmasq-discuss] Security - IMPORTANT Re: [Dnsmasq-discuss] Issue with circuit-id matching on dhcp requests Re: [Dnsmasq-discuss] Issue with circuit-id matching on dhcp requests Re: [Dnsmasq-discuss] Issue with circuit-id matching on dhcp requests [Dnsmasq-discuss] Issue with circuit-id matching on dhcp requests Re: [Dnsmasq-discuss] [PATCH] bpf.c: fix memory leak in arp_enumerate() on BSD Re: [Dnsmasq-discuss] [PATCH] bpf.c: fix memory leak in arp_enumerate() on BSD Re: [Dnsmasq-discuss] dnssec problem here and now Re: [Dnsmasq-discuss] dnssec problem here and now [Dnsmasq-discuss] dnssec problem here and now Re: [Dnsmasq-discuss] server= with interface parameter changes behavior over time Re: [Dnsmasq-discuss] [PATCH] bpf.c: fix memory leak in arp_enumerate() on BSD Re: [Dnsmasq-discuss] [PATCH] bpf.c: fix memory leak in arp_enumerate() on BSD Re: [Dnsmasq-discuss] [PATCH] Preserve existing log file permissions when adding group-write bit. [Dnsmasq-discuss] server= with interface parameter changes behavior over time
[Dnsmasq-discuss] Don't mix local (hosts/DHCP/config) rec...
Dominik Derigs via Dnsmasq-discuss · 2026-06-20 · via dnsmasq-discuss
Hi Simon, all,

we have run into a case where dnsmasq returns an authoritative local record
together with a cached upstream record for the same name, and additionally
forwards the query upstream even though it already has a local answer.

It happens when an upstream answer for a name is cached before a local record for that same name comes into existence, which is easy to hit with a hostsdir: adding or modifying a hosts file there triggers an inotify reload of just that
file, without flushing the rest of the cache. The previously cached upstream
record stays around (and, with --use-stale-cache, lingers as a stale entry once its TTL passes). On the next query, answer_request() walks the whole cache chain
for the name and adds both records to the reply; the expired upstream record
also sets *stale, which forwards the query to refresh it.

A restart clears the cache and the symptom disappears until the name is resolved
upstream again, which is what makes it look intermittent.

Minimal reproducer (two loopback instances, no real network):

  # upstream, authoritative for repro.test with a short TTL
  dnsmasq --port=5392 --listen-address=127.0.0.1 --bind-interfaces \
          --no-resolv --no-hosts --keep-in-foreground \
          --address=/repro.test/192.0.2.50 --local-ttl=2 &

  mkdir -p /tmp/hd
  # under test
  dnsmasq --port=5391 --listen-address=127.0.0.1 --bind-interfaces \
          --no-resolv --no-hosts --keep-in-foreground \
          --server=127.0.0.1#5392 --hostsdir=/tmp/hd \
          --use-stale-cache=3600 --log-queries=extra &

  dig +short @127.0.0.1 -p 5391 repro.test A      # prime cache -> 192.0.2.50
  echo "192.168.0.99 repro.test" > /tmp/hd/custom.list
  sleep 4                                          # let the upstream entry go stale
  dig +noall +answer @127.0.0.1 -p 5391 repro.test A

Before the patch the final answer contains both 192.168.0.99 (local) and
192.0.2.50 (stale upstream), and the log shows the query being forwarded. After
the patch only 192.168.0.99 is returned, with no forward.

The fix relies on cache_find_by_name() returning all local
(F_HOSTS/F_DHCP/F_CONFIG) records for a name ahead of any cached records: once a local record has answered, stop at the first non-local record so it is neither added to the reply nor allowed to set *stale. Multiple local records, and the
normal case of multiple cached upstream records with no local record, are
unaffected.

Patch attached.

Warm regards,

Dominik
From 4b902310c30b81e6cb0652d5c264f40cb260fb81 Mon Sep 17 00:00:00 2001
From: Dominik Derigs <[email protected]>
Date: Fri, 19 Jun 2026 20:32:41 +0200
Subject: [PATCH] Don't mix local (hosts/DHCP/config) records with cached
 upstream data

When a name has an authoritative local record (from /etc/hosts, a
hostsdir file, DHCP or a config "address") and a record for the same
name is also present in the cache from earlier upstream resolution,
answer_request() walked the entire cache chain for that name and added
both to the reply. With --use-stale-cache the expired upstream record
additionally set *stale, triggering a needless upstream refresh even
though an authoritative local answer was available.

This is reachable whenever an upstream answer is cached before the local
record exists, e.g. a hostsdir file is created or modified at run time:
the inotify reload re-reads that hosts file but does not flush the rest
of the cache. The client then receives both the local address and a
stale upstream address, and the query is forwarded. Flushing the cache
(a restart) hides it until the name is resolved upstream again.

cache_find_by_name() returns all local (F_HOSTS/F_DHCP/F_CONFIG) records
for a name ahead of any cached records. So once a local record has
answered, stop at the first non-local record: do not add it to the reply
and do not let it set *stale.
---
 src/rfc1035.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/rfc1035.c b/src/rfc1035.c
index 16df1b1..5534446 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -2028,6 +2028,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
 		  crecp = save;
 		}
 	      
+	      /* An authoritative local record (/etc/hosts, DHCP or config) must
+		 not be mixed in a reply with cached upstream records for the same
+		 name. cache_find_by_name() returns all local records ahead of any
+		 cached records, so remember whether we started from a local one. */
+	      int local_auth = (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) != 0;
+
 	      /* If the client asked for DNSSEC  don't use cached data. */
 	      if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
 		  (rd_bit && (!do_bit || cache_not_validated(crecp)) ))
@@ -2035,6 +2041,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
 		  { 
 		    int stale_flag = 0;
 		    
+		    /* Once a local record has answered, stop at the first cached
+		       upstream record: don't add it to the reply and don't let it
+		       trigger a stale refresh (which would forward the query). */
+		    if (local_auth && !(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
+		      break;
+
 		    if (crec_isstale(crecp, now))
 		      {
 			if (stale)
-- 
2.43.0

_______________________________________________
Dnsmasq-discuss mailing list
[email protected]
https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss