mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-20 02:38:32 +00:00
Warning when using --bind-interfaces and routeable addresses.
This commit is contained in:
@@ -633,6 +633,8 @@ int main (int argc, char **argv)
|
|||||||
if (bind_fallback)
|
if (bind_fallback)
|
||||||
my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
|
my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
|
||||||
|
|
||||||
|
warn_bound_listeners();
|
||||||
|
|
||||||
if (!option_bool(OPT_NOWILD))
|
if (!option_bool(OPT_NOWILD))
|
||||||
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
|
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
|
||||||
if (if_tmp->name && !if_tmp->used)
|
if (if_tmp->name && !if_tmp->used)
|
||||||
@@ -856,6 +858,7 @@ int main (int argc, char **argv)
|
|||||||
enumerate_interfaces(0);
|
enumerate_interfaces(0);
|
||||||
/* NB, is_dad_listeners() == 1 --> we're binding interfaces */
|
/* NB, is_dad_listeners() == 1 --> we're binding interfaces */
|
||||||
create_bound_listeners(0);
|
create_bound_listeners(0);
|
||||||
|
warn_bound_listeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
|
|||||||
@@ -454,7 +454,7 @@ struct ipsets {
|
|||||||
struct irec {
|
struct irec {
|
||||||
union mysockaddr addr;
|
union mysockaddr addr;
|
||||||
struct in_addr netmask; /* only valid for IPv4 */
|
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;
|
char *name;
|
||||||
struct irec *next;
|
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,
|
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||||
char *name, int isExtract, int extrabytes);
|
char *name, int isExtract, int extrabytes);
|
||||||
int in_arpa_name_2_addr(char *namein, struct all_addr *addrp);
|
int in_arpa_name_2_addr(char *namein, struct all_addr *addrp);
|
||||||
|
int private_net(struct in_addr addr, int ban_localhost);
|
||||||
|
|
||||||
/* auth.c */
|
/* auth.c */
|
||||||
#ifdef HAVE_AUTH
|
#ifdef HAVE_AUTH
|
||||||
@@ -1068,6 +1069,7 @@ void check_servers(void);
|
|||||||
int enumerate_interfaces(int reset);
|
int enumerate_interfaces(int reset);
|
||||||
void create_wildcard_listeners(void);
|
void create_wildcard_listeners(void);
|
||||||
void create_bound_listeners(int die);
|
void create_bound_listeners(int die);
|
||||||
|
void warn_bound_listeners(void);
|
||||||
int is_dad_listeners(void);
|
int is_dad_listeners(void);
|
||||||
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
|
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);
|
int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
|
||||||
|
|||||||
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
#include "dnsmasq.h"
|
#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
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
|
|
||||||
int indextoname(int fd, int index, char *name)
|
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->dns_auth = auth_dns;
|
||||||
iface->mtu = mtu;
|
iface->mtu = mtu;
|
||||||
iface->dad = dad;
|
iface->dad = dad;
|
||||||
iface->done = iface->multicast_done = 0;
|
iface->done = iface->multicast_done = iface->warned = 0;
|
||||||
iface->index = if_index;
|
iface->index = if_index;
|
||||||
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
|
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)
|
int is_dad_listeners(void)
|
||||||
{
|
{
|
||||||
struct irec *iface;
|
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? */
|
/* 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);
|
in_addr_t ip_addr = ntohl(addr.s_addr);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user