Reviewed by: freebsd-current
Add ICMP_BANDLIM option and 'net.inet.icmp.icmplim' sysctl. If option is specified in kernel config, icmplim defaults to 100 pps. Setting it to 0 will disable the feature. This feature limits ICMP error responses for packets sent to bad tcp or udp ports, which does a lot to help the machine handle network D.O.S. attacks. The kernel will report packet rates that exceed the limit at a rate of one kernel printf per second. There is one issue in regards to the 'tail end' of an attack... the kernel will not output the last report until some unrelated and valid icmp error packet is return at some point after the attack is over. This is a minor reporting issue only.
This commit is contained in:
parent
3b60b6ac12
commit
51508de112
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=41487
@ -31,12 +31,14 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)icmp_var.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: icmp_var.h,v 1.8 1997/08/25 16:29:25 wollman Exp $
|
||||
* $Id: icmp_var.h,v 1.9 1997/09/07 05:26:34 bde Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETINET_ICMP_VAR_H_
|
||||
#define _NETINET_ICMP_VAR_H_
|
||||
|
||||
#include "opt_icmp_bandlim.h" /* for ICMP_BANDLIM */
|
||||
|
||||
/*
|
||||
* Variables related to this implementation
|
||||
* of the internet control message protocol.
|
||||
@ -63,12 +65,26 @@ struct icmpstat {
|
||||
*/
|
||||
#define ICMPCTL_MASKREPL 1 /* allow replies to netmask requests */
|
||||
#define ICMPCTL_STATS 2 /* statistics (read-only) */
|
||||
|
||||
#ifdef ICMP_BANDLIM
|
||||
#define ICMPCTL_ICMPLIM 3
|
||||
#define ICMPCTL_MAXID 4
|
||||
#define ICMP_BANDLIM_INFO { "icmplim", CTLTYPE_INT },
|
||||
#else
|
||||
#define ICMPCTL_MAXID 3
|
||||
#define ICMP_BANDLIM_INFO
|
||||
#endif
|
||||
|
||||
|
||||
#define ICMPCTL_NAMES { \
|
||||
{ 0, 0 }, \
|
||||
{ "maskrepl", CTLTYPE_INT }, \
|
||||
{ "stats", CTLTYPE_STRUCT }, \
|
||||
ICMP_BANDLIM_INFO \
|
||||
}
|
||||
|
||||
#ifdef ICMP_BANDLIM
|
||||
extern int badport_bandlim __P((int));
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
|
||||
* $Id: ip_icmp.c,v 1.30 1998/05/26 11:34:30 dg Exp $
|
||||
* $Id: ip_icmp.c,v 1.31 1998/09/15 10:49:03 jkoshy Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -69,10 +69,23 @@ static int icmpmaskrepl = 0;
|
||||
SYSCTL_INT(_net_inet_icmp, ICMPCTL_MASKREPL, maskrepl, CTLFLAG_RW,
|
||||
&icmpmaskrepl, 0, "");
|
||||
|
||||
#ifdef ICMP_BANDLIM
|
||||
|
||||
/*
|
||||
* ICMP error-response bandwidth limiting
|
||||
*/
|
||||
|
||||
static int icmplim = 100;
|
||||
SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RW,
|
||||
&icmplim, 0, "");
|
||||
|
||||
#endif
|
||||
|
||||
static int icmpbmcastecho = 0;
|
||||
SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_RW, &icmpbmcastecho,
|
||||
0, "");
|
||||
|
||||
|
||||
#ifdef ICMPPRINTFS
|
||||
int icmpprintfs = 0;
|
||||
#endif
|
||||
@ -704,3 +717,69 @@ ip_next_mtu(mtu, dir)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ICMP_BANDLIM
|
||||
|
||||
/*
|
||||
* badport_bandlim() - check for ICMP bandwidth limit
|
||||
*
|
||||
* Return 0 if it is ok to send an ICMP error response, -1 if we have
|
||||
* hit our bandwidth limit and it is not ok.
|
||||
*
|
||||
* If icmplim is <= 0, the feature is disabled and 0 is returned.
|
||||
*
|
||||
* For now we separate the TCP and UDP subsystems w/ different 'which'
|
||||
* values. We may eventually remove this separation (and simplify the
|
||||
* code further).
|
||||
*
|
||||
* Note that the printing of the error message is delayed so we can
|
||||
* properly print the icmp error rate that the system was trying to do
|
||||
* (i.e. 22000/100 pps, etc...). This can cause long delays in printing
|
||||
* the 'final' error, but it doesn't make sense to solve the printing
|
||||
* delay with more complex code.
|
||||
*/
|
||||
|
||||
int
|
||||
badport_bandlim(int which)
|
||||
{
|
||||
static int lticks[2];
|
||||
static int lpackets[2];
|
||||
int dticks;
|
||||
|
||||
/*
|
||||
* Return ok status if feature disabled or argument out of
|
||||
* ranage.
|
||||
*/
|
||||
|
||||
if (icmplim <= 0 || which >= 2 || which < 0)
|
||||
return(0);
|
||||
dticks = ticks - lticks[which];
|
||||
|
||||
/*
|
||||
* reset stats when cumulative dt exceeds one second.
|
||||
*/
|
||||
|
||||
if ((unsigned int)dticks > hz) {
|
||||
if (lpackets[which] > icmplim) {
|
||||
printf("icmp-response bandwidth limit %d/%d pps\n",
|
||||
lpackets[which],
|
||||
icmplim
|
||||
);
|
||||
}
|
||||
lticks[which] = ticks;
|
||||
lpackets[which] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* bump packet count
|
||||
*/
|
||||
|
||||
if (++lpackets[which] > icmplim) {
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -31,10 +31,10 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
|
||||
* $Id: tcp_input.c,v 1.80 1998/08/24 07:47:39 dfr Exp $
|
||||
* $Id: tcp_input.c,v 1.81 1998/09/11 16:04:03 wollman Exp $
|
||||
*/
|
||||
|
||||
#include "opt_ipfw.h" /* for ipfw_fwd */
|
||||
#include "opt_ipfw.h" /* for ipfw_fwd */
|
||||
#include "opt_tcpdebug.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -57,8 +57,10 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h> /* for ICMP_BANDLIM */
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/tcp_fsm.h>
|
||||
#include <netinet/tcp_seq.h>
|
||||
@ -397,6 +399,10 @@ tcp_input(m, iphlen)
|
||||
buf, ntohs(ti->ti_dport), inet_ntoa(ti->ti_src),
|
||||
ntohs(ti->ti_sport));
|
||||
}
|
||||
#ifdef ICMP_BANDLIM
|
||||
if (badport_bandlim(1) < 0)
|
||||
goto drop;
|
||||
#endif
|
||||
goto dropwithreset;
|
||||
}
|
||||
tp = intotcpcb(inp);
|
||||
|
@ -31,10 +31,10 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
|
||||
* $Id: tcp_input.c,v 1.80 1998/08/24 07:47:39 dfr Exp $
|
||||
* $Id: tcp_input.c,v 1.81 1998/09/11 16:04:03 wollman Exp $
|
||||
*/
|
||||
|
||||
#include "opt_ipfw.h" /* for ipfw_fwd */
|
||||
#include "opt_ipfw.h" /* for ipfw_fwd */
|
||||
#include "opt_tcpdebug.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -57,8 +57,10 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h> /* for ICMP_BANDLIM */
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/tcp_fsm.h>
|
||||
#include <netinet/tcp_seq.h>
|
||||
@ -397,6 +399,10 @@ tcp_input(m, iphlen)
|
||||
buf, ntohs(ti->ti_dport), inet_ntoa(ti->ti_src),
|
||||
ntohs(ti->ti_sport));
|
||||
}
|
||||
#ifdef ICMP_BANDLIM
|
||||
if (badport_bandlim(1) < 0)
|
||||
goto drop;
|
||||
#endif
|
||||
goto dropwithreset;
|
||||
}
|
||||
tp = intotcpcb(inp);
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
|
||||
* $Id: udp_usrreq.c,v 1.47 1998/05/15 20:11:35 wollman Exp $
|
||||
* $Id: udp_usrreq.c,v 1.48 1998/08/24 07:47:39 dfr Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -57,6 +57,7 @@
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/icmp_var.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/udp_var.h>
|
||||
|
||||
@ -296,6 +297,10 @@ udp_input(m, iphlen)
|
||||
goto bad;
|
||||
}
|
||||
*ip = save_ip;
|
||||
#ifdef ICMP_BANDLIM
|
||||
if (badport_bandlim(0) < 0)
|
||||
goto bad;
|
||||
#endif
|
||||
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
|
||||
return;
|
||||
}
|
||||
@ -691,3 +696,4 @@ struct pr_usrreqs udp_usrreqs = {
|
||||
pru_rcvoob_notsupp, udp_send, pru_sense_null, udp_shutdown,
|
||||
in_setsockaddr, sosend, soreceive, sopoll
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user