Tcp’s Semi-connected and Full-connected Queues

  network

Queue and Parameters

图片描述

The server-side semi-connection queue (syn queue)

In the three-way handshake protocol, the server maintains a semi-connection queue, which creates an entry for each client’s SYN packet (the server has already created the request_sock structure when it receives the SYN packet and stored it in the semi-connection queue). The entry indicates that the server has received the SYN packet, sends an acknowledgement to the client, and is waiting for the client’s acknowledgement packet (the packet that will send SYN+ACK for the second handshake will be acknowledged). The connection identified by these entries is in Syn_RECV state on the server. When the server receives the confirmation package from the customer, it deletes the entry and the server enters ESTABLISHED state.
The queue is a SYN queue with a length of max (64,/proc/sys/net/IPv4/tcp_max_syn_backlog) and is configured under the TCP _ max _ syn _ backlog value of the machine in/proc/sys/net/IPv4/TCP _ max _ syn _ backlog.

The server-side full connection queue (accpet queue)

When the first three-way handshake, when the server receives the ACK, it will enter a new queue called accept. The length of the queue is min(backlog, somaxconn). By default, somaxconn has a value of 128, indicating that there are 129 ESTAB connections waiting for accept (), The value of the backlog should be specified by the second parameter in intlisten (intsockfd, intbacklog). the backlog in list can be defined by our application.

When Client hangs up after sending SYN packet (Syn flood attack)

The Client hung up after sending the SYN packet to the Server. The SYN-ACK returned by the Server to the Client has not received the ACK confirmation from the Client. At this time, the connection has not been established and cannot be counted as a failure. This requires a timeout period for the Server to disconnect the connection, otherwise the connection will occupy a position in the Server’s SYN connection queue all the time, and a large number of such connections will exhaust the Server’s SYN connection queue, making normal connections unable to be processed.

At present, Linux will retransmit SYN-ACK packets five times by default. The retry interval starts from 1s. The next retry interval is twice as long as the previous one. The retry interval for the five times is 1s, 2s, 4s, 8s, 16s, 31s in total. After the fifth transmission, it will take 32s to know that the fifth time has expired. Therefore, TCP will disconnect this connection only after 1s+2s+4s+ 8s+ 16s+32s = 63s in total. Because the SYN timeout takes 63 seconds, the attacker is given an opportunity to attack the Server. The attacker sends a large number of SYN packets to the Server (commonly known as SYN flood attack) in a short time to deplete the server’s SYN queue. To deal with the problem of too many SYNs, linux provides several TCP parameters: tcp_syncookies, tcp_synack_retries, tcp_max_syn_backlog, tcp_abort_on_overflow to adjust the response.

Net.ipv4.tcp_synack_retries # number of SYN+ACK packets sent before the kernel abandoned the connection
Net.ipv4.tcp_SYN_retries # number of syn packets sent before the kernel abandons establishing a connection

In order to cope with SYNflooding (that is, the client only sends SYN packets to initiate handshaking and does not respond to ACK to complete connection establishment, filling up the semi-connection queue on the server side so that it cannot handle normal handshaking requests), Linux has implemented a mechanism called SYNcookie, which is controlled by net.ipv4.tcp_syncookies and set to 1 to indicate opening. Simply speaking, SYNcookie is to encode the connection information in ISN(initialsequencenumber) and return it to the client. At this time, the server does not need to save the semi-connection in the queue, but restores the connection information by using ISN brought back by ACK sent by the client, so as to complete the connection establishment and prevent the semi-connection queue from being filled with SYN packets.

When the syn queue is full (tcp_abort_on_overflow)

The size of SYN semi-connection queue is controlled by the kernel parameter (/proc/sys/net/IPv4/TCP _ max _ syn _ backlog). Some kernels also seem to be affected by listen’s backlog parameter, which is the minimum of two values. When the queue is full and syncookies are not opened, the Server discards the new SYN packet, and the Client side returns (connection time out) Error. However, when syncookies=1 is turned on on the Server side, the SYN semi-connection queue will have no logical maximum, and the value set by/proc/sys/net/IPv4/TCP _ max _ SYN _ backlog will also be ignored.

The Client side did not respond to multiple retransmissions of SYN packets and returned.connection time outError

examine

netstat -s | grep LISTEN
4375 SYNs to LISTEN sockets dropped

When the accept queue is full

When the accept queue is full, even if the client continues to send ACK packets to the server, it will not be responded to. At this time, ListenOverflows+1, and the server decides how to return through/proc/sys/net/IPv4/TCP _ abort _ on _ overflow. 0 means to directly discard the ACK, and 1 means to send RST notification to the client. Correspondingly, client will return separatelyread timeoutOr ..connection reset by peer.

Client returns separatelyread timeoutOr ..connection reset by peer

examine

root@b5dbe93bcb04:/opt# netstat -s | grep listen
22438 times the listen queue of a socket overflowed

Accept queue is full, which also affects syn queue. In code net/ipv4/tcp_ipv4.c:

int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
{
    /*tcp_syncookies为2 进行syn cookie
      tcp_syncookies为1 且request队列满了 进行syn cookie处理
      tcp_syncookies为0 且request队列满了 将该syn报文drop掉
    */
    if ((sysctl_tcp_syncookies == 2 ||
         inet_csk_reqsk_queue_is_full(sk)) && !isn) {
        want_cookie = tcp_syn_flood_action(sk, skb, "TCP");
        if (!want_cookie)
            goto drop;
    }

    /* Accept backlog is full. If we have already queued enough
     * of warm entries in syn queue, drop request. 
     */
    if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) {
        NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
        goto drop;
}

The accept queue is small in most cases, so the SYN queue is not full and the ACCEPT queue is full. In this case, tcp_aborton_overflow will be used to decide whether to discard directly or return to reject RST. However, if syncookies are enabled, syncookies will be turned on, limiting the speed of SYN packets entering.

When the system discards the last ACK and there is still a net.ipv4.tcp_synack_retries setting in the system, Linux will resend the SYN ACK packet. However, when the client receives multiple SYN ACK packets, it will consider the previous ACK packet lost. Therefore, the client is prompted to send ACK again and finally complete the connection when the accept queue is free. If the accept queue is always full, the final client receives the RST packet.

doc