Home > Experiential Learning > Experiential Learning of Networking Technologies: Understanding TCP States – Part 2

Experiential Learning of Networking Technologies: Understanding TCP States – Part 2

Experiment 3:
TCP State CLOSE_WAIT ($H_{1}$) and FIN_WAIT1 ($H_{2}$)

Let us now consider the other possibility where $H_{1}$ receives the FIN message, but the ACK it sends back to $H_{2}$ as it moves to the CLOSE_WAIT state (refer to Figure 2) gets lost. In this case, the TCP connection state on $H_{2}$ will continue to be FIN_WAIT1. This scenario can be easily simulated by dropping the ACK message on $H_{2}$, as shown in Figure 7 and Figure 8. In this experiment, when $H_{1}$ receives FIN it will send only the ACK (but not FIN) because we will assume that it still has some data to send. This functionality to send data even after receiving FIN from the other side cannot be achieved using the netcat utility (this utility immediately sends a FIN/ACK as response when it receives a FIN message), so we have developed a simple Python program tcp_client.py that sends the current date and time as the data at a specified time interval (option -d) for a specified number of times (option -c). This program can be accessed from [10], and the key part of code is given in the Appendix.

PIC
Figure 7: Sending FIN but not receiving ack of FIN
PIC
Figure 8: Receiving FIN, sending Ack for FIN, Ack is lost

The upper panel of Figure 7 shows the data being received on $H_{2}$. The lower panel of this figure shows the TCP connection state on this machine, which starts from LISTEN (the output of the first netstat command [3][4]). Once the application on machine $H_{1}$ connects, the TCP connection state on $H_{2}$ changes to ESTABLISHED (output of the second command issued at time 22:17:51). Now, the application on $H_{2}$ is aborted using Ctrl-C, so it sends the FIN message and moves to state FIN_WAIT1. The application on machine $H_{1}$ is shown in the upper panel of Figure 8. The lower panel shows the TCP connection state as well as firewall (iptables) commands that are used to mimic the abnormal network conditions. The first line of the lower panel of this figure shows that the connection is established, and then data communication takes place. To simulate poor network conditions, an iptables rule is invoked at time 22:18:04 to drop the ACK packet sent on port 7777. Thus, when at time 22:18:12, Ctrl-C (upper panel of Figure 7) is pressed on $H_{2}$, it sends the FIN message which is received by $H_{1}$. However, the ACK response it sends is dropped by firewall and not received by $H_{2}$. Thus, the state of this connection on $H_{2}$ continues to remain FIN_WAIT1 as shown by the last line of the lower panel of Figure 7. Since the application program on $H_{1}$ is still sending data, it does not send the FIN message and thus its state remains CLOSE_WAIT (output of the third netstat command as shown in lower panel of Figure 8).

Interestingly, the scenario described here can also arise in a perfectly functional network if the web applications are written without a full understanding of TCP connection states. For instance, suppose that when a poorly designed client application running on machine $H_{2}$ encounters an error, it sends the FIN message and immediately exits. Thus, even though the network is functional, the client application running on $H_{2}$ does not receive the ACK from the server application running on $H_{1}$, and the TCP connection state on $H_{1}$ remains in CLOSE_WAIT for a long time. This unnecessarily consumes system resources on the server, which can become a performance bottleneck when the faulty client application is a popular one.

Experiment 4:
TCP State FIN_WAIT1 ($H_{2}$) and LAST_ACK ($H_{1}$)

Another possible case is that the TCP connection state is FIN_WAIT1 on one machine and LAST_ACK on the other. This would occur when $H_{2}$ sends FIN, $H_{1}$ receives FIN and sends the ACK response and moves to the CLOSE_WAIT state (as in previous case) and then the application on $H_{1}$ invokes the close}() call because it has no more data to transmit. Thus, the machine $H_{1}$ will send a FIN message and move the TCP connection state to LAST_ACK state as it waits for the acknowledgement of its FIN in order to finally close the connection. However, when the second FIN message is lost in the network, $H_{2}$ will continue to remain in the FIN_WAIT1 state. This scenario is captured in Figure 9 and Figure 10. The experimental steps as shown in Figure 9 are same as those carried out in previous experiment, but on $H_{1}$ we simply use the netcat (nc) utility. When the TCP connection is closed by the application at other end, nc also immediately closes the connection resulting in the issuance of a FIN message. A firewall rule can be defined to drop this second FIN message.

PIC
Figure 9: Sending FIN, not receiving ACK
PIC
Figure 10: Receiving FIN, sending ACK, and FIN-ACK

In Figure 9, the application (nc server) on $H_{2}$ starts in the upper panel at time 06:03:58, and its initial state is LISTEN as shown in the output of first command in the lower panel at time 06:04:57. The application (nc client) starts on $H_{1}$ at time 06:05:01 and connects to the server as shown in the upper panel of Figure 10. After the connection setup, the TCP connection state on both machines moves to ESTABLISHED, as shown by the outputs of the first command in the lower panel of Figure 10 and the second command in the lower panel of Figure 9. The applications subsequently exchange some data (“Hello”). To simulate the network abnormality condition of losing the FIN-ACK packet, an iptables command is issued on $H_{1}$ (shown by the second command in the lower panel of Figure 10) at time 06:05:31. Now, the application is aborted on $H_{2}$ by pressing Ctrl-C (upper panel of Figure 9). This results in $H_{2}$ sending a FIN message and moving the TCP connection state to FIN_WAIT1. When $H_{1}$ receives the FIN message, it sends the ACK and moves to CLOSE_WAIT, and the application immediately invokes close(). This sends a FIN message and the TCP connection on $H_{1}$ moves to the LAST_ACK state (Figure 2) as shown by the output of the third command at time 06:05:44 in the lower panel of Figure 10. Since this packet is dropped in the network on account of the firewall rule, $H_{2}$ receives neither this ACK nor the FIN message. Hence, the TCP connection state on $H_{2}$ continues to be FIN_WAIT1, as shown by output of the third command in the lower panel of Figure 9.

Here again, we note that the scenario described above can also occur in a functional network. This time, a problem can arise because many firewalls block outgoing TCP reset messages (since these may be associated with port scanning, where attackers examine ports to determine if any vulnerable applications are running). Specifically, consider a poorly written client application running on $H_{2}$ that crashes while a TCP connection has been established with a server application running on $H_{1}$. Here, the Operating System running on $H_{2}$ will send a FIN message on behalf of the crashed application. The server application will reply with an ACK and move to the LAST_ACK state. Next, when the server application sends pending data or the FIN message, $H_{2}$ will respond with a TCP Reset which may be blocked by either the client-side or server-side firewall. Thus, the server will not receive the TCP Reset and will waste resources (and may suffer degraded performance) as it remains in the LAST_ACK state.


Pages ( 3 of 5 ): « Previous12 3 45Next »

Leave a Comment:

Your email address will not be published. Required fields are marked *