TCP SYN Proxy & I HAVE IT!

Nicholas Jenkins njenkins@voyager.net
Sat, 8 Sep 2001 00:32:09 -0400


Let me recap to make sure we're all thinking the same thing(s)...

SYN attacks are Bad.

SYN attacks currently fall into 2 groupings:
1) A machine generates many messages from a spoofed source addresses and
sends them to a single machine, which tries to respond, but ties up its TCP
connection table while waiting for the final ACK back, that it never gets,
because there is no machine actually at the spoofed address, or because the
machine that is there is not the one that sent a packet to begin with (this
brings up and interesting thought...)
2) A machine, or more likely, a bunch of machines working in concert
generates many messages using its/their real source address(es), just to use
all available TCP connections on the destination machine.

#2 is has a pretty straightforward solution for protection from either a
firewall, or the machine's own IP stack - only allow X many connections
within a specific time frame from a singular host, where X should be large
enough to not keep out "normal" users, but small enough to keep 1 (or a
small group of) machine(s) from flooding it.

#1 on the other hand is tough...SYNcookies (which I did not realize Linux
supported...dummy me) solves the problem for the local IP stack - great.
However, it doesn't solve the problem for a firewall/gateway.  For that, I
see only 1 solution - a proxy.  Why a proxy, you ask...The primary reason I
see is that we should (at this point in time) assume that the machine
connecting to our web server is actually a NATed address from inside a
remote firewall, and that only a reply from the client-requested destination
will be allowed back, so merely pinging (or equivalent) the remote host is
out - so, without using the connection itself, we have no hope of verifying
the remote system really exists (and will respond) before tying up our
resources on establishing the connection.  In fact, this is the crux of the
problem - How do we verify that a machine really exists and will respond,
before continuing with the connection?

With a proxy, the solution seems easy - just continue the TCP handshaking to
verify the machine's existence before bothering our local server.  Now the
problem is, how do I write the proxy?  A full TCP proxy?  Or, just a TCP SYN
proxy?

How about this... (drum roll please - (and God, I hope I'm correct, or I'm
going to catch so much crap))...
1) We accept the inital SYN packet and squirrel it to the side (*)
2) We reply with a SYN,ACK packet without contacting the local server, or
anything, only...
           WE SET THE "EXPECTED FIRST DATA SEQUENCE NUMBER" TO ANYTHING
OTHER THAN THE CORRECT VALUE!
3) According to Fig 9&10 of RFC793, this should for one reason or another
cause the remote machine to send a RST packet, with the "BAD" sequence
number back
4) Now we know that the machine exists, and we can forward the initial
packet (unchanged) to the internal server.

If we let the TCP spec do this work for us, the firewall/filter/proxy has
very little work to do, at the expense of 2 additional packets.  The 3-way
handshake becomes a 5-way handshake.  However, for something like a web
server, where it is no big deal to download web pages of 10-150k or more,
with a 1500 byte window, these 2 additional, small packets are moot.

The (*) above is meant to indicate a special case...if you don't want the
firewall to have to cough-up memory to store the initial connection
requests, use a SYNcookie!  Since the value will be returned in the RST
packet (assuming an implementation that follows RFC793...), you could decode
the SYN cookie back into the original connection request, and just forward
it on after the RST (I think - I'm still getting up to speed on how SYN
cookies work...)

Well, what do you think?

-NICK