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 <[EMAIL PROTECTED]> MARA Systems AB, Sweden
