From 09f81a46a58daaafc59a7ea5907502e3f2ae3cd0 Mon Sep 17 00:00:00 2001 From: Bosko Milekic Date: Fri, 15 Dec 2000 21:45:49 +0000 Subject: [PATCH] Change the following: 1. ICMP ECHO and TSTAMP replies are now rate limited. 2. RSTs generated due to packets sent to open and unopen ports are now limited by seperate counters. 3. Each rate limiting queue now has its own description, as follows: Limiting icmp unreach response from 439 to 200 packets per second Limiting closed port RST response from 283 to 200 packets per second Limiting open port RST response from 18724 to 200 packets per second Limiting icmp ping response from 211 to 200 packets per second Limiting icmp tstamp response from 394 to 200 packets per second Submitted by: Mike Silbersack --- sys/netinet/icmp_var.h | 6 ++++++ sys/netinet/ip_icmp.c | 26 ++++++++++++++++++++------ sys/netinet/tcp_input.c | 10 ++++++++-- sys/netinet/tcp_reass.c | 10 ++++++++-- sys/netinet/udp_usrreq.c | 2 +- 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/sys/netinet/icmp_var.h b/sys/netinet/icmp_var.h index 2eeef541fb21..fd04f2760847 100644 --- a/sys/netinet/icmp_var.h +++ b/sys/netinet/icmp_var.h @@ -77,6 +77,12 @@ struct icmpstat { #ifdef _KERNEL SYSCTL_DECL(_net_inet_icmp); extern int badport_bandlim __P((int)); +#define BANDLIM_UNREACH 0 +#define BANDLIM_RST_NOTOPEN 1 +#define BANDLIM_RST_OPEN 2 +#define BANDLIM_ECHO 3 +#define BANDLIM_TSTAMP 4 +#define BANDLIM_MAX 4 #endif #endif diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index eb68d1d0493b..5a44807ad3b0 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -449,7 +449,10 @@ icmp_input(m, off, proto) break; } icp->icmp_type = ICMP_ECHOREPLY; - goto reflect; + if (badport_bandlim(BANDLIM_ECHO) < 0) + goto freeit; + else + goto reflect; case ICMP_TSTAMP: if (!icmpbmcastecho @@ -464,7 +467,10 @@ icmp_input(m, off, proto) icp->icmp_type = ICMP_TSTAMPREPLY; icp->icmp_rtime = iptime(); icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ - goto reflect; + if (badport_bandlim(BANDLIM_TSTAMP) < 0) + goto freeit; + else + goto reflect; case ICMP_MASKREQ: #define satosin(sa) ((struct sockaddr_in *)(sa)) @@ -821,16 +827,23 @@ ip_next_mtu(mtu, dir) int badport_bandlim(int which) { - static int lticks[2]; - static int lpackets[2]; + static int lticks[BANDLIM_MAX + 1]; + static int lpackets[BANDLIM_MAX + 1]; int dticks; + const char *bandlimittype[] = { + "Limiting icmp unreach response", + "Limiting closed port RST response", + "Limiting open port RST response", + "Limiting icmp ping response", + "Limiting icmp tstamp response" + }; /* * Return ok status if feature disabled or argument out of * ranage. */ - if (icmplim <= 0 || which >= 2 || which < 0) + if (icmplim <= 0 || which > BANDLIM_MAX || which < 0) return(0); dticks = ticks - lticks[which]; @@ -840,7 +853,8 @@ badport_bandlim(int which) if ((unsigned int)dticks > hz) { if (lpackets[which] > icmplim && icmplim_output) { - printf("icmp-response bandwidth limit %d/%d pps\n", + printf("%s from %d to %d packets per second\n", + bandlimittype[which], lpackets[which], icmplim ); diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index cb7e05e93696..367fc95a8d96 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -392,6 +392,7 @@ tcp_input(m, off0, proto) struct ip6_hdr *ip6 = NULL; int isipv6; #endif /* INET6 */ + int rstreason = 0; /* For badport_bandlim accounting purposes */ #ifdef INET6 isipv6 = (mtod(m, struct ip *)->ip_v == 6) ? 1 : 0; @@ -641,11 +642,14 @@ tcp_input(m, off0, proto) goto drop; } } + rstreason = BANDLIM_RST_NOTOPEN; goto maybedropwithreset; } tp = intotcpcb(inp); - if (tp == 0) + if (tp == 0) { + rstreason = BANDLIM_RST_NOTOPEN; goto maybedropwithreset; + } if (tp->t_state == TCPS_CLOSED) goto drop; @@ -2259,7 +2263,9 @@ tcp_input(m, off0, proto) * we think we are under attack or not. */ maybedropwithreset: - if (badport_bandlim(1) < 0) + if (rstreason != BANDLIM_RST_NOTOPEN) + rstreason = BANDLIM_RST_OPEN; + if (badport_bandlim(rstreason) < 0) goto drop; /* fall through */ dropwithreset: diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index cb7e05e93696..367fc95a8d96 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -392,6 +392,7 @@ tcp_input(m, off0, proto) struct ip6_hdr *ip6 = NULL; int isipv6; #endif /* INET6 */ + int rstreason = 0; /* For badport_bandlim accounting purposes */ #ifdef INET6 isipv6 = (mtod(m, struct ip *)->ip_v == 6) ? 1 : 0; @@ -641,11 +642,14 @@ tcp_input(m, off0, proto) goto drop; } } + rstreason = BANDLIM_RST_NOTOPEN; goto maybedropwithreset; } tp = intotcpcb(inp); - if (tp == 0) + if (tp == 0) { + rstreason = BANDLIM_RST_NOTOPEN; goto maybedropwithreset; + } if (tp->t_state == TCPS_CLOSED) goto drop; @@ -2259,7 +2263,9 @@ tcp_input(m, off0, proto) * we think we are under attack or not. */ maybedropwithreset: - if (badport_bandlim(1) < 0) + if (rstreason != BANDLIM_RST_NOTOPEN) + rstreason = BANDLIM_RST_OPEN; + if (badport_bandlim(rstreason) < 0) goto drop; /* fall through */ dropwithreset: diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 221dd8d4570c..651e16624d6f 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -353,7 +353,7 @@ udp_input(m, off, proto) udpstat.udps_noportbcast++; goto bad; } - if (badport_bandlim(0) < 0) + if (badport_bandlim(BANDLIM_UNREACH) < 0) goto bad; if (blackhole) goto bad;