[Dnsmasq-discuss] Conceptual patch to reject CNAME as NODATA

Josh Soref jsoref at gmail.com
Sun Nov 12 20:05:06 GMT 2017


Simon Kelley wrote:
> My feeling is that this is sensible. The patch does have flaws, as you
> fear. From inspection:
>
> 1) You're not checking the value of header->ancount, but assuming that
> it's one. It may be zero in the case of a NODATA reply, or it may be
> more than one, if the answer isn't a CNAME, or if the target of the
> CNAME is included.
>
> 2) So you need to iterate through all the RRs in the answer section,
> looking for a CNAME whose name matches the question.
>
> 3) This is probably better done in rfc1035.c, which where DNS packet
> code tends to exist.

Based on this feedback, I've migrated the code [1]. My general fears
still apply.

I'm now patching this codepath:
extract_addresses / !(qclass != C_IN) / !(qtype == T_PTR) /
cname_loop1 / header->ancount / aqtype == T_CNAME

I'm hoping that by migrating the code to the section I picked, this
should address (1) and (2). I'm really not certain about either. The
guard should at least cover header->ancount.

Note that in migrating, the variables don't line up perfectly (the
other site had cache_secure / this site has secure; the other site had
munged / this site only has doctored -- whose use I haven't spent much
time deciphering).

> Did you hit a real-world problem which inspired this?

Yes. I noted that I hit it [2]. (This is actually the bug that led me
to send the spelling patch -- I use spelling patches to test the
waters of projects before I write code patches.)

Roughly, I have split-horizon-dns with mostly macOS clients. macOS's
happy eyeballs dns resolution behavior more-or-less amounts to:
* when asked about a name, perform two parallel queries (A and AAAA)
* when receiving a CNAME response back, follow it
* even if the CNAME is a response to an AAAA and the CNAME record only
has an A, accept and include that answer when returning results to the
client†

split-horizon:
Internally:
gateway.example.com:
* IP: 10.0.0.1
* DHCP server for the intranet (running isc-dhcp-server) and points to
itself as the dns server
* DNS server for 10.* (running dnsmasq)
* Apache web server (:80,:443)
build.example.com:
* IP: 10.1.2.3
* web server (:80,:443)
* SSH server -- people expect to be able to ssh to it internally (they
don't have that expectation externally)

Externally:
gateway.example.com:
* IP: public IP address
* Apache web server(:80,443) set to do reverse proxying for various
sites (including build.example.com).
build.example.com:
* CNAME to gateway.example.com (because having it as an A would mean
that if I change the IP of gateway.example.com, I have to change 20
other records as well, which felt really annoying).

>From in the office, visiting http://build.example.com either resolves
to 10.1.2.3 or gateway.example.com's public IP address (depending on
happy eyeballs dumb luck / the macOS resolver which follows the CNAME
and populates it with the ipv4 address). As both gateway.example.com
and build.example.com can answer for http:, this isn't a problem, and
the same applies for https:. For ssh, unfortunately, more often than
not the answer is gateway.example.com's IP address, which of course is
that of the wrong computer, has the different host keys, and different
accepted accounts/credentials.

†FWIW, I consider both the dnsmasq handling and the macOS handling
buggy, but admittedly, I'm treading at the edge of the specification
w/ split-horizon-dns. I'm trying to patch dnsmasq. I'm not quite sure
where the macOS code is, but don't really expect to get particularly
good results trying to send a bug report to them...

††I know that I could, in theory, disable IPv6 everywhere, but I
really don't want to do that. Each network link on gateway.example.com
(with the exception of some VPNs) has an IPv6 address and most modern
computers self-assign IPv6 addresses. Eventually, I want to be able to
configure IPv6, and if I took the time to disable it everywhere, I'd
be making my future life (or a successor's) much harder. I have
checked, and unfortunately, I'd have to pay for a more expensive
service level to get a public IPv6 address today.... I could probably
spend time setting up my DHCP server to assign local IPv6 addresses
and get dnsmasq to conspire to return them for local resolution, but
given that nothing else would be using IPv6, it'd be a moderately
significant investment for minimal payoff, and would make some traffic
behave fairly differently from other traffic (which I expect would
make debugging future problems harder).

[1] https://github.com/jsoref/dnsmasq/commit/094e4163b24eb5bccdbcfeb5e09ad99d8e0188de.patch
[2] http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2017q1/011303.html



More information about the Dnsmasq-discuss mailing list