From 087eb76140725f8f1892ba6f251ea052d3440966 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Mon, 30 Oct 2017 23:16:54 +0000 Subject: [PATCH] Always return a SERVFAIL response to DNS queries with RD=0. Unless we are acting in authoritative mode, obviously. To do otherwise may allows cache snooping, see. http://cs.unc.edu/~fabian/course_papers/cache_snooping.pdf --- CHANGELOG | 4 ++++ src/dnsmasq.h | 1 + src/rfc1035.c | 6 ++++++ 3 files changed, 11 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 0f01ad3..fe8df02 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,10 @@ version 2.79 upstream servers to an interface, rather than SO_BINDTODEVICE. Thanks to Beniamino Galvani for the patch. + Always return a SERVFAIL answer to DNS queries without the + recusion desired bit set, UNLESS acting as a authoritative + DNS server. This avoids a potential route to cache snooping. + version 2.78 Fix logic of appending "." to PXE basename. Thanks to Chris diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 91b1f04..5b678bd 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -456,6 +456,7 @@ struct crec { #define F_NO_RR (1u<<25) #define F_IPSET (1u<<26) #define F_NOEXTRA (1u<<27) +#define F_SERVFAIL (1u<<28) /* Values of uid in crecs with F_CONFIG bit set. */ #define SRC_INTERFACE 0 diff --git a/src/rfc1035.c b/src/rfc1035.c index 10e710e..8d9d47d 100644 --- a/src/rfc1035.c +++ b/src/rfc1035.c @@ -940,6 +940,8 @@ size_t setup_reply(struct dns_header *header, size_t qlen, SET_RCODE(header, NOERROR); /* empty domain */ else if (flags == F_NXDOMAIN) SET_RCODE(header, NXDOMAIN); + else if (flags == F_SERVFAIL) + SET_RCODE(header, SERVFAIL); else if (flags == F_IPV4) { /* we know the address */ SET_RCODE(header, NOERROR); @@ -1278,6 +1280,10 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY ) return 0; + + /* always servfail queries with RD unset, to avoid cache snooping. */ + if (!(header->hb3 & HB3_RD)) + return setup_reply(header, qlen, NULL, F_SERVFAIL, 0); /* Don't return AD set if checking disabled. */ if (header->hb4 & HB4_CD)