summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlen Huang <curvedmark@gmail.com>2014-12-27 15:28:12 +0000
committerSimon Kelley <simon@thekelleys.org.uk>2014-12-27 15:28:12 +0000
commit32fc6dbe03569d70dd394420ceb73532cf303c33 (patch)
tree8886b5623d7d27ee4f430d4b3ca6a67e7c095edc
parent83d2ed09fc0216b567d7fb2197e4ff3eae150b0d (diff)
downloaddnsmasq-32fc6dbe03569d70dd394420ceb73532cf303c33.tar.gz
Add --ignore-address option.
-rw-r--r--CHANGELOG8
-rw-r--r--man/dnsmasq.86
-rw-r--r--src/dnsmasq.h3
-rw-r--r--src/forward.c4
-rw-r--r--src/option.c18
-rw-r--r--src/rfc1035.c37
6 files changed, 72 insertions, 4 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 956b71a..2b6356b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -22,6 +22,14 @@ version 2.73
Fix crash in DNSSEC code with long RRs. Thanks to Marco Davids
for the bug report.
+
+ Add --ignore-address option. Ignore replies to A-record
+ queries which include the specified address. No error is
+ generated, dnsmasq simply continues to listen for another
+ reply. This is useful to defeat blocking strategies which
+ rely on quickly supplying a forged answer to a DNS
+ request for certain domains, before the correct answer can
+ arrive. Thanks to Glen Huang for the patch.
version 2.72
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 0b8e04f..4236ba3 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -293,6 +293,12 @@ an advertising web page in response to queries for unregistered names,
instead of the correct NXDOMAIN response. This option tells dnsmasq to
fake the correct response when it sees this behaviour. As at Sept 2003
the IP address being returned by Verisign is 64.94.110.11
+.TP
+.B \-B, --ignore-address=<ipaddr>
+Ignore replies to A-record queries which include the specified address.
+No error is generated, dnsmasq simply continues to listen for another reply.
+This is useful to defeat blocking strategies which rely on quickly supplying a
+forged answer to a DNS request for certain domain, before the correct answer can arrive.
.TP
.B \-f, --filterwin2k
Later versions of windows make periodic DNS requests which don't get sensible answers from
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 1dd61c5..7bc982d 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -930,7 +930,7 @@ extern struct daemon {
char *runfile;
char *lease_change_command;
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
- struct bogus_addr *bogus_addr;
+ struct bogus_addr *bogus_addr, *ignore_addr;
struct server *servers;
struct ipsets *ipsets;
int log_fac; /* log facility */
@@ -1093,6 +1093,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
time_t now, int *ad_reqd, int *do_bit);
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
struct bogus_addr *addr, time_t now);
+int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
size_t *len, unsigned char **p, int *is_sign);
int check_for_local_domain(char *name, time_t now);
diff --git a/src/forward.c b/src/forward.c
index 408a179..f28c7d5 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -724,6 +724,10 @@ void reply_query(int fd, int family, time_t now)
if (!(forward = lookup_frec(ntohs(header->id), hash)))
return;
+ if (daemon->ignore_addr && RCODE(header) == NOERROR &&
+ check_for_ignored_address(header, n, daemon->ignore_addr))
+ return;
+
if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) &&
!option_bool(OPT_ORDER) &&
forward->forwardall == 0)
diff --git a/src/option.c b/src/option.c
index 209fa69..907d0cf 100644
--- a/src/option.c
+++ b/src/option.c
@@ -147,6 +147,7 @@ struct myoption {
#define LOPT_LOCAL_SERVICE 335
#define LOPT_DNSSEC_TIME 336
#define LOPT_LOOP_DETECT 337
+#define LOPT_IGNORE_ADDR 338
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -181,6 +182,7 @@ static const struct myoption opts[] =
{ "local-service", 0, 0, LOPT_LOCAL_SERVICE },
{ "bogus-priv", 0, 0, 'b' },
{ "bogus-nxdomain", 1, 0, 'B' },
+ { "ignore-address", 1, 0, LOPT_IGNORE_ADDR },
{ "selfmx", 0, 0, 'e' },
{ "filterwin2k", 0, 0, 'f' },
{ "pid-file", 2, 0, 'x' },
@@ -457,6 +459,7 @@ static struct {
{ LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL },
{ LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, gettext_noop("Accept queries only from directly-connected networks"), NULL },
{ LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Detect and remove DNS forwarding loops"), NULL },
+ { LOPT_IGNORE_ADDR, ARG_DUP, "<ipaddr>", gettext_noop("Ignore DNS responses containing ipaddr."), NULL },
{ 0, 0, NULL, NULL, NULL }
};
@@ -2119,14 +2122,23 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
break;
case 'B': /* --bogus-nxdomain */
- {
+ case LOPT_IGNORE_ADDR: /* --ignore-address */
+ {
struct in_addr addr;
unhide_metas(arg);
if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
{
struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
- baddr->next = daemon->bogus_addr;
- daemon->bogus_addr = baddr;
+ if (option == 'B')
+ {
+ baddr->next = daemon->bogus_addr;
+ daemon->bogus_addr = baddr;
+ }
+ else
+ {
+ baddr->next = daemon->ignore_addr;
+ daemon->ignore_addr = baddr;
+ }
baddr->addr = addr;
}
else
diff --git a/src/rfc1035.c b/src/rfc1035.c
index bdeb3fb..75c4266 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1328,6 +1328,43 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
return 0;
}
+int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr)
+{
+ unsigned char *p;
+ int i, qtype, qclass, rdlen;
+ struct bogus_addr *baddrp;
+
+ /* skip over questions */
+ if (!(p = skip_questions(header, qlen)))
+ return 0; /* bad packet */
+
+ for (i = ntohs(header->ancount); i != 0; i--)
+ {
+ if (!(p = skip_name(p, header, qlen, 10)))
+ return 0; /* bad packet */
+
+ GETSHORT(qtype, p);
+ GETSHORT(qclass, p);
+ p += 4; /* TTL */
+ GETSHORT(rdlen, p);
+
+ if (qclass == C_IN && qtype == T_A)
+ {
+ if (!CHECK_LEN(header, p, qlen, INADDRSZ))
+ return 0;
+
+ for (baddrp = baddr; baddrp; baddrp = baddrp->next)
+ if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
+ return 1;
+ }
+
+ if (!ADD_RDLEN(header, p, qlen, rdlen))
+ return 0;
+ }
+
+ return 0;
+}
+
int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp,
unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
{