FreeBSD and the Rose Attack / NewDawn
Mike Silbersack
silby at silby.com
Thu May 12 22:57:01 PDT 2005
On Thu, 12 May 2005, Gandalf The White wrote:
> # patch ip_reass-20050507.diff
> Recompile kernel
>
> I ran:
> # top
>
> I ran the test again and CPU utilization was at close to 98% to 99% in the
> interrupt column.
>
> Ken
Brooks Davis and myself ran some tests tonight while sitting around at
BSDCan and came to the conclusion that IP Reassembly overhead is not the
main problem here. This conclusion was derived from the patch I've
attached to this e-mail (please tell me if it gets stripped off.)
On my laptop, we found that we could hit it with 14000 frags per second,
and it didn't matter if those frags were all processed, or all ignored
(via the net.inet.ip.maxfragspersecond sysctl). Either way, the amount of
cpu time used was about the same - 70%.
But on another laptop with the same processor, 8000 pps could effectively
freeze it. We believe this is because the network card on that machine
shares an IRQ with the sound card, making interrupt processing very
expensive.
So, test out my attached patch with varying settings of maxfragspersecond
and see if it makes any difference for you.
Thanks,
Mike "Silby" Silbersack
-------------- next part --------------
diff -u -r /usr/src/sys.old/netinet/in_pcb.c /usr/src/sys/netinet/in_pcb.c
--- /usr/src/sys.old/netinet/in_pcb.c Sun Apr 17 18:05:05 2005
+++ /usr/src/sys/netinet/in_pcb.c Thu May 12 21:47:39 2005
@@ -1234,5 +1234,10 @@
ipport_stoprandom--;
}
ipport_tcplastcount = ipport_tcpallocs;
+ if (ip_curfragspersecond > ip_maxfragspersecond) {
+ printf("Received %d frags, exceeded %d per second\n.",
+ ip_curfragspersecond, ip_maxfragspersecond);
+ }
+ ip_curfragspersecond = 0;
callout_reset(&ipport_tick_callout, hz, ipport_tick, NULL);
}
diff -u -r /usr/src/sys.old/netinet/ip_input.c /usr/src/sys/netinet/ip_input.c
--- /usr/src/sys.old/netinet/ip_input.c Sun Apr 17 18:05:06 2005
+++ /usr/src/sys/netinet/ip_input.c Thu May 12 21:49:52 2005
@@ -130,6 +130,12 @@
&maxfragsperpacket, 0,
"Maximum number of IPv4 fragments allowed per packet");
+int ip_curfragspersecond;
+int ip_maxfragspersecond;
+SYSCTL_INT(_net_inet_ip, OID_AUTO, maxfragspersecond, CTLFLAG_RW,
+ &ip_maxfragspersecond, 0,
+ "Maximum number of IPv4 fragments allowed per second");
+
static int ip_sendsourcequench = 0;
SYSCTL_INT(_net_inet_ip, OID_AUTO, sendsourcequench, CTLFLAG_RW,
&ip_sendsourcequench, 0,
@@ -284,6 +290,7 @@
TAILQ_INIT(&ipq[i]);
maxnipq = nmbclusters / 32;
maxfragsperpacket = 16;
+ ip_maxfragspersecond = 100;
/* Start ipport_tick. */
callout_init(&ipport_tick_callout, CALLOUT_MPSAFE);
@@ -802,7 +809,9 @@
u_short hash;
/* If maxnipq or maxfragsperpacket are 0, never accept fragments. */
- if (maxnipq == 0 || maxfragsperpacket == 0) {
+ if (maxnipq == 0 || maxfragsperpacket == 0 ||
+ ip_curfragspersecond >= ip_maxfragspersecond) {
+ ip_curfragspersecond++;
ipstat.ips_fragments++;
ipstat.ips_fragdropped++;
m_freem(m);
@@ -884,6 +893,7 @@
* ip_reass() will return a different mbuf.
*/
ipstat.ips_fragments++;
+ ip_curfragspersecond++;
m->m_pkthdr.header = ip;
/* Previous ip_reass() started here. */
@@ -1069,6 +1079,7 @@
ip->ip_len = (ip->ip_hl << 2) + next;
ip->ip_src = fp->ipq_src;
ip->ip_dst = fp->ipq_dst;
+ ip_curfragspersecond -= fp->ipq_nfrags;
TAILQ_REMOVE(head, fp, ipq_list);
nipq--;
(void) m_free(dtom(fp));
Only in /usr/src/sys/netinet: ip_input.c.old
diff -u -r /usr/src/sys.old/netinet/ip_var.h /usr/src/sys/netinet/ip_var.h
--- /usr/src/sys.old/netinet/ip_var.h Sun Apr 17 18:05:06 2005
+++ /usr/src/sys/netinet/ip_var.h Thu May 12 21:16:47 2005
@@ -61,6 +61,8 @@
struct mbuf *ipq_frags; /* to ip headers of fragments */
struct in_addr ipq_src,ipq_dst;
u_char ipq_nfrags; /* # frags in this packet */
+ u_short ipq_len; /* length of final packet */
+ u_short ipq_curlen; /* how much we've gotten so far */
struct label *ipq_label; /* MAC label */
};
#endif /* _KERNEL */
@@ -156,6 +158,8 @@
extern u_long (*ip_mcast_src)(int);
extern int rsvp_on;
extern struct pr_usrreqs rip_usrreqs;
+extern int ip_curfragspersecond;
+extern int ip_maxfragspersecond;
int ip_ctloutput(struct socket *, struct sockopt *sopt);
void ip_drain(void);
More information about the freebsd-net
mailing list