mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
Add --no-0x20-encode config option.
The "bit 0x20 encoding" implemented in 995a16ca0c
can interact badly with (hopefully) rare broken upstream servers. Provide
an option to turn it off and a log message to give a clue as to why DNS service
is non-functional.
This commit is contained in:
@@ -109,7 +109,12 @@ version 2.91
|
|||||||
on the number of a-z and A-Z characters in the query, and this
|
on the number of a-z and A-Z characters in the query, and this
|
||||||
implementation puts a hard limit of 32 bits to make rescource
|
implementation puts a hard limit of 32 bits to make rescource
|
||||||
allocation easy. This about doubles entropy over the standard
|
allocation easy. This about doubles entropy over the standard
|
||||||
random ID and random port combination.
|
random ID and random port combination. This technique can interact
|
||||||
|
badly with rare broken DNS servers which don't preserve the case
|
||||||
|
of the query in their reply. The first time a reply is returned
|
||||||
|
which matches the query in all respects except case, a warning
|
||||||
|
will be logged. If this coincides with DNS not functioning, it
|
||||||
|
is necessary to disable bit 0x20 encoding with --no-0x20-encode.
|
||||||
|
|
||||||
|
|
||||||
version 2.90
|
version 2.90
|
||||||
|
|||||||
@@ -852,6 +852,14 @@ name on successive queries, for load-balancing. This turns off that
|
|||||||
behaviour, so that the records are always returned in the order
|
behaviour, so that the records are always returned in the order
|
||||||
that they are received from upstream.
|
that they are received from upstream.
|
||||||
.TP
|
.TP
|
||||||
|
.B --no-0x20-encode
|
||||||
|
By default, dnsmasq scambles the case of letters in DNS queries it sends upstream as a security feature.
|
||||||
|
This technique can interact badly with rare broken DNS servers which don't preserve the case
|
||||||
|
of the query in their reply. The first time a reply is returned
|
||||||
|
which matches the query in all respects except case, a warning
|
||||||
|
will be logged. If this coincides with DNS not functioning, it
|
||||||
|
is necessary to disable this scrambling with --no-0x20-encode.
|
||||||
|
.TP
|
||||||
.B --use-stale-cache[=<max TTL excess in s>]
|
.B --use-stale-cache[=<max TTL excess in s>]
|
||||||
When set, if a DNS name exists in the cache, but its time-to-live has expired, dnsmasq will return the data anyway. (It attempts to refresh the
|
When set, if a DNS name exists in the cache, but its time-to-live has expired, dnsmasq will return the data anyway. (It attempts to refresh the
|
||||||
data with an upstream query after returning the stale data.) This can improve speed and reliability. It comes at the expense
|
data with an upstream query after returning the stale data.) This can improve speed and reliability. It comes at the expense
|
||||||
|
|||||||
@@ -279,7 +279,8 @@ struct event_desc {
|
|||||||
#define OPT_CACHE_RR 71
|
#define OPT_CACHE_RR 71
|
||||||
#define OPT_LOCALHOST_SERVICE 72
|
#define OPT_LOCALHOST_SERVICE 72
|
||||||
#define OPT_LOG_PROTO 73
|
#define OPT_LOG_PROTO 73
|
||||||
#define OPT_LAST 74
|
#define OPT_NO_0x20 74
|
||||||
|
#define OPT_LAST 75
|
||||||
|
|
||||||
#define OPTION_BITS (sizeof(unsigned int)*8)
|
#define OPTION_BITS (sizeof(unsigned int)*8)
|
||||||
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
|
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ static void forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
forward->new_id = get_id();
|
forward->new_id = get_id();
|
||||||
header->id = ntohs(forward->new_id);
|
header->id = ntohs(forward->new_id);
|
||||||
|
|
||||||
forward->encode_bitmap = rand32();
|
forward->encode_bitmap = option_bool(OPT_NO_0x20) ? 0 : rand32();
|
||||||
p = (unsigned char *)(header+1);
|
p = (unsigned char *)(header+1);
|
||||||
if (!extract_name(header, plen, &p, NULL, EXTR_NAME_FLIP, forward->encode_bitmap))
|
if (!extract_name(header, plen, &p, NULL, EXTR_NAME_FLIP, forward->encode_bitmap))
|
||||||
goto reply;
|
goto reply;
|
||||||
@@ -2016,7 +2016,7 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet,
|
|||||||
sending replies containing questions and bogus answers.
|
sending replies containing questions and bogus answers.
|
||||||
Try another server, or give up */
|
Try another server, or give up */
|
||||||
p = (unsigned char *)(header+1);
|
p = (unsigned char *)(header+1);
|
||||||
if (extract_name(header, rsize, &p, daemon->namebuff, EXTR_NAME_NOCASE, 4) != 1)
|
if (extract_name(header, rsize, &p, daemon->namebuff, EXTR_NAME_COMPARE, 4) != 1)
|
||||||
continue;
|
continue;
|
||||||
GETSHORT(rtype, p);
|
GETSHORT(rtype, p);
|
||||||
GETSHORT(rclass, p);
|
GETSHORT(rclass, p);
|
||||||
@@ -3057,21 +3057,34 @@ static struct frec *lookup_frec(char *target, int class, int rrtype, int id, int
|
|||||||
(header = blockdata_retrieve(f->stash, f->stash_len, NULL)))
|
(header = blockdata_retrieve(f->stash, f->stash_len, NULL)))
|
||||||
{
|
{
|
||||||
unsigned char *p = (unsigned char *)(header+1);
|
unsigned char *p = (unsigned char *)(header+1);
|
||||||
int hclass, hrrtype;
|
int hclass, hrrtype, rc;
|
||||||
|
|
||||||
/* Case sensitive compare for DNS-0x20 encoding. */
|
/* Case sensitive compare for DNS-0x20 encoding. */
|
||||||
if (extract_name(header, f->stash_len, &p, target, EXTR_NAME_NOCASE, 4) != 1)
|
if ((rc = extract_name(header, f->stash_len, &p, target, option_bool(OPT_NO_0x20) ? EXTR_NAME_COMPARE : EXTR_NAME_NOCASE, 4)))
|
||||||
continue;
|
{
|
||||||
|
GETSHORT(hrrtype, p);
|
||||||
|
GETSHORT(hclass, p);
|
||||||
|
|
||||||
GETSHORT(hrrtype, p);
|
/* type checked by flags for DNSSEC queries. */
|
||||||
GETSHORT(hclass, p);
|
if (rrtype != -1 && rrtype != hrrtype)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* type checked by flags for DNSSEC queries. */
|
if (class != hclass)
|
||||||
if (rrtype != -1 && rrtype != hrrtype)
|
continue;
|
||||||
continue;
|
}
|
||||||
|
|
||||||
if (class != hclass)
|
if (rc != 1)
|
||||||
continue;
|
{
|
||||||
|
static int warned = 0;
|
||||||
|
|
||||||
|
if (rc == 3 && !warned)
|
||||||
|
{
|
||||||
|
my_syslog(LOG_WARNING, _("Case mismatch in DNS reply - check bit 0x20 encoding."));
|
||||||
|
warned = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ struct myoption {
|
|||||||
#define LOPT_MAX_PROCS 384
|
#define LOPT_MAX_PROCS 384
|
||||||
#define LOPT_DNSSEC_LIMITS 385
|
#define LOPT_DNSSEC_LIMITS 385
|
||||||
#define LOPT_PXE_OPT 386
|
#define LOPT_PXE_OPT 386
|
||||||
|
#define LOPT_NO_ENCODE 387
|
||||||
|
|
||||||
#ifdef HAVE_GETOPT_LONG
|
#ifdef HAVE_GETOPT_LONG
|
||||||
static const struct option opts[] =
|
static const struct option opts[] =
|
||||||
@@ -247,6 +248,7 @@ static const struct myoption opts[] =
|
|||||||
{ "local-ttl", 1, 0, 'T' },
|
{ "local-ttl", 1, 0, 'T' },
|
||||||
{ "no-negcache", 0, 0, 'N' },
|
{ "no-negcache", 0, 0, 'N' },
|
||||||
{ "no-round-robin", 0, 0, LOPT_NORR },
|
{ "no-round-robin", 0, 0, LOPT_NORR },
|
||||||
|
{ "no-0x20-encode", 0, 0, LOPT_NO_ENCODE },
|
||||||
{ "cache-rr", 1, 0, LOPT_CACHE_RR },
|
{ "cache-rr", 1, 0, LOPT_CACHE_RR },
|
||||||
{ "addn-hosts", 1, 0, 'H' },
|
{ "addn-hosts", 1, 0, 'H' },
|
||||||
{ "hostsdir", 1, 0, LOPT_HOST_INOTIFY },
|
{ "hostsdir", 1, 0, LOPT_HOST_INOTIFY },
|
||||||
@@ -591,6 +593,7 @@ static struct {
|
|||||||
{ LOPT_UMBRELLA, ARG_ONE, "[=<optspec>]", gettext_noop("Send Cisco Umbrella identifiers including remote IP."), NULL },
|
{ LOPT_UMBRELLA, ARG_ONE, "[=<optspec>]", gettext_noop("Send Cisco Umbrella identifiers including remote IP."), NULL },
|
||||||
{ LOPT_QUIET_TFTP, OPT_QUIET_TFTP, NULL, gettext_noop("Do not log routine TFTP."), NULL },
|
{ LOPT_QUIET_TFTP, OPT_QUIET_TFTP, NULL, gettext_noop("Do not log routine TFTP."), NULL },
|
||||||
{ LOPT_NORR, OPT_NORR, NULL, gettext_noop("Suppress round-robin ordering of DNS records."), NULL },
|
{ LOPT_NORR, OPT_NORR, NULL, gettext_noop("Suppress round-robin ordering of DNS records."), NULL },
|
||||||
|
{ LOPT_NO_ENCODE, OPT_NO_0x20, NULL, gettext_noop("Suppress DNS bit 0x20 encoding."), NULL },
|
||||||
{ LOPT_NO_IDENT, OPT_NO_IDENT, NULL, gettext_noop("Do not add CHAOS TXT records."), NULL },
|
{ LOPT_NO_IDENT, OPT_NO_IDENT, NULL, gettext_noop("Do not add CHAOS TXT records."), NULL },
|
||||||
{ LOPT_CACHE_RR, ARG_DUP, "<RR-type>", gettext_noop("Cache this DNS resource record type."), NULL },
|
{ LOPT_CACHE_RR, ARG_DUP, "<RR-type>", gettext_noop("Cache this DNS resource record type."), NULL },
|
||||||
{ LOPT_MAX_PROCS, ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent tcp connections."), NULL },
|
{ LOPT_MAX_PROCS, ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent tcp connections."), NULL },
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
return = 0 -> error
|
return = 0 -> error
|
||||||
return = 1 -> extract OK, compare OK, flip OK
|
return = 1 -> extract OK, compare OK, flip OK
|
||||||
return = 2 -> extract OK, compare failed.
|
return = 2 -> extract OK, compare failed.
|
||||||
|
return = 3 -> extract OK, compare failed but only on case.
|
||||||
*/
|
*/
|
||||||
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||||
char *name, int func, unsigned int parm)
|
char *name, int func, unsigned int parm)
|
||||||
@@ -141,8 +142,20 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
if (case_insens && c2 >= 'A' && c2 <= 'Z')
|
if (case_insens && c2 >= 'A' && c2 <= 'Z')
|
||||||
c2 += 'a' - 'A';
|
c2 += 'a' - 'A';
|
||||||
|
|
||||||
|
if (!case_insens && retvalue != 2 && c1 != c2)
|
||||||
|
{
|
||||||
|
if (c1 >= 'A' && c1 <= 'Z')
|
||||||
|
c1 += 'a' - 'A';
|
||||||
|
|
||||||
|
if (c2 >= 'A' && c2 <= 'Z')
|
||||||
|
c2 += 'a' - 'A';
|
||||||
|
|
||||||
|
if (c1 == c2)
|
||||||
|
retvalue = 3;
|
||||||
|
}
|
||||||
|
|
||||||
if (c1 != c2)
|
if (c1 != c2)
|
||||||
retvalue = 2;
|
retvalue = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user