Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Jan 2004 20:26:24 +0100
From:      Andre Oppermann <andre@freebsd.org>
To:        Mike Silbersack <silby@silby.com>
Cc:        freebsd-net@freebsd.org
Subject:   Re: Rate limiting icmp host unreachable replies?
Message-ID:  <401023E0.9D6A5952@freebsd.org>
References:  <4010165F.2080507@freebsd.org> <20040122130156.N7234@odysseus.silby.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Mike Silbersack wrote:
> 
> On Thu, 22 Jan 2004, Andre Oppermann wrote:
> 
> > I'm having a FreeBSD router here that has many networks connected to it which
> > are only sparsely populated.  These days I get network scans (deliberate and
> > worms scanning for new targets) every second or so going through every IP in
> > my netblocks.  The router is faithfully generating ICMP host unreachable replies
> > to all these scans for each and every unreachable destination IP.
> >
> > I wonder whether it is justifyable to rate limit the icmp host unreachable replies
> > just like the other icmp stuff to 200 (default) per second?  Should help alot if
> > the next SQL slammer is coming around and you get thousands of packets per second
> > for unreachable destinations.
> >
> > Comments and opinions welcome!
> 
> I like this a lot, and I would be willing to write up an implementation!
> 
> > PS: I've already coded it and it works nicely.
> >
> > --
> > Andre
> 
> Doh!  Well, I guess we'll just have to go with your implementation then.
> :)

Here it is (pretty trivial actually):

Index: icmp_var.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet/icmp_var.h,v
retrieving revision 1.21
diff -u -p -r1.21 icmp_var.h
--- icmp_var.h	19 Mar 2002 21:25:46 -0000	1.21
+++ icmp_var.h	22 Jan 2004 19:23:23 -0000
@@ -81,11 +81,12 @@ SYSCTL_DECL(_net_inet_icmp);
 extern int badport_bandlim(int);
 #define BANDLIM_UNLIMITED -1
 #define BANDLIM_ICMP_UNREACH 0
-#define BANDLIM_ICMP_ECHO 1
-#define BANDLIM_ICMP_TSTAMP 2
-#define BANDLIM_RST_CLOSEDPORT 3 /* No connection, and no listeners */
-#define BANDLIM_RST_OPENPORT 4   /* No connection, listener */
-#define BANDLIM_MAX 4
+#define BANDLIM_ICMP_UNREACH_HOST 1
+#define BANDLIM_ICMP_ECHO 2
+#define BANDLIM_ICMP_TSTAMP 3
+#define BANDLIM_RST_CLOSEDPORT 4	/* No connection, and no listeners */
+#define BANDLIM_RST_OPENPORT 5		/* No connection, listener */
+#define BANDLIM_MAX 5
 #endif
 
 #endif
Index: ip_icmp.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.87
diff -u -p -r1.87 ip_icmp.c
--- ip_icmp.c	8 Jan 2004 17:40:06 -0000	1.87
+++ ip_icmp.c	22 Jan 2004 19:23:23 -0000
 /*
  * ICMP broadcast echo sysctl
  */
@@ -169,6 +173,18 @@ icmp_error(n, type, code, dest, destifp)
 	if (n->m_flags & (M_BCAST|M_MCAST))
 		goto freeit;
 	/*
+	 * Limit sending of ICMP host unreachable messages.
+	 * If we are acting as a router and someone is doing a sweep
+	 * scan (eg. nmap and/or numerous windows worms) for destinations
+	 * we are the gateway for but are not reachable (ie. a /24 on a
+	 * interface and only a couple of hosts on the ethernet) we would
+	 * generate a storm of ICMP host unreachable messages.
+	 */
+	if (type == ICMP_UNREACH && code == ICMP_UNREACH_HOST) {
+		if (badport_bandlim(BANDLIM_ICMP_UNREACH_HOST) < 0)
+			goto freeit;
+	}
+	/*
 	 * First, formulate icmp message
 	 */
 	m = m_gethdr(M_DONTWAIT, MT_HEADER);
@@ -859,7 +901,8 @@ badport_bandlim(int which)
 		struct timeval	lasttime;
 		int		curpps;;
 	} rates[BANDLIM_MAX+1] = {
-		{ "icmp unreach response" },
+		{ "icmp unreach port response" },
+		{ "icmp unreach host response" },
 		{ "icmp ping response" },
 		{ "icmp tstamp response" },
 		{ "closed port RST response" },



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?401023E0.9D6A5952>