Subject: Re: kernel ip_randomid() and libc randomid(3) still "broken"
To: Jonathan Stone <jonathan@DSG.Stanford.EDU>
From: Robert Elz <kre@munnari.OZ.AU>
List: tech-net
Date: 11/18/2003 13:30:41
    Date:        Mon, 17 Nov 2003 14:03:11 -0800
    From:        Jonathan Stone <jonathan@DSG.Stanford.EDU>
    Message-ID:  <200311172203.OAA28947@Pescadero.DSG.Stanford.EDU>

  | Done. I have heard, but consciously did not adopt, your suggestion
  | about passing dst-address.

Thanks, or I think perhaps thanks soon...  Maybe I just updated by
tree at the wrong time, but at the minute I can't find ip_newid()
(the actual function source).   Did you perhaps forget to commit ip_id.c ?

  | For me, its actually fairly common for the muli-homed tests I run
  | (I have an .. unusual setup).

Yes, there are just some odd cases where it might make a difference,
but I really suspect that they're very rare.   And wrt (from a different
message) ...

  | Then again, I'm watching 10GbE prices like a hawk, waiting for 10GbE-CX4
  | adaptors to come out. 

In a GB type environment like this, do you really want to be doing
reassembly at all, ever?    Wouldn't you be better off just setting DF
and then leaving the id as 0 (or anything) for most of that traffic,
even if that means really making GB's jumbo frames work and be better
supported (if they're not well enough already - unfortunately where I
am at the minute, I have no GB equipment to play with - an interface
but nothing to connect it to).

Overall here, the ID generation we're doing can be anything from one
global generator (the current system, with or without random IDs)
to one generator (linear, linear congruent, or random) per (src,dst,proto)
tuple.   Or something between.    You already pointed out that even for
your needs, the proto value in that tuple adds nothing of value (though
it is possible for some others it might make some useful difference).
For most systems, I doubt the src really makes much difference either
(again, for a few it does) - after all, most systems have just a small
handful of src addresses to pick from, so all you can usually gain is
perhaps a 2 or 3 fold increase in the id lifetimes (assuming all src
addresses are equally used).   That isn't enough to compensate for a
GB -> 10BG jump.

I certainly agree that putting in all the baggage that you mention to
allow (src,dst) (or src,dst,proto) unique ID generators right now wouldn't
be the thing to do.   I'm not sure that worrying about 2.0 is worthwhile
yet, I don't see that as being that close to the horizon (but I am looking
from a long way away) - more that I'm not sure that all that baggage would
ever be worth it.

Regardless of how fast your interfaces go, there can only be a limited set
of hosts with which you're communicating for which ID wraparound can
be a problem (even assuming that DF=1 isn't a plausible solution).  At
least in the forseeable future (when we get multi TB interfaces then
maybe - but by then IPv6 is likely to dominate, I hope, and DF==1 will
be the normal thing).   So, all that's really needed is for those hosts
(or (src,dst) pairs perhaps) to have individual ID counters - what IDs
are put on packets going elsewhere is largely irrelevant (whether they
come from the same ID generator as used for one of the fast hosts, or not).

This is why I think a simple mapping of addr -> ID generator is likely
to be good enough, even for your setup (though perhaps you might want to
include the src addr in it).   My guess is that a really simple function,
line using the low N bits of the address (src or dst) might just suit
your needs ideally (though perhaps be not quite as good for others).

Why not try

#define ID_BUCKETS	1024
#define	IP_ID_HASH(n)	((n) & (ID_BUCKETS-1))

static uint16_t ip_id_buckets[ID_BUCKETS];

uint16_t
ip_newid(struct in_addr dst)
{
	return ip_id_buckets[IP_ID_HASH((uint32_t)(dst.s_addr))]++;
}

or something like that, and see whether it improves things or not?
I believe that's simple enough to add now, and has enough advantages
(for everyone) to be worth doing.

Do note that the more buckets there (with the ultimate limit being
one for each (src,dst,proto)) the bigger the spoofing problem becomes.
Approaching the limit, a good random generator, which also doesn't
reuse ID's (which is almost a contradiction in itself) gets more and
more important - part of the reason that spoofing isn't trivial now is
that no-one can predict how many packets you'll send to a different
host before the next to the target, which means packet storms are
needed to get in a "good" spoofed packet.   One linear generator per
target and now the ID to be in the next packet will be known from the
previous one.

kre