RA flood mitigation via a limit on accepted routes:

- introduce a limit for the routes accepted via IPv6 Router Advertisement:
  a common 2 interface client will have 6, the default limit is 100 and
  can be adjusted via sysctl
- report the current number of routes installed via RA via sysctl
- count discarded route additions. Note that one RA message is two routes.
  This is at present only across all interfaces even though per-interface
  would be more useful, since the per-interface structure complies to RFC2466
- bump kernel version due to the previous change
- adjust netstat to use the new value (with netstat -p icmp6)
This commit is contained in:
spz 2011-05-24 18:07:11 +00:00
parent a0d7ecb547
commit 5f1fd2312c
9 changed files with 71 additions and 21 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: icmp6.h,v 1.41 2011/05/08 18:42:53 spz Exp $ */
/* $NetBSD: icmp6.h,v 1.42 2011/05/24 18:07:11 spz Exp $ */
/* $KAME: icmp6.h,v 1.84 2003/04/23 10:26:51 itojun Exp $ */
@ -569,8 +569,9 @@ struct icmp6_filter {
#define ICMP6_STAT_BADRS 538 /* bad router solicitiation */
#define ICMP6_STAT_BADRA 539 /* bad router advertisement */
#define ICMP6_STAT_BADREDIRECT 540 /* bad redirect message */
#define ICMP6_STAT_DROPPED_RAROUTE 541 /* discarded routes from router advertisement */
#define ICMP6_NSTATS 541
#define ICMP6_NSTATS 542
#define ICMP6_ERRSTAT_DST_UNREACH_NOROUTE 0
#define ICMP6_ERRSTAT_DST_UNREACH_ADMIN 1

View File

@ -1,4 +1,4 @@
/* $NetBSD: in6.h,v 1.68 2009/09/11 22:06:29 dyoung Exp $ */
/* $NetBSD: in6.h,v 1.69 2011/05/24 18:07:11 spz Exp $ */
/* $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $ */
/*
@ -575,9 +575,13 @@ struct ip6_mtuinfo {
/* 40: reserved */
#define IPV6CTL_MAXFRAGS 41 /* max fragments */
#define IPV6CTL_IFQ 42 /* ip6intrq node */
#define IPV6CTL_RTADV_MAXROUTES 43 /* maximum number of routes */
/* via router advertisement */
#define IPV6CTL_RTADV_NUMROUTES 44 /* current number of routes */
/* via router advertisement */
/* New entries should be added here from current IPV6CTL_MAXID value. */
/* to define items, should talk with KAME guys first, for *BSD compatibility */
#define IPV6CTL_MAXID 43
#define IPV6CTL_MAXID 45
#define IPV6CTL_NAMES { \
{ 0, 0 }, \
@ -623,6 +627,8 @@ struct ip6_mtuinfo {
{ 0, 0 }, \
{ "maxfrags", CTLTYPE_INT }, \
{ "ifq", CTLTYPE_NODE }, \
{ "rtadv_maxroutes", CTLTYPE_INT }, \
{ "rtadv_numroutes", CTLTYPE_INT }, \
}
#endif /* _NETBSD_SOURCE */

View File

@ -1,4 +1,4 @@
/* $NetBSD: in6_proto.c,v 1.91 2011/05/03 17:44:30 dyoung Exp $ */
/* $NetBSD: in6_proto.c,v 1.92 2011/05/24 18:07:11 spz Exp $ */
/* $KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $ */
/*
@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.91 2011/05/03 17:44:30 dyoung Exp $");
__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.92 2011/05/24 18:07:11 spz Exp $");
#include "opt_gateway.h"
#include "opt_inet.h"
@ -482,6 +482,13 @@ int ip6_v6only = 1;
int ip6_keepfaith = 0;
time_t ip6_log_time = (time_t)0L;
int ip6_rtadv_maxroutes = 100; /* (arbitrary) initial maximum number of
* routes via rtadv expected to be
* significantly larger than common use.
* if you need to count: 3 extra initial
* routes, plus 1 per interface after the
* first one, then one per non-linklocal
* prefix */
/* icmp6 */
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip6_input.c,v 1.130 2011/05/03 18:28:45 dyoung Exp $ */
/* $NetBSD: ip6_input.c,v 1.131 2011/05/24 18:07:11 spz Exp $ */
/* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
/*
@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.130 2011/05/03 18:28:45 dyoung Exp $");
__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.131 2011/05/24 18:07:11 spz Exp $");
#include "opt_gateway.h"
#include "opt_inet.h"
@ -1793,6 +1793,20 @@ sysctl_net_inet6_ip6_setup(struct sysctllog **clog)
NULL, 0, &ip6_accept_rtadv, 0,
CTL_NET, PF_INET6, IPPROTO_IPV6,
IPV6CTL_ACCEPT_RTADV, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
CTLTYPE_INT, "rtadv_maxroutes",
SYSCTL_DESCR("Maximum number of routes accepted via router advertisements"),
NULL, 0, &ip6_rtadv_maxroutes, 0,
CTL_NET, PF_INET6, IPPROTO_IPV6,
IPV6CTL_RTADV_MAXROUTES, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_INT, "rtadv_numroutes",
SYSCTL_DESCR("Current number of routes accepted via router advertisements"),
NULL, 0, &nd6_numroutes, 0,
CTL_NET, PF_INET6, IPPROTO_IPV6,
IPV6CTL_RTADV_NUMROUTES, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
CTLTYPE_INT, "keepfaith",

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip6_var.h,v 1.54 2011/05/03 17:44:30 dyoung Exp $ */
/* $NetBSD: ip6_var.h,v 1.55 2011/05/24 18:07:11 spz Exp $ */
/* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */
/*
@ -281,6 +281,7 @@ extern int ip6_maxfrags; /* Maximum fragments in reassembly queue */
extern int ip6_sourcecheck; /* Verify source interface */
extern int ip6_sourcecheck_interval; /* Interval between log messages */
extern int ip6_accept_rtadv; /* Acts as a host not a router */
extern int ip6_rtadv_maxroutes; /* maximum number of routes via rtadv */
extern int ip6_keepfaith; /* Firewall Aided Internet Translator */
extern int ip6_log_interval;
extern time_t ip6_log_time;

View File

@ -1,4 +1,4 @@
/* $NetBSD: nd6.h,v 1.53 2009/11/06 20:41:22 dyoung Exp $ */
/* $NetBSD: nd6.h,v 1.54 2011/05/24 18:07:11 spz Exp $ */
/* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */
/*
@ -372,6 +372,7 @@ extern int ip6_desync_factor; /* seconds */
extern u_int32_t ip6_temp_preferred_lifetime; /* seconds */
extern u_int32_t ip6_temp_valid_lifetime; /* seconds */
extern int ip6_temp_regen_advance; /* seconds */
extern int nd6_numroutes;
union nd_opts {
struct nd_opt_hdr *nd_opt_array[8];

View File

@ -1,4 +1,4 @@
/* $NetBSD: nd6_rtr.c,v 1.80 2009/11/06 20:41:22 dyoung Exp $ */
/* $NetBSD: nd6_rtr.c,v 1.81 2011/05/24 18:07:11 spz Exp $ */
/* $KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $ */
/*
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.80 2009/11/06 20:41:22 dyoung Exp $");
__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.81 2011/05/24 18:07:11 spz Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -95,6 +95,8 @@ u_int32_t ip6_temp_preferred_lifetime = DEF_TEMP_PREFERRED_LIFETIME;
u_int32_t ip6_temp_valid_lifetime = DEF_TEMP_VALID_LIFETIME;
int ip6_temp_regen_advance = TEMPADDR_REGEN_ADVANCE;
int nd6_numroutes = 0;
/* RTPREF_MEDIUM has to be 0! */
#define RTPREF_HIGH 1
#define RTPREF_MEDIUM 0
@ -104,7 +106,7 @@ int ip6_temp_regen_advance = TEMPADDR_REGEN_ADVANCE;
/*
* Receive Router Solicitation Message - just for routers.
* Router solicitation/advertisement is mostly managed by userland program
* Router solicitation/advertisement is mostly managed by a userland program
* (rtadvd) so here we have no function like nd6_ra_output().
*
* Based on RFC 2461
@ -206,8 +208,8 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len)
struct nd_defrouter *dr;
/*
* We only accept RAs only when
* the system-wide variable allows the acceptance, and
* We only accept RAs when
* the system-wide variable allows the acceptance, and the
* per-interface variable allows RAs on the receiving interface.
*/
if (!nd6_accepts_rtadv(ndi))
@ -458,6 +460,7 @@ defrouter_addreq(struct nd_defrouter *new)
if (newrt) {
nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
newrt->rt_refcnt--;
nd6_numroutes++;
}
if (error == 0)
new->installed = 1;
@ -561,6 +564,7 @@ defrouter_delreq(struct nd_defrouter *dr)
*/
oldrt->rt_refcnt++;
rtfree(oldrt);
nd6_numroutes--;
}
}
@ -778,6 +782,12 @@ defrtrlist_update(struct nd_defrouter *new)
return (NULL);
}
if (ip6_rtadv_maxroutes <= nd6_numroutes) {
ICMP6_STATINC(ICMP6_STAT_DROPPED_RAROUTE);
splx(s);
return (NULL);
}
n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT);
if (n == NULL) {
splx(s);
@ -1045,6 +1055,11 @@ prelist_update(struct nd_prefixctl *new,
if (new->ndpr_raf_onlink == 0 && new->ndpr_raf_auto == 0)
goto end;
if (ip6_rtadv_maxroutes <= nd6_numroutes) {
ICMP6_STATINC(ICMP6_STAT_DROPPED_RAROUTE);
goto end;
}
error = nd6_prelist_add(new, dr, &newpr);
if (error != 0 || newpr == NULL) {
nd6log((LOG_NOTICE, "prelist_update: "
@ -1603,8 +1618,10 @@ nd6_prefix_onlink(struct nd_prefix *pr)
error = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
ifa->ifa_addr, (struct sockaddr *)&mask6, rtflags, &rt);
if (error == 0) {
if (rt != NULL) /* this should be non NULL, though */
if (rt != NULL) { /* this should be non NULL, though */
nd6_rtmsg(RTM_ADD, rt);
nd6_numroutes++;
}
pr->ndpr_stateflags |= NDPRF_ONLINK;
} else {
nd6log((LOG_ERR, "nd6_prefix_onlink: failed to add route for a"
@ -1647,8 +1664,10 @@ nd6_prefix_offlink(struct nd_prefix *pr)
pr->ndpr_stateflags &= ~NDPRF_ONLINK;
/* report the route deletion to the routing socket. */
if (rt != NULL)
if (rt != NULL) {
nd6_rtmsg(RTM_DELETE, rt);
nd6_numroutes--;
}
/*
* There might be the same prefix on another interface,

View File

@ -1,4 +1,4 @@
/* $NetBSD: param.h,v 1.388 2011/04/26 11:32:39 hannken Exp $ */
/* $NetBSD: param.h,v 1.389 2011/05/24 18:07:11 spz Exp $ */
/*-
* Copyright (c) 1982, 1986, 1989, 1993
@ -63,7 +63,7 @@
* 2.99.9 (299000900)
*/
#define __NetBSD_Version__ 599005100 /* NetBSD 5.99.51 */
#define __NetBSD_Version__ 599005200 /* NetBSD 5.99.52 */
#define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
(m) * 1000000) + (p) * 100) <= __NetBSD_Version__)

View File

@ -1,4 +1,4 @@
/* $NetBSD: inet6.c,v 1.58 2011/05/11 22:21:59 dyoung Exp $ */
/* $NetBSD: inet6.c,v 1.59 2011/05/24 18:07:11 spz Exp $ */
/* BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp */
/*
@ -64,7 +64,7 @@
#if 0
static char sccsid[] = "@(#)inet.c 8.4 (Berkeley) 4/20/94";
#else
__RCSID("$NetBSD: inet6.c,v 1.58 2011/05/11 22:21:59 dyoung Exp $");
__RCSID("$NetBSD: inet6.c,v 1.59 2011/05/24 18:07:11 spz Exp $");
#endif
#endif /* not lint */
@ -1196,6 +1196,7 @@ icmp6_stats(u_long off, const char *name)
p(ICMP6_STAT_BADNA, "\t%llu bad neighbor advertisement message%s\n");
p(ICMP6_STAT_BADRS, "\t%llu bad router solicitation message%s\n");
p(ICMP6_STAT_BADRA, "\t%llu bad router advertisement message%s\n");
p(ICMP6_STAT_DROPPED_RAROUTE, "\t%llu router advertisement route%s dropped\n");
p(ICMP6_STAT_BADREDIRECT, "\t%llu bad redirect message%s\n");
p(ICMP6_STAT_PMTUCHG, "\t%llu path MTU change%s\n");
#undef p