Hello, I’m Xiao Lin.

A reader asked me this question last night:

If a TCP connection is established, the client breaks down and the server is in the “establish” state. After the client recovers, the server establishes a connection with the server.

As readers of my diagram of networks know, TCP connections are uniquely confirmed by quads.

In this scenario, the CLIENT IP address, server IP address, and destination port do not change. Therefore, the problem depends on whether the source port in the SYN packet sent by the client is the same as the source port connected last time.

1. The port number in the SYN packet on the client is different from that in the historical connection

If the source port number in the SYN packet sent by the client after recovery is different from the source port number of the last connection, the server considers that a new connection needs to be established and establishes a new connection through a three-way handshake.

What happens to the server that was established on the old connection?

If the server sends a packet to the client, the client kernel returns an RST message because the connection to the client has been closed. The server releases the connection after receiving the RST message.

If the server does not send data packets to the client, the TCP keepalive mechanism starts after a period of time. If the client is not alive, the server releases the connection.

2. The port number of the SYN packet on the client is the same as that of the historical connection

If the client recovers and the source port in the SYN packet is the same as the source port in the previous connection, the server in the establish state receives the SYN packet.

What do you think the server will do at this point?

  • Discard SYN packets?
  • Reply to an RST message?
  • Reply to an ACK packet?

At first, WHEN I saw this question, I had no idea, because I had not paid attention to it before, and then this question cannot be guessed, so I read the RFC specification and Linux kernel source code, and finally know the answer.

I’ll cut to the chase.

If a server in the establish state receives a SYN packet from the client, the server replies with an ACK packet containing the correct SEQUENCE number and confirmation number. This ACK is called a Challenge ACK.

Then, the client receives the Challenge ACK and discovers that the serial number is not what it expected. It sends back an RST message, and the server releases the connection when it receives it.

RFC document description

This example is mentioned on page 34 of the RFC793 document.

I also posted the original explanation for you to see.

  • When the SYN arrives at line 3, TCP B, being in a synchronized state,

and the incoming segment outside the window, responds with an acknowledgment indicating what sequence it next expects to hear (ACK 100).

  • TCP A sees that this segment does not acknowledge anything it

sent and, being unsynchronized, sends a reset (RST) because it has detected a half-open connection.

  • TCP B aborts at line 5.
  • TCP A willcontinue to try to establish the connection;

I will not blind translation, meaning the same as I said in Chinese before the explanation.

Source code analysis

When a server in the established state receives a SYN packet from a client, the kernel calls these functions:

tcp_v4_rcv
  -> tcp_v4_do_rcv
    -> tcp_rcv_established
      -> tcp_validate_incoming
        -> tcp_send_ack
Copy the code

Tcp_validate_incoming (); tcp_validate_incoming (); tcp_validate_incoming ();

As can be seen from the above code implementation, the server in the establish state will determine whether the serial number is in the window after receiving the packet. If not, it will check whether the RST flag is set. If so, it will discard it. Then, if there is no RST flag, it determines if there is a SYN flag, and if there is a SYN flag, it jumps to the SYN_challenge tag, and then the tcp_SEND_challenge_ACK function is executed.

In the tcp_send_challenge_ACK function, the tcp_send_ACK function is called to reply to an ACK message with the correct sequence number and confirmation number.

How do I close a TCP connection?

How do I close a TCP connection?

Wouldn’t the first reaction be “Kill the process”?

Yes, this is the roughest way to kill a client process and a server process in different ways:

  • If the client kills a process, the system sends a FIN packet to disconnect all TCP connections established by the client process and the server. In this mode, only the connections established by the client process are affected. Other clients or processes are not affected.
  • In this case, all TCP connections are closed and the server cannot continue to provide access services.

Therefore, it is not desirable to close the process. The best way is to close a SPECIFIC TCP connection.

Some friends may say, why not forge an RST message with the same quplet?

This is a good idea, but do not forget the serial number problem. Can the serial number of your forged RST message be accepted by the other party?

If the SERIAL number of an RST packet does not fall in the sliding window of the peer party, the RST packet will be discarded by the peer party. Therefore, the connection is not closed.

Therefore, to forgery an RST packet that can close a TCP connection, two conditions must be met: “The quad is the same” and “the serial number falls in the sliding window of the other party”.

It is difficult to forge the desired sequence number directly, because if a TCP connection is transmitting data, the sliding window changes all the time, so it is difficult to forge an RST message with the sequence number that falls in the sliding window of the other party.

There is a way to fake a SYN with a quad of the same number to get the “legitimate” sequence number!

As we learned at the beginning, if a server receives a SYN packet with the same quad, it will respond with a Challenge ACK whose acknowledge number is the sequence number that the server wants to receive next. This step is used to get the serial number that the server is expected to receive next time.

The confirmation number is used as the serial number of the RST packet and sent to the server. The server considers the serial number in the RST packet to be valid and releases the connection.

Killcx on Linux is implemented in this way. It proactively sends SYN packets to obtain the SEQ/ACK number, and then forges two RST packets to the client and server using the SEQ/ACK number. In this way, both TCP connections are released. Both active and inactive TCP connections can be killed in this way.

It is also very simple to use, just specify the client IP and port number.

/killcx <IP address >:< port number >Copy the code

The killcx tool works as shown in the following figure.

It forges the client to send a SYN packet. After receiving the PACKET, the server replies with a Challenge ACK with the correct SEQUENCE number and acknowledgement number. Then, it forges two RST packets using the ACK packet information:

  • The RST packet is forged with the Challenge ACK number and sent to the server. After receiving the RST packet, the server releases the connection.
  • The RST packet is forged with the sequence number in the Challenge ACK and sent to the client. After receiving the RST, the client releases the connection.

In this way, a TCP connection is successfully closed!

Here is a picture of using killcx tool to close the connection. You can see the change of serial number and confirmation number.

Therefore, in the future, if a SYN packet appears mysteriously, the other party may want to launch an RST attack on you, and directly disconnect your TCP connection!

How about that? Very clever!