diff --git a/package/network/services/dnsmasq/files/dhcp.conf b/package/network/services/dnsmasq/files/dhcp.conf index 29c9d705f..0225c9ebd 100644 --- a/package/network/services/dnsmasq/files/dhcp.conf +++ b/package/network/services/dnsmasq/files/dhcp.conf @@ -21,6 +21,7 @@ config dnsmasq #list bogusnxdomain '64.94.110.11' option localservice 1 # disable to allow DNS requests from non-local subnets option filter_aaaa 1 + option filter_a 0 option cachesize 8000 option mini_ttl 3600 option ednspacket_max 1232 diff --git a/package/network/services/dnsmasq/files/dnsmasq.init b/package/network/services/dnsmasq/files/dnsmasq.init index ebf5b5eab..3914001fc 100755 --- a/package/network/services/dnsmasq/files/dnsmasq.init +++ b/package/network/services/dnsmasq/files/dnsmasq.init @@ -929,13 +929,12 @@ dnsmasq_start() append_bool "$cfg" noping "--no-ping" append_bool "$cfg" rapidcommit "--dhcp-rapid-commit" append_bool "$cfg" scriptarp "--script-arp" - - append_bool "$cfg" filter_aaaa "--filter-aaaa" - append_bool "$cfg" filter_https "--filter-https" - append_bool "$cfg" filter_unknown "--filter-unknown" + + append_bool "$cfg" filter_aaaa "--filter-AAAA" + append_bool "$cfg" filter_a "--filter-A" append_parm "$cfg" logfacility "--log-facility" - + append_parm "$cfg" mini_ttl "--min-ttl" append_parm "$cfg" cachesize "--cache-size" diff --git a/package/network/services/dnsmasq/patches/011-dnsmasq-add-filter-and-filter-aaaa-options.patch b/package/network/services/dnsmasq/patches/011-dnsmasq-add-filter-and-filter-aaaa-options.patch new file mode 100644 index 000000000..00626d467 --- /dev/null +++ b/package/network/services/dnsmasq/patches/011-dnsmasq-add-filter-and-filter-aaaa-options.patch @@ -0,0 +1,204 @@ +From 37a70d39e0cd49f086b757937fa8735e6263cd7a Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Thu, 7 Oct 2021 23:12:59 +0100 +Subject: [PATCH] Add --filter and --filter-AAAA options. + +--- + CHANGELOG | 5 ++++- + man/dnsmasq.8 | 6 ++++++ + src/dnsmasq.h | 10 ++++++++-- + src/edns0.c | 2 +- + src/forward.c | 18 ++++++++++++++---- + src/option.c | 8 +++++++- + src/rrfilter.c | 37 +++++++++++++++++++++++++++---------- + 7 files changed, 67 insertions(+), 19 deletions(-) + +--- a/man/dnsmasq.8 ++++ b/man/dnsmasq.8 +@@ -348,6 +348,12 @@ the public DNS and can cause problems by triggering dial-on-demand links. This f + to filter such requests. The requests blocked are for records of types SOA and SRV, and type ANY where the + requested name has underscores, to catch LDAP requests. + .TP ++.B --filter-A ++Remove A records from answers. No IPv4 addresses will be returned. ++.TP ++.B --filter-AAAA ++Remove AAAA records from answers. No IPv6 addresses will be returned. ++.TP + .B \-r, --resolv-file= + Read the IP addresses of the upstream nameservers from , instead of + /etc/resolv.conf. For the format of this file see +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -275,7 +275,9 @@ struct event_desc { + #define OPT_UMBRELLA_DEVID 64 + #define OPT_CMARK_ALST_EN 65 + #define OPT_QUIET_TFTP 66 +-#define OPT_LAST 67 ++#define OPT_FILTER_A 67 ++#define OPT_FILTER_AAAA 68 ++#define OPT_LAST 69 + + #define OPTION_BITS (sizeof(unsigned int)*8) + #define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) ) +@@ -1735,7 +1737,11 @@ int do_poll(int timeout); + size_t rrfilter(struct dns_header *header, size_t plen, int mode); + u16 *rrfilter_desc(int type); + int expand_workspace(unsigned char ***wkspc, int *szp, int new); +- ++/* modes. */ ++#define RRFILTER_EDNS0 0 ++#define RRFILTER_DNSSEC 1 ++#define RRFILTER_A 2 ++#define RRFILTER_AAAA 3 + /* edns0.c */ + unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, + size_t *len, unsigned char **p, int *is_sign, int *is_last); +--- a/src/edns0.c ++++ b/src/edns0.c +@@ -178,7 +178,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l + memcpy(buff, datap, rdlen); + + /* now, delete OPT RR */ +- plen = rrfilter(header, plen, 0); ++ plen = rrfilter(header, plen, RRFILTER_EDNS0); + + /* Now, force addition of a new one */ + p = NULL; +--- a/src/forward.c ++++ b/src/forward.c +@@ -607,7 +607,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server + if (added_pheader) + { + /* client didn't send EDNS0, we added one, strip it off before returning answer. */ +- n = rrfilter(header, n, 0); ++ n = rrfilter(header, n, RRFILTER_EDNS0); + pheader = NULL; + } + else +@@ -696,7 +696,17 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server + cache_secure = 0; + } + } +- ++ ++ /* Before extract_addresses() */ ++ if (rcode == NOERROR) ++ { ++ if (option_bool(OPT_FILTER_A)) ++ n = rrfilter(header, n, RRFILTER_A); ++ ++ if (option_bool(OPT_FILTER_AAAA)) ++ n = rrfilter(header, n, RRFILTER_AAAA); ++ } ++ + if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, check_rebind, no_cache, cache_secure, &doctored)) + { + my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff); +@@ -726,7 +736,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server + + /* If the requestor didn't set the DO bit, don't return DNSSEC info. */ + if (!do_bit) +- n = rrfilter(header, n, 1); ++ n = rrfilter(header, n, RRFILTER_DNSSEC); + } + #endif + +@@ -750,7 +760,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server + u16 swap = htons((u16)ede); + n = add_pseudoheader(header, n, limit, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 1); + } +- ++ + return n; + } + +--- a/src/option.c ++++ b/src/option.c +@@ -174,7 +174,9 @@ struct myoption { + #define LOPT_CMARK_ALST_EN 365 + #define LOPT_CMARK_ALST 366 + #define LOPT_QUIET_TFTP 367 +- ++#define LOPT_FILTER_A 369 ++#define LOPT_FILTER_AAAA 370 ++ + #ifdef HAVE_GETOPT_LONG + static const struct option opts[] = + #else +@@ -211,6 +213,8 @@ static const struct myoption opts[] = + { "ignore-address", 1, 0, LOPT_IGNORE_ADDR }, + { "selfmx", 0, 0, 'e' }, + { "filterwin2k", 0, 0, 'f' }, ++ { "filter-A", 0, 0, LOPT_FILTER_A }, ++ { "filter-AAAA", 0, 0, LOPT_FILTER_AAAA }, + { "pid-file", 2, 0, 'x' }, + { "strict-order", 0, 0, 'o' }, + { "server", 1, 0, 'S' }, +@@ -380,6 +384,8 @@ static struct { + { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL }, + { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL }, + { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL }, ++ { LOPT_FILTER_A, OPT_FILTER_A, NULL, gettext_noop("Don't include IPv4 addresses in DNS answers."), NULL }, ++ { LOPT_FILTER_AAAA, OPT_FILTER_AAAA, NULL, gettext_noop("Don't include IPv6 addresses in DNS answers."), NULL }, + { 'F', ARG_DUP, ",...", gettext_noop("Enable DHCP in the range given with lease duration."), NULL }, + { 'g', ARG_ONE, "", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP }, + { 'G', ARG_DUP, "", gettext_noop("Set address or hostname for a specified machine."), NULL }, +--- a/src/rrfilter.c ++++ b/src/rrfilter.c +@@ -156,7 +156,7 @@ static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, i + } + + +-/* mode is 0 to remove EDNS0, 1 to filter DNSSEC RRs */ ++/* mode may be remove EDNS0 or DNSSEC RRs or remove A or AAAA from answer section. */ + size_t rrfilter(struct dns_header *header, size_t plen, int mode) + { + static unsigned char **rrs; +@@ -192,20 +192,37 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode) + if (!ADD_RDLEN(header, p, plen, rdlen)) + return plen; + +- /* Don't remove the answer. */ +- if (i < ntohs(header->ancount) && type == qtype && class == qclass) +- continue; +- +- if (mode == 0) /* EDNS */ ++ if (mode == RRFILTER_EDNS0) /* EDNS */ + { + /* EDNS mode, remove T_OPT from additional section only */ + if (i < (ntohs(header->nscount) + ntohs(header->ancount)) || type != T_OPT) + continue; + } +- else if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG) +- /* DNSSEC mode, remove SIGs and NSECs from all three sections. */ +- continue; +- ++ else if (mode == RRFILTER_DNSSEC) ++ { ++ if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG) ++ /* DNSSEC mode, remove SIGs and NSECs from all three sections. */ ++ continue; ++ ++ /* Don't remove the answer. */ ++ if (i < ntohs(header->ancount) && type == qtype && class == qclass) ++ continue; ++ } ++ else ++ { ++ /* Only looking at answer section now. */ ++ if (i >= ntohs(header->ancount)) ++ break; ++ ++ if (class != C_IN) ++ continue; ++ ++ if (mode == RRFILTER_A && type != T_A) ++ continue; ++ ++ if (mode == RRFILTER_AAAA && type != T_AAAA) ++ continue; ++ } + + if (!expand_workspace(&rrs, &rr_sz, rr_found + 1)) + return plen; diff --git a/package/network/services/dnsmasq/patches/910-mini-ttl.patch b/package/network/services/dnsmasq/patches/910-mini-ttl.patch index ac7d17ad0..cd5ba84f4 100644 --- a/package/network/services/dnsmasq/patches/910-mini-ttl.patch +++ b/package/network/services/dnsmasq/patches/910-mini-ttl.patch @@ -1,6 +1,6 @@ --- a/src/dnsmasq.h +++ b/src/dnsmasq.h -@@ -1116,7 +1116,7 @@ extern struct daemon { +@@ -1118,7 +1118,7 @@ extern struct daemon { int max_logs; /* queue limit */ int cachesize, ftabsize; int port, query_port, min_port, max_port; @@ -16,10 +16,10 @@ #define LOPT_CMARK_ALST 366 #define LOPT_QUIET_TFTP 367 +#define LOPT_MINTTL 368 - - #ifdef HAVE_GETOPT_LONG - static const struct option opts[] = -@@ -292,6 +293,7 @@ static const struct myoption opts[] = + #define LOPT_FILTER_A 369 + #define LOPT_FILTER_AAAA 370 + +@@ -296,6 +297,7 @@ static const struct myoption opts[] = { "dhcp-name-match", 1, 0, LOPT_NAME_MATCH }, { "dhcp-broadcast", 2, 0, LOPT_BROADCAST }, { "neg-ttl", 1, 0, LOPT_NEGTTL }, @@ -27,7 +27,7 @@ { "max-ttl", 1, 0, LOPT_MAXTTL }, { "min-cache-ttl", 1, 0, LOPT_MINCTTL }, { "max-cache-ttl", 1, 0, LOPT_MAXCTTL }, -@@ -425,6 +427,7 @@ static struct { +@@ -431,6 +433,7 @@ static struct { { 't', ARG_ONE, "", gettext_noop("Specify default target in an MX record."), NULL }, { 'T', ARG_ONE, "", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL }, { LOPT_NEGTTL, ARG_ONE, "", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL }, @@ -35,7 +35,7 @@ { LOPT_MAXTTL, ARG_ONE, "", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL }, { LOPT_MAXCTTL, ARG_ONE, "", gettext_noop("Specify time-to-live ceiling for cache."), NULL }, { LOPT_MINCTTL, ARG_ONE, "", gettext_noop("Specify time-to-live floor for cache."), NULL }, -@@ -3047,6 +3050,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma +@@ -3053,6 +3056,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma case 'T': /* --local-ttl */ case LOPT_NEGTTL: /* --neg-ttl */ @@ -43,7 +43,7 @@ case LOPT_MAXTTL: /* --max-ttl */ case LOPT_MINCTTL: /* --min-cache-ttl */ case LOPT_MAXCTTL: /* --max-cache-ttl */ -@@ -3058,6 +3062,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma +@@ -3064,6 +3068,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma ret_err(gen_err); else if (option == LOPT_NEGTTL) daemon->neg_ttl = (unsigned long)ttl; diff --git a/package/network/services/dnsmasq/patches/911-dnsmasq-filter-aaaa+https+unknown.patch b/package/network/services/dnsmasq/patches/911-dnsmasq-filter-aaaa+https+unknown.patch deleted file mode 100644 index ec082ec09..000000000 --- a/package/network/services/dnsmasq/patches/911-dnsmasq-filter-aaaa+https+unknown.patch +++ /dev/null @@ -1,143 +0,0 @@ -diff --git a/src/cache.c b/src/cache.c -index 8add610..c94132e 100644 ---- a/src/cache.c -+++ b/src/cache.c -@@ -66,6 +66,7 @@ static const struct { - { 52, "TLSA" }, - { 53, "SMIMEA" }, - { 55, "HIP" }, -+ { 65, "HTTPS"}, - { 249, "TKEY" }, - { 250, "TSIG" }, - { 251, "IXFR" }, -@@ -1805,6 +1806,20 @@ char *record_source(unsigned int index) - return ""; - } - -+// patch: function returns integer 1 if query type is unknown. -+// known types are defined in cache.c:typestr:36. -+int is_query_type_unknown(unsigned short type) -+{ -+ unsigned int i; -+ for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++) -+ if (typestr[i].type == type) -+ { -+ return 0; -+ } -+ return 1; -+} -+// end of patch -+ - char *querystr(char *desc, unsigned short type) - { - unsigned int i; -diff --git a/src/dns-protocol.h b/src/dns-protocol.h -index 496a4bb..ed0d64a 100644 ---- a/src/dns-protocol.h -+++ b/src/dns-protocol.h -@@ -71,6 +71,7 @@ - #define T_NSEC 47 - #define T_DNSKEY 48 - #define T_NSEC3 50 -+#define T_HTTPS 65 - #define T_TKEY 249 - #define T_TSIG 250 - #define T_AXFR 252 -diff --git a/src/dnsmasq.h b/src/dnsmasq.h -index 8674823..d067741 100644 ---- a/src/dnsmasq.h -+++ b/src/dnsmasq.h -@@ -275,7 +275,10 @@ struct event_desc { - #define OPT_UMBRELLA_DEVID 64 - #define OPT_CMARK_ALST_EN 65 - #define OPT_QUIET_TFTP 66 --#define OPT_LAST 67 -+#define OPT_FILTER_AAAA 67 -+#define OPT_FILTER_HTTPS 68 -+#define OPT_FILTER_UNKNOWN 69 -+#define OPT_LAST 70 - - #define OPTION_BITS (sizeof(unsigned int)*8) - #define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) ) -@@ -1247,6 +1250,10 @@ void cache_init(void); - void next_uid(struct crec *crecp); - void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg); - char *record_source(unsigned int index); -+// patch: function returns integer 1 if query type is unknown -+// known types are defined in cache.c:typestr:36. -+int is_query_type_unknown(unsigned short type); -+// end of patch - char *querystr(char *desc, unsigned short type); - int cache_find_non_terminal(char *name, time_t now); - struct crec *cache_find_by_addr(struct crec *crecp, -diff --git a/src/option.c b/src/option.c -index ffce9fc..3993c10 100644 ---- a/src/option.c -+++ b/src/option.c -@@ -174,6 +174,9 @@ struct myoption { - #define LOPT_CMARK_ALST 366 - #define LOPT_QUIET_TFTP 367 - #define LOPT_MINTTL 368 -+#define LOPT_FILTER_AAAA 369 -+#define LOPT_FILTER_HTTPS 370 -+#define LOPT_FILTER_UNKNOWN 371 - - #ifdef HAVE_GETOPT_LONG - static const struct option opts[] = -@@ -353,6 +356,9 @@ static const struct myoption opts[] = - { "log-debug", 0, 0, LOPT_LOG_DEBUG }, - { "umbrella", 2, 0, LOPT_UMBRELLA }, - { "quiet-tftp", 0, 0, LOPT_QUIET_TFTP }, -+ { "filter-aaaa", 0, 0, LOPT_FILTER_AAAA }, -+ { "filter-https", 0, 0, LOPT_FILTER_HTTPS }, -+ { "filter-unknown", 0, 0, LOPT_FILTER_UNKNOWN }, - { NULL, 0, 0, 0 } - }; - -@@ -539,6 +545,9 @@ static struct { - { LOPT_SCRIPT_TIME, OPT_LEASE_RENEW, NULL, gettext_noop("Call dhcp-script when lease expiry changes."), NULL }, - { LOPT_UMBRELLA, ARG_ONE, "[=]", 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_FILTER_AAAA, OPT_FILTER_AAAA, NULL, gettext_noop("Filter all AAAA requests."), NULL }, -+ { LOPT_FILTER_HTTPS, OPT_FILTER_HTTPS, NULL, gettext_noop("Filter all HTTPS/query type 65 requests."), NULL }, -+ { LOPT_FILTER_UNKNOWN, OPT_FILTER_UNKNOWN, NULL, gettext_noop("Filter all unknown query types (known are defined in cache.c)."), NULL }, - { 0, 0, NULL, NULL, NULL } - }; - -diff --git a/src/rfc1035.c b/src/rfc1035.c -index 6fc4f26..395634b 100644 ---- a/src/rfc1035.c -+++ b/src/rfc1035.c -@@ -1987,6 +1987,32 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, - } - } - -+ //patch to filter aaaa forwards -+ if (qtype == T_AAAA && option_bool(OPT_FILTER_AAAA) ){ -+ //return a null reply -+ ans = 1; -+ if (!dryrun) log_query(F_CONFIG | F_IPV6 | F_NEG, name, &addr, NULL); -+ break; -+ } -+ //end of patch -+ //patch to filter https/query type 65 forwards -+ if (qtype == T_HTTPS && option_bool(OPT_FILTER_HTTPS) ){ -+ //return a null reply -+ ans = 1; -+ if (!dryrun) log_query(F_CONFIG | F_IPV4 | F_NEG, name, &addr, NULL); -+ break; -+ } -+ //end of patch -+ //patch to filter all unknown query types -+ //known types are defined in cache.c:typestr:36. -+ if (is_query_type_unknown(qtype) && option_bool(OPT_FILTER_UNKNOWN)) { -+ //return a null reply -+ ans = 1; -+ if (!dryrun) log_query(F_CONFIG | F_NEG, name, NULL, NULL); -+ break; -+ } -+ //end of patch -+ - if (!ans) - return 0; /* failed to answer a question */ - }