4 ms·
This particular problem is solvable by having (client_sequence_number+1) to be part of the HMAC (thus checking it as well), and by storing the MSS in the MSB pa
by ay 6y ago
This particular problem is solvable by having (client_sequence_number+1) to be part of the HMAC (thus checking it as well), and by storing the MSS in the MSB part of the generated server sequence number rather than in the LSB.
Then every packet other than the first data packet will be discarded as invalid, and eventually the client-side retransmits will take care that everything works properly.
The problem that is impossible to solve, however, is the lost third ACK (acknowledging SYN-ACK) from the client , if the client doesn’t send any data to server upon the connect. It’s sufficiently rare in today’s protocols, though.
Another problem that the above approach will create afresh is that it assumes that the retransmitted client SYNs will have the same ISN, which isn’t the same in practice with e.g. some load balancers (who also try hard not to keep the state). And that behavior is kinda a slightly gray zone in the TCP spec, IIRC...
Edit: (I wonder if the last paragraph above is the real reason or I missed something else)
Edit2: oh, thanks to Majromax’s mention of the DJB’s write-up, the above has the problem of not complying with “sequence numbers increasing slowly”, and indeed brings up a real-world scenario where that approach was an issue - using rcp/rlogin protocols, which reused a very narrow range of source ports, so the 5-tuple reuse was common.
- toast0 6y ago> Another problem that the above approach will create afresh is that it assumes that the retransmitted client SYNs will have the same ISN, which isn’t the same in practice with e.g. some load balancers (who also try hard not to keep the state). And that behavior is kinda a slightly gray zone in the TCP spec, IIRC... I don't think this is a big problem with SYN cookies. If you get a SYN with initial sequence X, you send an appropriate SYN+ACK, and if you get a retransmitted SYN (because the other end didn't get your SYN+ACK), you send a new SYN+ACK appropriate for that one. If you then get an ACK for either, you would form a full connection; which should work fine. I would have to review the RFCS, they might say that if you had room in your syncache to hold the data, you should send a RST to the second SYN or the first SYN, because the states are conflicting; but since you don't have the information you don't have the information. Anyway, unless the client end is really messed up, it shouldn't send both the ACK on the first SYN, because it received your SYN+ACK and a new SYN, because it didn't receive your SYN+ACK. I acknowledge that there are plenty of really messed up TCP stacks on the internet though :)
- a1369209993 6y ago> Anyway, unless the client end is really messed up, it shouldn't send both the ACK on the first SYN This is a race condition; hypothetic sequence of events: send SYN-0, wait for reply or timeout timer interrupt fires timeout to resend SYN(-1) is ready, start running that packet interrupt fires (interrupts resend) got SYN+ACK-0, construct and send ACK-0 iret finish constructing SYN-1 and send it iret again This is clearly a bug, but it could easily work >99.99% of the time (especially if the timeout is high enough that normal RTTs never hit it, which is probably how the person setting the timeout would try to set it).
- toast0 6y agoYeah, I guess someone could write that, and if it worked mostly it would get shipped. Like you said in another post, ugh. Overall, I'd rank that like a 3 out of 10 on the scale of tcp bugs in the wild.