tis 2003-03-11 klockan 14.50 skrev Gianni Tedesco:
> Sounds racy. If you get a SYN for svr1 and start connecting, by the time
> the connect succeeds you could have got a RST and a new SYN to svr2,
> when you come back to accept you will accept the wrong connection. Even
> if you watch for RSTs there is always a window for a race condition
> between connecting to the server and calling the accept as the RST can
> be received *inside* the accept() system call and of course the earliest
> time you can know is right after you already accepted the wrong
> connection.
>
> I am convinced that the only 100% solution has to be done in kernel
> space. That is not to say you can't get a good 99% solution with
> existing interfaces.
Making a 100% solution if at all possible will as you said require
substantial rewrites of the TCP kernel, in ways it is not at all
intended to be used today.
For all practical purposes, using QUEUE as an early detection and delay
of connection requests can give you a 99.5% solution, and a little not
too ugly application level glue can hide the remaining 0.5%.
Proposed solution:
1. Use QUEUE to detect and delay client SYN requests until the upstream
connection have been established.
1a) Receive a SYN. Initiate upstream connection and record the
characteristics of the corresponding client connection (source IP:PORT).
Then the upstream connection is established instruct QUEUE to accept the
SYN packet.
1b) If establishing the upstream connection takes too long, instruct
QUEUE to drop the SYN (the client will retransmit).
1c) If a SYN is received matching the characteristics of an existing
upstream connection instruct QUEUE to accept the packet immediately if
the connection is established, or drop the previous SYN packet if not
yet established.
2. When accepting a client connection, pick up the now established
server connection. If no established server connection is found initiate
a new connection.
3. Use a relatively short (<10s) timeout on waiting server connections
to get rid of connections where the client never fulfilled the
connection.
4. Switch to the normal "deferred initiation" mode if the number of
waiting server connections for which no client connection have been seen
goes above a certain threshold.
> Well theoretically it is possible (just not with that interface). You
> just send a SYN to the server when you get one from a client and send
> the SYN-ACK back to the client only when you have it from the server.
> The end server needs syncookies available of course, where as with the
> current code it doesn't.
Thinking... not quite. The thing with syncookies is that no state needs
to be kept. This can only be done on the TCP listening side, not the
client. In this case you need to keep state for the initiated server
connection which invalidates the idea of SYN cookies..
If you want to look into this approach then you better completely change
approach on how to intercept connections in TPROXY, and instead of
allowing applications to intercept connect requests or initiate
connections as the client, allow applications to intercept both
directions of an already established connection, but then you are
seriously bending TCP and are begging for problems in TCP option
processing etc.
> In fact for one of our clients just putting squid in front of their
> servers and enabling syncookies allowed them to operate through a
> synflood attack which until then had crippled their windows servers.
> This is a great advantage to the current model :)
Which is a very different story from the case of SYN flood protecting in
a transparent proxy with deferred client accepts until the server
connection have been established..
Regard
Henrik
-- Henrik Nordstrom <hno@squid-cache.org> MARA Systems AB, SwedenReceived on Tue Mar 11 2003 - 07:40:16 MST
This archive was generated by hypermail pre-2.1.9 : Tue Dec 09 2003 - 16:19:32 MST