The changes we've made in NetBSD to deal with the `land' attack are:
1) If a socket in LISTEN state receives a SYN+ACK packet, then send a
RST and drop the packet.
2) If a socket in LISTEN state receives a SYN-only packet claiming to
be from itself, then drop the packet.
The rationale for this is as follows:
1) Since the initial sequence number cannot possibly be known, it is
never correct to send an ACK before an initial SYN has been sent.
A socket in LISTEN state didn't send a SYN, unless it was a
SYN+ACK, in response to a SYN-only packet, in the second stage of
the 3WHS. In this case, we would not expect to get another SYN; we
should instead get an ACK-only packet to complete the 3WHS. We
treat the stray SYN+ACK the same as data for an old connection.
2) A socket in LISTEN state is not initiating a connection attempt, so
if it receives a SYN-only packet from itself, it *must* be a
forgery. A self-connect would cause the socket to no longer be in
LISTEN state before the SYN-only packet arrives. There's no point
in sending a RST in this case, since we'd just be sending it to
ourselves.
(Actually, this change isn't really complete; in theory, if the
LISTEN socket was bound to INADDR_ANY, then we should check whether
the source address of the SYN was any of our local addreses, not
just that it matches the destination. However, a failure to detect
the attack at this point will merely generate an extra SYN+ACK that
will be dropped by the first change.)
Interestingly, SunOS (not Solaris) appears to do #1, but still freezes
up. I haven't investigated why.