Commit dc27e148 authored by Simon Kelley's avatar Simon Kelley

Warning when using --bind-interfaces and routeable addresses.

parent 45cca585
......@@ -632,6 +632,8 @@ int main (int argc, char **argv)
if (bind_fallback)
my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
warn_bound_listeners();
if (!option_bool(OPT_NOWILD))
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
......@@ -856,6 +858,7 @@ int main (int argc, char **argv)
enumerate_interfaces(0);
/* NB, is_dad_listeners() == 1 --> we're binding interfaces */
create_bound_listeners(0);
warn_bound_listeners();
}
#ifdef HAVE_LINUX_NETWORK
......
......@@ -454,7 +454,7 @@ struct ipsets {
struct irec {
union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */
int tftp_ok, dhcp_ok, mtu, done, dad, dns_auth, index, multicast_done;
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done;
char *name;
struct irec *next;
};
......@@ -988,6 +988,7 @@ unsigned char *skip_questions(struct dns_header *header, size_t plen);
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
char *name, int isExtract, int extrabytes);
int in_arpa_name_2_addr(char *namein, struct all_addr *addrp);
int private_net(struct in_addr addr, int ban_localhost);
/* auth.c */
#ifdef HAVE_AUTH
......@@ -1068,6 +1069,7 @@ void check_servers(void);
int enumerate_interfaces(int reset);
void create_wildcard_listeners(void);
void create_bound_listeners(int die);
void warn_bound_listeners(void);
int is_dad_listeners(void);
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
......
......@@ -16,6 +16,10 @@
#include "dnsmasq.h"
#ifndef IN6_IS_ADDR_ULA
#define IN6_IS_ADDR_ULA(a) ((((__const uint32_t *) (a))[0] & htonl (0xfe00000)) == htonl (0xfc000000))
#endif
#ifdef HAVE_LINUX_NETWORK
int indextoname(int fd, int index, char *name)
......@@ -383,7 +387,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
iface->dns_auth = auth_dns;
iface->mtu = mtu;
iface->dad = dad;
iface->done = iface->multicast_done = 0;
iface->done = iface->multicast_done = iface->warned = 0;
iface->index = if_index;
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
{
......@@ -824,6 +828,59 @@ void create_bound_listeners(int dienow)
}
}
/* In --bind-interfaces, the only access control is the addresses we're listening on.
There's nothing to avoid a query to the address of an internal interface arriving via
an external interface where we don't want to accept queries, except that in the usual
case the addresses of internal interfaces are RFC1918. When bind-interfaces in use,
and we listen on an address that looks like it's probably globally routeable, shout.
The fix is to use --bind-dynamic, which actually checks the arrival interface too.
Tough if your platform doesn't support this.
*/
void warn_bound_listeners(void)
{
struct irec *iface;
int advice = 0;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (option_bool(OPT_NOWILD) && !iface->dns_auth)
{
int warn = 0;
if (iface->addr.sa.sa_family == AF_INET)
{
if (!private_net(iface->addr.in.sin_addr, 1))
{
inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
warn = 1;
}
}
#ifdef HAVE_IPV6
else
{
if (!IN6_IS_ADDR_LINKLOCAL(&iface->addr.in6.sin6_addr) &&
!IN6_IS_ADDR_SITELOCAL(&iface->addr.in6.sin6_addr) &&
!IN6_IS_ADDR_ULA(&iface->addr.in6.sin6_addr) &&
!IN6_IS_ADDR_LOOPBACK(&iface->addr.in6.sin6_addr))
{
inet_ntop(AF_INET6, &iface->addr.in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);
warn = 1;
}
}
#endif
if (warn)
{
iface->warned = advice = 1;
my_syslog(LOG_WARNING,
_("LOUD WARNING: listening on %s may accept requests via interfaces other than %s. "),
daemon->addrbuff, iface->name);
}
}
if (advice)
my_syslog(LOG_WARNING, _("LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)."));
}
int is_dad_listeners(void)
{
struct irec *iface;
......
......@@ -724,7 +724,7 @@ int check_source(struct dns_header *header, size_t plen, unsigned char *pseudohe
}
/* is addr in the non-globally-routed IP space? */
static int private_net(struct in_addr addr, int ban_localhost)
int private_net(struct in_addr addr, int ban_localhost)
{
in_addr_t ip_addr = ntohl(addr.s_addr);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment