When time_ TCP in wait status waves normally. After receiving SYN

Absrtact: let's discuss this problem today. In the normal waving process of TCP, it is at time_ What happens when a connection in wait state receives a SYN of the same Quad?

This article is shared from Huawei cloud community< At time_ What happens to TCP connections in wait state after receiving SYN? >, author: Kobayashi coding.

At the weekend, I discussed some TCP problems with my friends. When I looked up the book "high performance programming for Linux server", I found that the book wrote the following sentence:

The book says that in time_ The connection in wait status will return RST message after receiving the SYN of the same quadruple, and the other party will disconnect after receiving it.

In the book, the author just mentioned that there is no evidence of source code or packet capture.

At first, when I saw the source code of TCP, I found that it was not common sense.

So today, let's talk about this question, "what happens when a connection in TIME_WAIT state receives a SYN of the same Quad in the normal waving process of TCP?"

The problem phenomenon is shown in the following figure. The server is on the left and the client is on the right:

Let's start with the conclusion

Before analyzing the TCP source code with you, let me draw a conclusion directly.

To solve this problem, the key is to see whether the "serial number and timestamp" of SYN is legal, because it is in time_ After the connection in wait state receives syn, it will judge whether the "serial number and timestamp" of SYN is legal, and then do different processing according to the judgment results.

First, let me explain to you what is a "legal" SYN?

  • Legal syn: the "serial number" of the syn of the client is larger than the "expected next received serial number" of the server, and the "timestamp" of the SYN is larger than the "timestamp of the last received message" of the server.
  • Illegal syn: the "serial number" of the syn of the client is smaller than the "expected next received serial number" of the server, or the "timestamp" of the SYN is smaller than the "timestamp of the last received message" of the server.

The above SYN legal judgment is based on the scenario that both parties have enabled the TCP timestamp mechanism. If both parties have not enabled the TCP timestamp mechanism, the SYN legal judgment is as follows:

  • Legal SYN: the "serial number" of the SYN of the client is larger than the "expected next received serial number" of the server.
  • Illegal SYN: the "serial number" of the SYN of the client is smaller than the "expected next received serial number" of the server.

Legal SYN received

If at time_ After a connection in wait state receives a "legal SYN", it will reuse the quad connection, skip 2MSL and change to SYN_RECV status, and then the connection establishment process can be carried out.

Take the following figure as an example. Both parties have enabled the TCP timestamp mechanism. TSval is the timestamp when sending messages:

In the figure above, when receiving the FIN message waving for the third time, TSval (21) of the message will be recorded, using ts_ The recent variable is saved. Then the accountant calculates the next expected serial number. In this example, the next expected serial number is 301, using rcv_nxt variable save.

At time_ After the connection in wait state receives syn, the seq (400) of SYN is greater than rcv_nxt (301), and TSval (30) of SYN is greater than ts_recent (21), so it is a "legal syn", so it will reuse this quad connection and skip 2MSL to SYN_RECV status, and then the connection establishment process can be carried out.

Illegal SYN received

If at time_ After receiving the "illegal SYN", the connection in the wait state will reply to an ACK message waved for the fourth time. After receiving it, the client finds that it does not expect to receive the acknowledgement number (acknum), and then returns the RST message to the server.

Using the following figure as an example, both parties have enabled the TCP timestamp mechanism. TSval is the timestamp when sending messages:

In the figure above, when receiving the FIN message waving for the third time, TSval (21) of the message will be recorded, using ts_ The recent variable is saved. Then the accountant calculates the next expected serial number. In this example, the next expected serial number is 301, using rcv_nxt variable save.

At time_ After the connection in wait state receives syn, the seq (200) of SYN is less than rcv_nxt (301), so it is an "illegal syn", and it will reply to the same ACK message as the fourth wave. After receiving it, the client finds that it does not expect to receive the confirmation number, and then returns the RST message to the server.

After the client waits for a period of time and still does not receive SYN+ACK, it will timeout and retransmit SYN message. After the retransmission times reach the maximum, it will disconnect.

PS: let's bury a question here. It's at time_ Will the connection in wait state be disconnected after receiving RST?

Source code analysis

The following source code analysis is based on Linux 4 Kernel code version 2.

After receiving the TCP message, the Linux kernel will execute tcp_v4_rcv function, in which and time_ The main codes related to wait status are as follows:

inttcp_v4_rcv(structsk_buff*skb)
{
structsock*sk;
...
//After receiving the message, this function will be called to find the corresponding sock
sk=__inet_lookup_skb(&tcp_hashinfo,skb,__tcp_hdrlen(th),th->source,
th->dest,sdif,&refcounted);
if(!sk)
gotono_tcp_socket;

process:
//If the status of the connection is time_wait, it will jump to do_time_wait
if(sk->sk_state==TCP_TIME_WAIT)
gotodo_time_wait;

...

do_time_wait:
...
//By TCP_ timewait_ state_ The process function handles at time_ Message received in wait status
switch(tcp_timewait_state_process(inet_twsk(sk),skb,th)){
//If TCP_TW_SYN, then allow this SYN to reestablish the connection
//That is, Tim is allowed_ Wait state transitions to SYN_RECV
caseTCP_TW_SYN:{
structsock*sk2=inet_lookup_listener(....);
if(sk2){
....
gotoprocess;
}
}
//If TCP_TW_ACK, then, return to the ACK in memory
caseTCP_TW_ACK:
tcp_v4_timewait_ack(sk,skb);
break;
//If TCP_TW_RST sends RESET packet directly
caseTCP_TW_RST:
tcp_v4_send_reset(sk,skb);
inet_twsk_deschedule_put(inet_twsk(sk));
gotodiscard_it;
//If TCP_TW_SUCCESS directly discards the packet and makes no response
caseTCP_TW_SUCCESS:;
}
gotodiscard_it;
}

The process of this Code:

  1. After receiving the message, it will call__ inet_lookup_skb() function to find the corresponding sock structure;
  2. If the status of the connection is TIME_WAIT, jump to do_time_wait processing;
  3. By tcp_timewait_state_process() function to process the received message, and then do corresponding processing according to the return value.

Let me tell you first. If the SYN received is legal, TCP_ timewait_ state_ The process () function returns TCP_TW_SYN, and then reuse this connection. If the SYN received is illegal, TCP_ timewait_ state_ The process () function returns TCP_TW_ACK, and then the last ack will be returned.

Next, look at TCP_ timewait_ state_ How does the process () function judge the SYN package.

enumtcp_tw_status
tcp_timewait_state_process(structinet_timewait_sock*tw,structsk_buff*skb,
conststructtcphdr*th)
{
...
//paws_reject is false, indicating that no timestamp wrap occurs
//paws_reject is true, indicating that a timestamp wrap has occurred
boolpaws_reject=false;

tmp_opt.saw_tstamp=0;
//There is an option in the TCP header and the old connection has the timestamp option enabled
if(th->doff>(sizeof(*th)>>2)&&tcptw->tw_ts_recent_stamp){
//Parsing options
tcp_parse_options(twsk_net(tw),skb,&tmp_opt,0,NULL);

if(tmp_opt.saw_tstamp){
...
//Check whether the timestamp of the received message has time stamp wrapping
paws_reject=tcp_paws_reject(&tmp_opt,th->rst);
}
}

....

//SYN packet, no RST, no ACK, no time stamp wrap, and no serial number wrap,
if(th->syn&&!th->rst&&!th->ack&&!paws_reject&&
(after(TCP_SKB_CB(skb)->seq,tcptw->tw_rcv_nxt)||
(tmp_opt.saw_tstamp&&//The new connection has a timestamp enabled
(s32)(tcptw->tw_ts_recent-tmp_opt.rcv_tsval)<0))){//The timestamp does not wrap around
//Initialization serial number
u32isn=tcptw->tw_snd_nxt+65535+2;
if(isn==0)
isn++;
TCP_SKB_CB(skb)->tcp_tw_isn=isn;
returnTCP_TW_SYN;//Allow reuse of TIME_WAIT Quad reconnects
}
if(!th->rst){
//If the timestamp wraps around or the message contains ack, the duration of TIMEWAIT status will be extended again
if(paws_reject||th->ack)
inet_twsk_schedule(tw,&tcp_death_row,TCP_TIMEWAIT_LEN,
TCP_TIMEWAIT_LEN);

//Return TCP_TW_ACK, send the last ACK
returnTCP_TW_ACK;
}
inet_twsk_put(tw);
returnTCP_TW_SUCCESS;
}

If both parties enable the TCP timestamp mechanism, they will pass tcp_paws_reject() function to judge whether the timestamp has been rewound, that is, whether the "timestamp of the currently received message" is greater than the "timestamp of the last received message":

  • If it is greater than, it indicates that there is no timestamp detour, and the function returns false.
  • If it is less than, it indicates that a timestamp wrap has occurred, and the function returns true.

It can be seen from the source code that after receiving the syn package, if the timestamp of the syn package does not wrap around, that is, the timestamp is incremented, and the serial number of the syn package does not wrap around, that is, the serial number of the SYN is "greater than" the next expected serial number. It initializes a serial number and returns TCP_TW_SYN, and then reuse the connection, that is, skip 2MSL and convert to SYN_RECV status, and then the connection establishment process can be carried out.

If both parties do not enable the TCP timestamp mechanism, they only need to judge whether the sequence number of syn packet is wrapped. If the sequence number of SYN is greater than the next expected sequence number, they can skip 2MSL and reuse the connection.

If the SYN packet is illegal, TCP is returned_ TW_ ACK, and then send the same ack as the last time to the other party.

At TIME_WAIT status, will you disconnect after receiving RST?

I left a question before. It's time_ Will the connection in wait state be disconnected after receiving RST?

Whether it will be disconnected depends on net ipv4. tcp_ Rfc1337 kernel parameter (0 by default):

  • If this parameter is set to 0, the received RST message will end time in advance_ Wait state, release the connection.
  • If this parameter is set to 1, the RST message will be lost.

The source code processing is as follows:

enumtcp_tw_status
tcp_timewait_state_process(structinet_timewait_sock*tw,structsk_buff*skb,
conststructtcphdr*th)
{
....
//The timestamp of rst message is not rewound
if(!paws_reject&&
(TCP_SKB_CB(skb)->seq==tcptw->tw_rcv_nxt&&
(TCP_SKB_CB(skb)->seq==TCP_SKB_CB(skb)->end_seq||th->rst))){

//Processing rst message
if(th->rst){
//If this option is not enabled, tw will be recycled immediately when RST is received, but it is risky to do so
if(twsk_net(tw)->ipv4.sysctl_tcp_rfc1337==0){
kill:
//Delete the tw timer and release tw
inet_twsk_deschedule_put(tw);
returnTCP_TW_SUCCESS;
}
}else{
//Extend the duration of TIMEWAIT status again
inet_twsk_reschedule(tw,TCP_TIMEWAIT_LEN);
}

...
returnTCP_TW_SUCCESS;
}
}

TIME_ The wait state releases the connection after receiving the RST message, which is equivalent to skipping the 2MSL time. This is still risky.

sysctl_ tcp_ The parameter rfc1337 is proposed in the rfc1337 document in order to avoid time_ In the wait status, the time of skipping 2MSL after receiving RST message is also given in the document. What potential problems will there be in skipping 2MSL time.

TIME_ The reason why the wait state lasts 2MSL is mainly for two purposes:

  • Prevent the data in the historical connection from being received incorrectly by the connection of the same Quad;
  • Ensure that the "passive closing connection" party can be closed correctly;

Why design time in detail_ Wait status, I have a detailed description in this article: If time_ What's the problem if the wait state lasts too short or not?

Although time_ The wait state lasts a little long and seems unfriendly, but it is designed to avoid chaos.

"UNIX network programming" says: TIME_WAIT is our friend. It helps us. Don't try to avoid this state, but find out it.

So, I personally think it will be net ipv4. tcp_ Setting rfc1337 to 1 is safer.

summary

In the normal waving process of TCP, it is at time_ What happens when a connection in wait state receives a SYN of the same Quad?

If both parties have enabled the timestamp mechanism:

  • If the "serial number" of the syn of the client is larger than the "expected next received serial number" of the server, and the "timestamp" of the SYN is larger than the "timestamp of the last received message" of the server. Then the quad connection will be reused, and 2MSL will be skipped to SYN_RECV status, and then the connection establishment process can be carried out.
  • If the "serial number" of the syn of the client is smaller than the "expected next received serial number" of the server, or the "timestamp" of the SYN is smaller than the "timestamp of the last received message" of the server. Then it will reply to an ACK message waved for the fourth time. After receiving it, the client finds that it does not expect to receive the confirmation number, and then returns the RST message to the server.

At TIME_WAIT status, will you disconnect after receiving RST?

  • If net ipv4. tcp_ If the rfc1337 parameter is 0, the time will end in advance_ Wait state, release the connection.
  • If net ipv4. tcp_ If the rfc1337 parameter is 1, the RST message will be lost.

 

Click follow to learn about Huawei's new cloud technology for the first time~

Keywords: Linux

Added by digitalmustache on Thu, 03 Mar 2022 10:10:18 +0200