public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Route cache performance under stress
@ 2003-04-05 16:37 Florian Weimer
  2003-04-05 18:17 ` Martin Josefsson
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Florian Weimer @ 2003-04-05 16:37 UTC (permalink / raw)
  To: linux-kernel

Please read the following paper:

<http://www.cs.rice.edu/~scrosby/tr/HashAttack.pdf>

Then look at the 2.4 route cache implementation.

Short summary: It is possible to freeze machines with 1 GB of RAM and
more with a stream of 400 packets per second with carefully chosen
source addresses.  Not good.

The route cache is a DoS bottleneck in general (that's why I started
looking at it).  You have to apply rate-limits in the PREROUTING
chain, otherwise a modest packet flood will push the machine off the
network (even with truly random source addresses, not triggering hash
collisions).  The route cache partially defeats the purpose of SYN
cookies, too, because the kernel keeps (transient) state for spoofed
connection attempts in the route cache.

The following patch can be applied in an emergency, if you face the
hash collision DoS attack.  It drastically limits the size of the
cache (but not the bucket count), and decreases performance in some
applications, but 

--- route.c	2003/04/05 12:41:51	1.1
+++ route.c	2003/04/05 12:42:42
@@ -2508,8 +2508,8 @@
 		rt_hash_table[i].chain = NULL;
 	}
 
-	ipv4_dst_ops.gc_thresh = (rt_hash_mask + 1);
-	ip_rt_max_size = (rt_hash_mask + 1) * 16;
+	ipv4_dst_ops.gc_thresh = 512;
+	ip_rt_max_size = 2048;
 
 	devinet_init();
 	ip_fib_init();


(Yeah, I know, it's stupid, but it might help in an emergency.)

I wonder why the route cache is needed at all for hosts which don't
forward any IP packets, and why it has to include the source addresses
and TOS (for policy-based routing, probably).  Most hosts simply don't
face such complex routing decisions to make the cache a win.

If you don't believe me, hook a Linux box to a packet generator
(generating packets with random source addresses) and use iptables to
drop the packets, in a first test run in the INPUT chain (after route
cache), and in a second one in the PREROUTING chain (before route
cache).  I've observed an incredible difference (not in laboratory
tests, but during actual DoS attacks).

Netfilter ip_conntrack support might have similar issues, but you
can't use it in a uncooperative environment anyway, at least in my
experience.  (Note that there appears to be no way to disable
connection tracking while the code is in the kernel.)

^ permalink raw reply	[flat|nested] 14+ messages in thread
* Re: Route cache performance under stress
@ 2003-04-08  6:14 Scott A Crosby
  0 siblings, 0 replies; 14+ messages in thread
From: Scott A Crosby @ 2003-04-08  6:14 UTC (permalink / raw)
  To: linux-kernel

Please CC me on any replies:


The suggested code here is problematic.

   RND1 = random_generated_at_start_time() ;
   RND2 = random_generated_at_start_time() ;
   /* RND2 may be 0 or equal to RND1, all cases seem OK */
   x = (RND1 - saddr) ^ (RND1 - daddr) ^ (RND2 + saddr + daddr);
   reduce(x)

For instance, if the table is assumed to have size N, bucket
collisions can be generated by:

   saddr=daddr= k*N  for all k.

Or, a different attack, if I assume that reduce(x) determines the
bucket by masking off, say, the lowest 12 bits, then:

   saddr=0xXXXXXAAA
   daddr=0xYYYYYBBB

Where, XXX, YYY are anything, AAA, BBB are arbitrarily chosen.

Now, lets look at the various terms:
 (RND1 - saddr)         = 0xUUUUUCCC
 (RND1 - daddr)         = 0xUUUUUDDD
 (RND2 + saddr + daddr) = 0xUUUUUEEE

The U's are all unknown, but the CCC, DDD, and EEE---the only thing
that we care about---are constant. Thus, the lowest 12 bits of x will
be constant. If those are the only bits that are used, then the
attacker has complete freedom to forge the highest 20 bits of saddr
and daddr.

With that function, you'd probably be better off masking off the high
order bits. At least there's a chance of a carry from the UUUU's
propagating into the bits you mask off.

I'm rusty with statistical analysis of cryptographic algorithms, but I
suspect demons may be lurking from that avenue too.


What might work better is to have a good universal hash function, h,
then do:

   h_k(saddr) - h_k(daddr)

Perhaps the simplest is:

  h_k(x) = x * k (mod P)

where P is a prime, and $ 0<= k < P$ is a random variable determined
at bootup.

Scott



^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2003-05-19 19:04 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-04-05 16:37 Route cache performance under stress Florian Weimer
2003-04-05 18:17 ` Martin Josefsson
2003-04-05 18:34 ` Willy Tarreau
2003-05-16 22:24 ` Simon Kirby
2003-05-16 23:16   ` Florian Weimer
2003-05-19 19:10     ` Simon Kirby
2003-05-17  2:35   ` David S. Miller
2003-05-17  7:31     ` Florian Weimer
2003-05-17 22:09       ` David S. Miller
2003-05-18  9:21         ` Florian Weimer
2003-05-18  9:31           ` David S. Miller
2003-05-19 17:36             ` Jamal Hadi
2003-05-19 19:18               ` Ralph Doncaster
  -- strict thread matches above, loose matches on Subject: below --
2003-04-08  6:14 Scott A Crosby

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox