Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Jul 2001 21:49:03 -0500 (CDT)
From:      Mike Silbersack <silby@silby.com>
To:        <freebsd-arch@freebsd.org>
Subject:   TCP Initial Sequence Numbers: We need to talk
Message-ID:  <20010717212424.X3382-100000@achilles.silby.com>

next in thread | raw e-mail | index | archive | help

As those of you watching -net and -hackers may have noticed, we're
starting to see more reports of our current TCP ISN generation scheme
causing problems for users.  The effect is far greater than it was
expected to be, and we need to fix this before 4.4 freezes.

I'm no longer pushing for my previous suggestion of storing per-host
sequence numbers.  I have been unable to find people willing to review it,
and many people concerned about having to track such state.

I think I've found a solution that will be acceptable to all.  But first,
here's a little background on the current state of things for those who
have just tuned in.

In response to Tim Newsham's paper on the flaws of random positive
incrementation of ISNs, we switched to using a generation scheme used by
OpenBSD.  The OpenBSD scheme has a few specially designed features, but
can basically be classified as a random number generator.  Hence, there is
no monotonicity in the ISNs generated by systems using this method.

For the purpose of generating ISNs for SYN-ACKs, this scheme works quite
well.  However, for the purpose of generating ISNs for SYNs, there are
some quirks.  If there is no preexisting socket on the receiver's side, a
random ISN will work properly.  However, if our SYN is received by a
socket currently in the TIME_WAIT state, a problem arises.

BSD based network stacks (including FreeBSD) check the sequence number of
the incoming SYN packet for sockets in the TIME_WAIT state.  If the
incoming sequence number is greater than the last sequence number of the
socket, the old socket is destroyed, and a new one is created in its
place.  However, if the incoming sequence number is less, this recycling
will _not_ take place.  As a result, the connection will be delayed until
after the TIME_WAIT socket times out, or never connect in the case where
the socket persists longer than the SYN retry timeout.

When using randomly generated sequence numbers in SYNs, we cause this
undesireable case to happen quite often.  This causes numerous delays and
failures for apps which constantly connect to another app (sql backends,
etc.)

So, in short, we must change algorithms.

There are two guidelines we should abide by:

1.  The ISNs we use in SYN-ACK packets must be as random as possible to
avoid spoofing and prediction of the sequence numbers of other
connections.

2.  The ISNs we use in SYN packets must be monotonic on a
per-(lhost,lport,rhost,rport) basis.  To protect against RST and data
injection attacks, they must also be unknown to anyone other than lhost
and rhost.

In order to meet these requirements, I propose that we use the following
system:

For SYN-ACKs:  Use the value of arc4random() as our ISN.

For SYNs:  Use the value generated by the rfc1948 scheme, with the
modification that the secret used in the hash be changed on a weekly
basis.  (This will break recycling for perhaps a minute a week, but it
will ensure that the hash can not be bruteforced and also make sure that
the system's uptime cannot be easily tracked.)

Comments are appreciated.

Mike "Silby" Silbersack



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010717212424.X3382-100000>