I just looked up the RFC1337 about TIME_WAIT Assassination and this is a portion of it.
Figure 1 shows an example of TIME-WAIT assassination. Segments 1-5
are copied exactly from Figure 13 of RFC-793, showing a normal close
handshake. Packets 5.1, 5.2, and 5.3 are an extension to this
sequence, illustrating TWA. Here 5.1 is any old segment that is
unacceptable to TCP A. It might be unacceptable because of its
sequence number or because of an old PAWS timestamp. In either case,
TCP A sends an ACK segment 5.2 for its current SND.NXT and RCV.NXT.
Since it has no state for this connection, TCP B reflects this as RST
segment 5.3, which assassinates the TIME-WAIT state at A!
**
RFC 1337 TCP TIME-WAIT Hazards May 1992
TCP A TCP B
1. ESTABLISHED ESTABLISHED
(Close)
2. FIN-WAIT-1 --> <SEQ=100><ACK=300><CTL=FIN,ACK> --> CLOSE-WAIT
3. FIN-WAIT-2 <-- <SEQ=300><ACK=101><CTL=ACK> <-- CLOSE-WAIT
(Close)
4. TIME-WAIT <-- <SEQ=300><ACK=101><CTL=FIN,ACK> <-- LAST-ACK
5. TIME-WAIT --> <SEQ=101><ACK=301><CTL=ACK> --> CLOSED
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
5.1. TIME-WAIT <-- <SEQ=255><ACK=33> ... old duplicate
5.2 TIME-WAIT --> <SEQ=101><ACK=301><CTL=ACK> --> ????
5.3 CLOSED <-- <SEQ=301><CTL=RST> <-- ????
(prematurely)
**
Now, what confuses me is, in TCP/IP Illustrated volume1, what it says is:
Any delayed segments that arrive for a connection while it is in the
2MSL wait are discarded.
So, why did the TCP A in RFC 1337's figure 1 ACK the old duplicate segment?
RFC 793 states in 'Reset generation':
If the connection is in a synchronized state (ESTABLISHED,
FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT),
any unacceptable segment (out of window sequence number or
unacceptible acknowledgment number) must elicit only an empty
acknowledgment segment containing the current send-sequence number
and an acknowledgment indicating the next sequence number expected
to be received, and the connection remains in the same state.
Related
I have implemented SIP calls over TCP.
Now I intend to extrapolate it to REGISTRATION over TCP.
I have a reference PCAP with the following flow:
Logic for Sequence number and Acknowledgement number for initial registration:
A------------------------------------B Seq - Ack - Size
REGISTER
----------------------------------→ 1 - 1 - 709
100 Giving a Try
<---------------------------------- 1 - 710 - 358
401 Unauthorized
<---------------------------------- 359 - 710 - 459
REGISTER
----------------------------------→ 710 - 818 - 931
100 Giving a Try
<---------------------------------- 818 - 1641 - 358
200OK
<---------------------------------- 1176 - 1641 - 450
sequence number of current leg= (sequence number of previous leg in same direction+window size of previous leg in same direction.)
Ack number of current leg =(Ack number of previous leg) {if current leg is in same direction as previous one}
=(sequence number of previous leg)+(window size of previous leg ) {else}
I am trying to understand the following:
Should the refresh instance be part of the same TCP stream?
Which means should the Src and dest IP addresses and Src and Dest Port addresses of the refresh instance be the same as the initial registration?
What logic should be applied to the Seq and Ack numbers?
Should they be in continuation to the previous messages (initial registration attempt) or should these values be as if a new instance is being generated between the given devices?
PS: I am working on a tool that generates calls among devices, so src and dest message code is within my realm.
SIP registrations are independent of the used transport protocol. If you want to update an existing SIP registration that was established over a TCP connection you can send the registration update request over the same TCP connection, another TCP connection or even via UDP. As long as the request is sent to the same registrar the update request will be treated as such.
More information on the use of seq numbers and SIP registration (update) in the Registration section of RFC 3261.
More information SIP registration paths and the use of (different) transport protocols in RFC 5626.
When connection sets up, there is:
Client ------SYN-----> Server
Client <---ACK/SYN---- Server ----①
Client ------ACK-----> Server
and when termination comes, there is:
Client ------FIN-----> Server
Client <-----ACK------ Server ----②
Client <-----FIN------ Server ----③
Client ------ACK-----> Server
my question is why ② and ③ can not set in the same package like ① which is ACK and SYN set in one package ???
After googling a lot, I recognized that the four-way is actually two pairs of two-way handshakes.
If termination is a REAL four-way actions, the 2 and 3 indeed can be set 1 at the same packet.
But this a two-phase work: the first phase (i.e. the first two-way handshake) is :
Client ------FIN-----> Server
Client <-----ACK------ Server
At this moment the client has been in FIN_WAIT_2 state waiting for a FIN from Server. As a bidirectional and full-duplex protocol, at present one direction has break down, no more data would be sent, but receiving still work, client has to wait for the other "half-duplex" to be terminated.
While the FIN from the Server was sent to Client, then Client response a ACK to terminate the connection.
Concluding note: the 2 and 3 can not merge into one package, because they belong to different states. But, if server has no more data or no data at all to be sent when received the FIN from client, it's ok to merge 2 and 3 in one package.
References:
http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm
http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentProcessTheThreeWayHandsh-3.htm
http://www.tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF-2.htm
I think of course the 2 and 3 can merge technically, but not flexible enough as not atomic.
The first FIN1 C to S means and only means: I would close on my way of communication.
The first ACK1 S to C means a response to FIN1. OK, I know your channel is disconnected but for my S(server) way connection, I'm not sure yet. Maybe my receiving buffer is not fully handled yet. The time I need is uncertain.
Thus 2 and 3 are not appropriate to merge. Only the server would have right to decide when his way of connection can be disconnected.
From Wikipedia - "It is also possible to terminate the connection by a 3-way handshake, when host A sends a FIN and host B replies with a FIN & ACK (merely combines 2 steps into one) and host A replies with an ACK.[14]"
Source:
Wikipedia - https://en.wikipedia.org/wiki/Transmission_Control_Protocol
[14] - Tanenbaum, Andrew S. (2003-03-17). Computer Networks (Fourth ed.). Prentice Hall. ISBN 0-13-066102-3.
Based on this document, we can see the detail process of the four way handshake as follows
The ACK (marked as ②) is send by TCP stack automatically. And the next FIN (marked as ③) is controlled in application level by calling close socket API. Application has the control to terminate the connection. So in common case, we didn't merge this two packets into one.
In contrast, the ACK/SYN (marked as ①) is send by TCP stack automatically. In the TCP connection establishment stage, the process is straightforward and easier, so TCP stack handles this by default.
If this is observed from the angle of coding, it is more reasonable to have 4 way than 3 way although both are possible ways for use.
When a connection is to be terminated by one side, there are multiple possibilities or states that the peer may have. At least one is normal, one is on transmitting or receiving, one is in disconnected state somehow all of a sudden before this initiation.
The way of termination should take at least above three into consideration for they all have high probabilities to happen in real life.
So it becomes more natural to find out why based on above. If the peer is in offline state, then things are quite easy for client to infer the peer state by delving into the packet content captured in the procedure since the first ack msg could not be received from peer. But if the two messages are combined together, then it becomes much difficult for the client to know why the peer does not respond because not only offline state could lead to the packet missing but also the various exceptions in the procedure of processing in server side could make this happen. Not to mention the client needs to wait large amount of time until timeout. With the additional 1 message, the two problems could become more easier
to handle from client side.
The reason for it looks like coding because the information contained in the message is just like the log of code.
In the Three-Way Handshake (connection setup) : The server must acknowledge (ACK) the client's SYN and the server must also send its own SYN containing the initial sequence number for the data that the server will send on the connection.
That why the server sends its SYN and the ACK of the client's SYN in a single segment.
In connection Termination : it takes four segments to terminate a connection since a FIN and an ACK are required in each direction.
(2) means that The received FIN (first segment) is acknowledged (ACK) by TCP
(3) means that sometime later the application that received the end-of-file will close its socket. This causes its TCP to send a FIN.
And then the last segment will mean that The TCP on the system that receives this final FIN acknowledges (ACK) the FIN.
The Windows registry has a key TcpAckFrequency (default 2), which sets the number of TCP packets received before sending back an ACK packet. Also, there is a TcpDelAckTicks key defining the delay (default 2 i.e. 2 * 100 ms = 200 ms) after which an acknowledgment is sent anyway, even if TcpAckFrequency is not reached.
Is there any way to change (temporarily) these parameters using WinSock API or other APIs, but without modifying the registry?
Thank you very much in advance.
From the HAProxy documentation on client timeouts:
It is a good practice to cover one or several TCP packet losses by
specifying timeouts that are slightly above multiples of 3 seconds
(eg: 4 or 5 seconds).
That seems like an arbitrary number. What is the significance of the 3 second figure?
It appears this is the default TCP retransmission timeout. From this Microsoft KB article:
TCP starts a re-transmission timer when each outbound segment is
handed down to IP. If no acknowledgment has been received for the data
in a given segment before the timer expires, then the segment is
retransmitted, up to the TcpMaxDataRetransmissions times. The default
value for this parameter is 5.
The re-transmission timer is initialized to 3 seconds when a TCP
connection is established; however it is adjusted "on the fly" to
match the characteristics of the connection using Smoothed Round Trip
Time (SRTT) calculations as described in RFC793. The timer for a given
segment is doubled after each re-transmission of that segment. Using
this algorithm, TCP tunes itself to the "normal" delay of a
connection. TCP connections over high-delay links will take much
longer to time out than those over low- delay links.
I am reading 《Internetworking with TCP/IP》 by Douglas Comer,and when talking about creating a tcp connection ,there is a problem:
Suppose an implementation of TCP use
initial sequence number 1 when it
creates a connection,Explain how a
system crash and restart can confuse a
remote system into believing that the
old connection remained open.
I can't figure out why,please help me,Thanks.
Consider why a connection may get duplicate sequence numbers normally.
Then consider how the receiving system would handle a packet with a "duplicate" sequence number (because the transmitting system started reusing sequence numbers in packets it is using try to re-establish a connection).
*Edit: *
OP says:
but when re-establish the connection,the transmitting system will send a segment with SYN code bit set(and the sequence number be set 1 of course),won't that(SYN code bit set) inform the receiving system it is a new connection trying to be established ?see wiki for Transmission_Control_Protocol,it says that "Only the first packet sent from each end should have this flag(SYN) set."
But packets get lost and delayed and arrive out of order. You can't simply say everything arriving after the packet with the SYN flag is new. Lets say some of the old packets are delayed and arrive after establishment of a new connection. How do you distinguish whether a packet with sequence number #10 is from the old connection or new one? The worse case scenario is that it's from the old connection and the receiving system accepts it as from the new connection. When the real new connection packet #10 arrives, it's ignored as an unnecessary retranmission. The stream is corrupted without any indication of it.
http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentSequenceNumberSynchroniz.htm
... The problem with starting off each connection with a sequence number of 1 is that it introduces the possibility of segments from different connections getting mixed up. Suppose we established a TCP connection and sent a segment containing bytes 1 through 30. However, there was a problem with the internetwork that caused this segment to be delayed, and eventually, the TCP connection itself to be terminated. We then started up a new connection and again used a starting sequence number of 1. As soon as this new connection was started, however, the old segment with bytes labeled 1 to 30 showed up. The other device would erroneously think those bytes were part of the new connection.
... This is but one of several similar problems that can occur. ...
The other issue with a predictable initial sequence number, such as starting at 1 every time, is that the predictability presents a vulnerability:
A malicious person could write code to analyze ISNs and then predict the ISN of a subsequent TCP connection based on the ISNs used in earlier ones. This represents a security risk, which has been exploited in the past (such as in the case of the famous Mitnick attack). To defeat this, implementations now use a random number in their ISN selection process.
Mitnick attack - http://www.cas.mcmaster.ca/wiki/index.php/The_Mitnick_attack
It's far worse than that though anyway - being predictable with sequence numbers makes spoofing and injecting an order of magnitude easier
After restart, if the first TCP connection is towards the same remote system, and since the sequence number will again be 1 - consider what that will cause.