FIN vs RST in TCP connections - networking

The way I understand this, there are 2 ways to close TCP connection:
send FIN flag
send RST flag
RST causes immediate connection termination, while in FIN you get a confirmation.
Do I understand this right, and are there any other distinctions between the two? Can those 2 flags be used together?

FIN says: "I finished talking to you, but I'll still listen to everything you have to say until you say that you're done."
RST says: "There is no conversation. I won't say anything and I won't listen to anything you say."
RST is useful if you have long lasting TCP connection with little traffic. If one of the computers is restarted, it forgets about the connection, and the other computer gets RST, as soon as it sends another packet.

FIN or RST would be sent in the following case
your process close the socket
OS is doing the resource cleanup when your process exit without closing socket.
If your process call close(), FIN would be sent from the closing side by default (note: you can set socket option SO_LINGER to make it send RST instead of FIN)
If your process exit without closing the socket, kernel would close the tcp connection and do the clean up for your process. FIN or RST can be sent. If there is data in your receive queue, RST would be sent. Otherwise, FIN would be sent.
You can loop through tcp_close() in tcp.c for more details.(I am using kernel-2.6.32-573.7.1 from redhat branch)

From RFC 1122, which everybody keeps citing, but not actually quoting, against me:
A TCP connection may terminate in two ways: (1) the normal
TCP close sequence using a FIN handshake, and (2) an "abort"
in which one or more RST segments are sent and the
connection state is immediately discarded.
It is not possible to use both at the same time. The concept doesn't even begin to make sense.
It is possible by means of trickery which I will not describe here to close a TCP connection with an RST instead of a FIN, but it's a stupid idea, which is why I am not documenting it. For one thing, all pending data in flight is lost.

Related

What is a FIN+ACK message in TCP?

I'm working on implementing TCP myself for a class project, and there's one detail I can't seem to understand. What is a FIN+ACK message? In the diagram I included here, receipt of a FIN+ACK will take a host from the FIN_WAIT_1 state to the TIME_WAIT state. Yet, NO state transition in the entire diagram sends a FIN+ACK. So how could a FIN+ACK ever be received if nothing is ever sending it?
When an application calls close it moves to FIN_WAIT_1
From FIN_WAIT_1 multiple things can happen:
Application receives ACK:
This means that the peer as acknowledged the last sent data packet. Local application moves to FIN_WAIT_2
Application receives FIN:
This indicates that peer has called close. And local application should acknowledge that. Hence ACK goes out to peer. Local application moves to CLOSING
Application receives FIN + ACK:
What FIN+ACK as you put it means is that the peer has called close as well as in the same TCP segment is acknowledging the data received last. Local application will acknowledge the FIN and this takes the state to TIME_WAIT.
TCP is defined by more than just that state diagram, the basic specification can be found in RFC 793. One particular statement is as follows (page 15, description of ACK field):
Once a connection is established this is always sent.
So basically this says an ACK must always be present after the initial three-way handshake, including during the four-way disconnect phase. There are subsequently only 2 messages that do not include an ACK:
The very first SYN as there is nothing to ACK
A RST as this usually means the connection state is non-existent or so messed up that an ACK does not make sense.
So to answer your question: in that diagram, whenever a FIN is sent, the ACK flag will also be set and an ACK nr will be present, even though it is not explicitly stated.

TCP four-way handshake

Four-way handshake connection termination can be reduced to three-way and even two way one. Is it possible the three-way handshake connection establishment would be extended to four-way?
SYN=>
<=ACK
<=SYN
ACK=>
Given the semantics of SYN and ACK it should be possible to send SYN+ACK in different packets and those delay the handshake. E.g. client sends a SYN, server replies with an ACK to acknowledge the wish of the client for a new connection, but it does not grant the wish yet. Later the server sends a SYN and gets the matching ACK back from the client and the connection is established. But I doubt that anybody does connection establishment this way and it might be, that some OS will croak on it.
But, there is another scenario for a four-way-handshake, however with a different ordering of the packets. It could happen, if both side try to establish a connection to the other side at the same time, e.g. both send a SYN to the peer, and get an ACK back. It is described in the RFC 793 (TCP) section 3.4. But I doubt you will ever see such a handshake, because it does not fit into the typical client-server-scenario where one end is waiting for connects and the other end does the connect.
Edit: the handshake you envision exists and it is called "split handshake". See http://hackmageddon.com/2011/04/17/tcp-split-handshake-attack-explained/ . And like I expected, it is not universally supported.

how to close a tcp connection if FIN/ACK doesn't get a ACK response?

in a tcp program written in Linux C
I want to close a tcp connectin
I used close(sockfd)
I notice this function will initiate a FIN/ACK packet to the other peer
but if the other peer doesn't respond an ACK due to network problem or tcp sequnce number inconsistency(e.g the tcp stack of the other peer crashes)
then it seems the tcp connection can't be closed
it will always be in FIN_WAIT1 status
how to deal with this?
how to close the tcp connection in such cases?
TCP deals with it. You don't have to deal with it. You can't deal with it.
By default, this is transparently handled by the TCP implementation according to system-wide configuration parameters which are system-dependent.
This can be overridden by setting the SO_LINGER socket option using setsockopt(), in which case the call to close() blocks until the specified timeout is reached.
Edit: I should add that most of the time using SO_LINGER is only worth the hassle if the goal is to add some error handling such as logging an error message stating that possibly some data was not received by the other end.

Unexpected TCP RST packet

We are facing random RST packet problem in our environments, which causes some unexpected behaviors, following image is snapshot of the tcp data generated by wireshark, which shows the problem:
Client (117.136.2.181) successfully sets up the connection with the server (192.168.40.16)
Client sends some data to the server, as well the KEEP_ALIVE signal.
Server receives the data, process it and sends the result back to client.
Server close the socket.
Server does not receive the ACK signal from client, so it re-transmits the result data as well as the FIN signal, this is automatically done by TCP protocol. However, server still does not receive the ACK signal from client.
Server sends a RST signal to client so connection is closed.
After some analysis, we think some network problem happens after step 3, so all the result data and FIN signal sent from server are not ack'd by client, but we are very confused about the RST signal sent from the server. Based on our understanding, a RST signal is sent if a half-closed socket receives some data, or if there is data in the receive queue when closes a socket. But both these seem not be the root cause of our case.
Can some one help to elaborate why this is happening?
RST usually happens when close is called on the socket without shutdown, or after a shutdown while the other party is still trying to send data (still has not replied with an FIN).
Some programming languages have a socket.close(timeout) for example .NET, that calls shutdown then close after timeout has passed.
So the client have up to timeout to finish sending and closing the connection with FIN, if it fails to do so, the connection will be forcibly closed by RST.
See https://stackoverflow.com/a/23483487/1438522 for a more thorough explanation about difference between close and shutdown.

Why TCP RST packet generated what are the possible cause

when TCP RST packet generated? what are the possible cause of generation on TCP RST packet?
The RST flag is used to signal any kind of error and terminate the connection.
If you send a packet with a wrong ACK, you will get a RST
If you don't acknowledge data in a timely manner, you get a RST
Basically, if you do anything wrong, a TCP will send a RST and terminate the connection.
It is also possible that Linux Kernel sent these RSTs.
An example:
http://blog.facilelogin.com/2010/12/hand-crafting-tcp-handshake-with-scapy.html

Resources