Handing a client a resolver address settles where queries are sent, not which source the resolver will see. Routing, forwarding and translation each get a turn between the two ends. A runbook for source questions follows the query hop by hop and records what each observer actually saw. The order matters, because a claim made before the observation is just a guess with better formatting.

Write down the arrangement before you collect evidence

Four places can tell you something about a DNS source, and they do not all tell you the same thing. The client kernel knows which source it would use, a forwarder knows what it sent upstream, a translating device knows what it rewrote, and the receiving resolver knows what arrived. Write down which of those you can actually reach before you collect anything.

Observation pointWhat it can proveWhat it cannot proveHow to read it
client kernelwhich source address it would use for that resolveranything a device in between rewroteip route get against the resolver address
forwarderthat it sent an upstream query, and from which sourcewhat the client originally asked forits own log and its cache state
translating devicethat a source was rewritten, and to whatwhether the query was legitimateNAT policy and its counters
receiving resolverthe address that actually arrivedwhich client behind that address askeda scoped capture on port 53

Write your expectation down as well, including the resolver you believe is in use. A split route can send a query somewhere else entirely, and a cache can answer with no upstream exchange at all, so an assumption held only in memory will not survive the first surprise. Keep the stated design and the observed path in separate columns of the same note; when the two disagree, you have found the question worth chasing.

Check which process actually sent the query

Start at the client: record the resolver address, the query name and the time, then confirm which process sent it. The first line below names the process holding the UDP socket, which is the check this heading promises. If that process is a browser helper or a container runtime rather than the system resolver, the rest of the trace describes a path nobody asked about.

ss -tunp 'dport = :53'
dig @10.20.30.53 host.corp.example +noall +answer
ip route get 10.20.30.53

On a host with several interfaces, find out which source address the kernel picks for that destination before you look anywhere else. That is the last point where the path is fully under your control, and it is the value you will compare with whatever the resolver reports. A mismatch is the signal that something in between rewrote the packet, or that two different queries were sent.

Keep the test names internal, since an internal name submitted to a public resolver proves nothing about the internal path and publishes a name you did not need to publish. A browser with secure DNS enabled will not appear in that socket list at all, and that absence is itself the answer.

The forwarder makes a second, separate query

A forwarder turns one exchange into two. The downstream request arrives, and the forwarder then sends its own query upstream from an address it chooses. Its configuration, not the client, decides what the upstream resolver sees.

The dnsmasq manual is worth reading for that reason: it documents how a forwarder selects upstream servers and binds its listening side, and nothing in that arrangement carries the client source upstream. A resolver log showing a gateway address is therefore normal rather than evidence of a fault. Absence is just as easy to misread, since a cache hit produces no upstream query and looks identical to a query that never arrived. Read the forwarder configuration and its cache state before drawing either conclusion. Two questions, two places to look.

Read the source at the receiving resolver

The only observation that settles this is taken on the server side. Anything inferred from the client interface list remains a hypothesis until the resolver reports what actually arrived.

tcpdump -ni any port 53 and host 10.20.30.53

Capture on the resolver host, keep the capture short and scoped, and store it where policy allows. If the observed source is a translated address, the next question is which device performed the translation and whether its policy is the intended one. A capture answers what arrived; it does not explain why the policy permitted it. Name the observer and the hop in the note, because a privacy claim about a gateway is a claim about that hop rather than about the whole path.

Write the finding as a path, not an address

Record the client, the resolver, any forwarder, the observed source at each hop and the policy that governs it. That record answers most future questions without another capture. Draw it as a chain, because a list of addresses hides which hop produced which one.

Attach the date, the client version and the configuration revision to the drawing, so a later reader can tell whether it still applies. Separate the transport source from everything else the service processes, since seeing a gateway address says nothing about what else is retained. A resolver location says nothing about which client asked, either. Keeping those claims apart is what makes the conclusion defensible under review.

Qillqakuna t'inkisqa