From: Matthias Fischer matthias.fischer@ipfire.org
Signed-off-by: Matthias Fischer matthias.fischer@ipfire.org --- lfs/dnsmasq | 4 + ...01-include_0_0_0_0_8_in_DNS_rebind_checks.patch | 41 ++++ ...subnet_to_allow_arbitary_subnet_addresses.patch | 271 +++++++++++++++++++++ ...h_zones_locally_when_localise_queries_set.patch | 34 +++ 4 files changed, 350 insertions(+) create mode 100644 src/patches/dnsmasq/001-include_0_0_0_0_8_in_DNS_rebind_checks.patch create mode 100644 src/patches/dnsmasq/002-enhance_add_subnet_to_allow_arbitary_subnet_addresses.patch create mode 100644 src/patches/dnsmasq/003-dont_answer_non_auth_queries_for_auth_zones_locally_when_localise_queries_set.patch
diff --git a/lfs/dnsmasq b/lfs/dnsmasq index f327967..f16c761 100644 --- a/lfs/dnsmasq +++ b/lfs/dnsmasq @@ -73,7 +73,11 @@ $(subst %,%_MD5,$(objects)) : $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) @$(PREBUILD) @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE) + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/001-include_0_0_0_0_8_in_DNS_rebind_checks.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/002-enhance_add_subnet_to_allow_arbitary_subnet_addresses.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/003-dont_answer_non_auth_queries_for_auth_zones_locally_when_localise_queries_set.patch cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease-file.patch + cd $(DIR_APP) && sed -i src/config.h \ -e 's|/* #define HAVE_IDN */|#define HAVE_IDN|g' \ -e 's|/* #define HAVE_DNSSEC */|#define HAVE_DNSSEC|g' \ diff --git a/src/patches/dnsmasq/001-include_0_0_0_0_8_in_DNS_rebind_checks.patch b/src/patches/dnsmasq/001-include_0_0_0_0_8_in_DNS_rebind_checks.patch new file mode 100644 index 0000000..8a2557a --- /dev/null +++ b/src/patches/dnsmasq/001-include_0_0_0_0_8_in_DNS_rebind_checks.patch @@ -0,0 +1,41 @@ +From d2aa7dfbb6d1088dcbea9fecc61b9293b320eb95 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Mon, 3 Aug 2015 21:52:12 +0100 +Subject: [PATCH] Include 0.0.0.0/8 in DNS rebind checks. + +--- + CHANGELOG | 7 +++++++ + src/rfc1035.c | 3 ++- + 2 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 901da47..3f4026d 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -1,3 +1,10 @@ ++version 2.76 ++ Include 0.0.0.0/8 in DNS rebind checks. This range ++ translates to hosts on the local network, or, at ++ least, 0.0.0.0 accesses the local host, so could ++ be targets for DNS rebinding. See RFC 5735 section 3 ++ for details. Thanks to Stephen Röttger for the bug report. ++ + version 2.75 + Fix reversion on 2.74 which caused 100% CPU use when a + dhcp-script is configured. Thanks to Adrian Davey for +diff --git a/src/rfc1035.c b/src/rfc1035.c +index 56647b0..29e9e65 100644 +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -728,7 +728,8 @@ int private_net(struct in_addr addr, int ban_localhost) + in_addr_t ip_addr = ntohl(addr.s_addr); + + return +- (((ip_addr & 0xFF000000) == 0x7F000000) && ban_localhost) /* 127.0.0.0/8 (loopback) */ || ++ (((ip_addr & 0xFF000000) == 0x7F000000) && ban_localhost) /* 127.0.0.0/8 (loopback) */ || ++ ((ip_addr & 0xFF000000) == 0x00000000) /* RFC 5735 section 3. "here" network */ || + ((ip_addr & 0xFFFF0000) == 0xC0A80000) /* 192.168.0.0/16 (private) */ || + ((ip_addr & 0xFF000000) == 0x0A000000) /* 10.0.0.0/8 (private) */ || + ((ip_addr & 0xFFF00000) == 0xAC100000) /* 172.16.0.0/12 (private) */ || +-- +1.7.10.4 diff --git a/src/patches/dnsmasq/002-enhance_add_subnet_to_allow_arbitary_subnet_addresses.patch b/src/patches/dnsmasq/002-enhance_add_subnet_to_allow_arbitary_subnet_addresses.patch new file mode 100644 index 0000000..2d3d6e4 --- /dev/null +++ b/src/patches/dnsmasq/002-enhance_add_subnet_to_allow_arbitary_subnet_addresses.patch @@ -0,0 +1,271 @@ +From a7369bef8abd241c3d85633fa9c870943f091e76 Mon Sep 17 00:00:00 2001 +From: Ed Bardsley ebardsley@google.com +Date: Wed, 5 Aug 2015 21:17:18 +0100 +Subject: [PATCH] Enhance --add-subnet to allow arbitary subnet addresses. + +--- + CHANGELOG | 4 ++++ + man/dnsmasq.8 | 32 ++++++++++++++++++++----------- + src/dnsmasq.h | 13 ++++++++++--- + src/option.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- + src/rfc1035.c | 39 +++++++++++++++++++++++++++++++------- + 5 files changed, 121 insertions(+), 26 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 3f4026d..bbc2834 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -4,6 +4,10 @@ version 2.76 + least, 0.0.0.0 accesses the local host, so could + be targets for DNS rebinding. See RFC 5735 section 3 + for details. Thanks to Stephen Röttger for the bug report. ++ ++ Enhance --add-subnet to allow arbitrary subnet addresses. ++ Thanks to Ed Barsley for the patch. ++ + + version 2.75 + Fix reversion on 2.74 which caused 100% CPU use when a +diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 +index c8913b5..a23c898 100644 +--- a/man/dnsmasq.8 ++++ b/man/dnsmasq.8 +@@ -604,17 +604,27 @@ experimental. Also note that exposing MAC addresses in this way may + have security and privacy implications. The warning about caching + given for --add-subnet applies to --add-mac too. + .TP +-.B --add-subnet[[=<IPv4 prefix length>],<IPv6 prefix length>] +-Add the subnet address of the requestor to the DNS queries which are +-forwarded upstream. The amount of the address forwarded depends on the +-prefix length parameter: 32 (128 for IPv6) forwards the whole address, +-zero forwards none of it but still marks the request so that no +-upstream nameserver will add client address information either. The +-default is zero for both IPv4 and IPv6. Note that upstream nameservers +-may be configured to return different results based on this +-information, but the dnsmasq cache does not take account. If a dnsmasq +-instance is configured such that different results may be encountered, +-caching should be disabled. ++.B --add-subnet[[=[<IPv4 address>/]<IPv4 prefix length>][,[<IPv6 address>/]<IPv6 prefix length>]] ++Add a subnet address to the DNS queries which are forwarded ++upstream. If an address is specified in the flag, it will be used, ++otherwise, the address of the requestor will be used. The amount of ++the address forwarded depends on the prefix length parameter: 32 (128 ++for IPv6) forwards the whole address, zero forwards none of it but ++still marks the request so that no upstream nameserver will add client ++address information either. The default is zero for both IPv4 and ++IPv6. Note that upstream nameservers may be configured to return ++different results based on this information, but the dnsmasq cache ++does not take account. If a dnsmasq instance is configured such that ++different results may be encountered, caching should be disabled. ++ ++For example, ++.B --add-subnet=24,96 ++will add the /24 and /96 subnets of the requestor for IPv4 and IPv6 requestors, respectively. ++.B --add-subnet=1.2.3.4/24 ++will add 1.2.3.0/24 for IPv4 requestors and ::/0 for IPv6 requestors. ++.B --add-subnet=1.2.3.4/24,1.2.3.4/24 ++will add 1.2.3.0/24 for both IPv4 and IPv6 requestors. ++ + .TP + .B -c, --cache-size=<cachesize> + Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching. +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index cf1a782..f42acdb 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -541,6 +541,13 @@ struct iname { + struct iname *next; + }; + ++/* subnet parameters from command line */ ++struct mysubnet { ++ union mysockaddr addr; ++ int addr_used; ++ int mask; ++}; ++ + /* resolv-file parms from command-line */ + struct resolvc { + struct resolvc *next; +@@ -935,9 +942,9 @@ extern struct daemon { + struct auth_zone *auth_zones; + struct interface_name *int_names; + char *mxtarget; +- int addr4_netmask; +- int addr6_netmask; +- char *lease_file; ++ struct mysubnet *add_subnet4; ++ struct mysubnet *add_subnet6; ++ char *lease_file; + char *username, *groupname, *scriptuser; + char *luascript; + char *authserver, *hostmaster; +diff --git a/src/option.c b/src/option.c +index ecc2619..746cd11 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -445,7 +445,7 @@ static struct { + { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL }, + { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL }, + { LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL }, +- { LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add requestor's IP subnet to forwarded DNS queries."), NULL }, ++ { LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add specified IP subnet to forwarded DNS queries."), NULL }, + { LOPT_DNSSEC, OPT_DNSSEC_PROXY, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL }, + { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL }, + { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL }, +@@ -722,6 +722,20 @@ static void do_usage(void) + + #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0) + ++static char *parse_mysockaddr(char *arg, union mysockaddr *addr) ++{ ++ if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0) ++ addr->sa.sa_family = AF_INET; ++#ifdef HAVE_IPV6 ++ else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0) ++ addr->sa.sa_family = AF_INET6; ++#endif ++ else ++ return _("bad address"); ++ ++ return NULL; ++} ++ + char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags) + { + int source_port = 0, serv_port = NAMESERVER_PORT; +@@ -1585,7 +1599,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + li = match_suffix->next; + free(match_suffix->suffix); + free(match_suffix); +- } ++ } + break; + } + +@@ -1593,10 +1607,45 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + set_option_bool(OPT_CLIENT_SUBNET); + if (arg) + { ++ char *err, *end; + comma = split(arg); +- if (!atoi_check(arg, &daemon->addr4_netmask) || +- (comma && !atoi_check(comma, &daemon->addr6_netmask))) +- ret_err(gen_err); ++ ++ struct mysubnet* new = opt_malloc(sizeof(struct mysubnet)); ++ if ((end = split_chr(arg, '/'))) ++ { ++ /* has subnet+len */ ++ err = parse_mysockaddr(arg, &new->addr); ++ if (err) ++ ret_err(err); ++ if (!atoi_check(end, &new->mask)) ++ ret_err(gen_err); ++ new->addr_used = 1; ++ } ++ else if (!atoi_check(arg, &new->mask)) ++ ret_err(gen_err); ++ ++ daemon->add_subnet4 = new; ++ ++ new = opt_malloc(sizeof(struct mysubnet)); ++ if (comma) ++ { ++ if ((end = split_chr(comma, '/'))) ++ { ++ /* has subnet+len */ ++ err = parse_mysockaddr(comma, &new->addr); ++ if (err) ++ ret_err(err); ++ if (!atoi_check(end, &new->mask)) ++ ret_err(gen_err); ++ new->addr_used = 1; ++ } ++ else ++ { ++ if (!atoi_check(comma, &new->mask)) ++ ret_err(gen_err); ++ } ++ } ++ daemon->add_subnet6 = new; + } + break; + +diff --git a/src/rfc1035.c b/src/rfc1035.c +index 29e9e65..6a51b30 100644 +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -629,26 +629,47 @@ struct subnet_opt { + #endif + }; + ++static void *get_addrp(union mysockaddr *addr, const short family) ++{ ++#ifdef HAVE_IPV6 ++ if (family == AF_INET6) ++ return &addr->in6.sin6_addr; ++#endif ++ ++ return &addr->in.sin_addr; ++} ++ + static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source) + { + /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */ + + int len; + void *addrp; ++ int sa_family = source->sa.sa_family; + + #ifdef HAVE_IPV6 + if (source->sa.sa_family == AF_INET6) + { +- opt->family = htons(2); +- opt->source_netmask = daemon->addr6_netmask; +- addrp = &source->in6.sin6_addr; ++ opt->source_netmask = daemon->add_subnet6->mask; ++ if (daemon->add_subnet6->addr_used) ++ { ++ sa_family = daemon->add_subnet6->addr.sa.sa_family; ++ addrp = get_addrp(&daemon->add_subnet6->addr, sa_family); ++ } ++ else ++ addrp = &source->in6.sin6_addr; + } + else + #endif + { +- opt->family = htons(1); +- opt->source_netmask = daemon->addr4_netmask; +- addrp = &source->in.sin_addr; ++ opt->source_netmask = daemon->add_subnet4->mask; ++ if (daemon->add_subnet4->addr_used) ++ { ++ sa_family = daemon->add_subnet4->addr.sa.sa_family; ++ addrp = get_addrp(&daemon->add_subnet4->addr, sa_family); ++ } ++ else ++ addrp = &source->in.sin_addr; + } + + opt->scope_netmask = 0; +@@ -656,6 +677,11 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source) + + if (opt->source_netmask != 0) + { ++#ifdef HAVE_IPV6 ++ opt->family = htons(sa_family == AF_INET6 ? 2 : 1); ++#else ++ opt->family = htons(1); ++#endif + len = ((opt->source_netmask - 1) >> 3) + 1; + memcpy(opt->addr, addrp, len); + if (opt->source_netmask & 7) +@@ -2335,4 +2361,3 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + + return len; + } +- +-- +1.7.10.4 diff --git a/src/patches/dnsmasq/003-dont_answer_non_auth_queries_for_auth_zones_locally_when_localise_queries_set.patch b/src/patches/dnsmasq/003-dont_answer_non_auth_queries_for_auth_zones_locally_when_localise_queries_set.patch new file mode 100644 index 0000000..cfbcdfb --- /dev/null +++ b/src/patches/dnsmasq/003-dont_answer_non_auth_queries_for_auth_zones_locally_when_localise_queries_set.patch @@ -0,0 +1,34 @@ +From 3a3965ac21b1b759eab8799b6edb09195b671306 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sun, 9 Aug 2015 17:45:06 +0100 +Subject: [PATCH] Don't answer non-auth queries for auth zones locally when + --localise-queries set. + +--- + src/forward.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/forward.c b/src/forward.c +index 2731b90..b76a974 100644 +--- a/src/forward.c ++++ b/src/forward.c +@@ -1365,7 +1365,7 @@ void receive_query(struct listener *listen, time_t now) + + #ifdef HAVE_AUTH + /* find queries for zones we're authoritative for, and answer them directly */ +- if (!auth_dns) ++ if (!auth_dns && !option_bool(OPT_LOCALISE)) + for (zone = daemon->auth_zones; zone; zone = zone->next) + if (in_zone(zone, daemon->namebuff, NULL)) + { +@@ -1904,7 +1904,7 @@ unsigned char *tcp_request(int confd, time_t now, + + #ifdef HAVE_AUTH + /* find queries for zones we're authoritative for, and answer them directly */ +- if (!auth_dns) ++ if (!auth_dns && !option_bool(OPT_LOCALISE)) + for (zone = daemon->auth_zones; zone; zone = zone->next) + if (in_zone(zone, daemon->namebuff, NULL)) + { +-- +1.7.10.4