全连接队列大小和半连接队列大小如何设置?
全连接大小:全连接大小取决于 backlog
和
somaxconn
的最小值,也就是
min(backlog, somaxconn)
somaxconn
是 Linux 内核参数,默认 128,可通过/proc/sys/net/core/somaxconn
进行配置backlog
是listen(int sockfd, int backlog)
函数中的参数backlog
半连接队列大小:通过
/proc/sys/net/ipv4/tcp_max_syn_backlog
来设置
如何查看当前全连接队列和半连接队列的大小?
- 查看半连接队列:
1 | netstat -antp | grep SYN_RECV | wc -l |
- 查看全连接队列
1 | ss -lnt | grep 6080 |
-l
显示正在 Listen 的 socket-n
不解析服务名称-t
只显示 tcpRecv-Q
完成三次握手并等待服务端accept()
的 TCP 全连接总数Send-Q
全连接队列大小
如何查看全连接半连接溢出?
netstat -s | grep SYN
如果开启了
tcp_syncookies
,那么当半队列溢出的时候,
95045 SYN cookies sent
这一行会一直变大。
netstat -s | grep overflowed
直接查看全链接队列是否有溢出,数字一直变大就是有溢出。
netstat -s | egrep "listen|LISTEN"
:
1 | 半连接队列溢出次数 |
全连接半连接溢出后如何处理?
全连接队列满
当全连接队列已满就会根据 tcp_abort_on_overflow
策略进行处理。Linux 可通过
/proc/sys/net/ipv4/tcp_abort_on_overflow
进行配置。
tcp_abort_on_overflow=0
,服务端accept
队列满了的时候,客户端发来ack
,服务端直接丢弃该ACK
,此时服务端处于SYN_RCVD
状态,客户端处于ESTABLISHED
状态。在该状态下服务端会重传SYN-ACK
报文。超过tcp_synack_retries
次后,服务端不再重传,后续也不会有任何动作。此时如果客户端再发送数据过来,服务端会返回RST
。tcp_abort_on_overflow=1
,服务端accept
队列满了,客户端发来ack
,服务端直接返回RST
通知 client,表示废掉这个握手过程和这个连接,client 会报connection reset by peer
。
半连接队列满
如果半连接队列满了,并且没有开启
tcp_syncookies
,则会丢弃;
net.ipv4.tcp_syncookies=1
表示开启
tcp_syncookies
。开启后,服务端会生成一个 cookie,通过
SYN+ACK
报文返回给客户端,然后收到客户端下一个 ACK
报文后会校验 cookie,如果是服务端生成的,则直接放入 accept
队列。
开启
tcp_syncookies
可防范 SYN 攻击。
syn flood
Linux 下默认会进行 5 次重发 SYN-ACK 包,总共耗时大概一分钟。由于
SYN-ACK 超时需要 63
秒,那么就给攻击者一个攻击服务器的机会,攻击者在短时间内发送大量的 SYN
包给服务端,用于耗尽服务端的 SYN 队列。为了应对 SYN 攻击的问题,linux
提供了几个 TCP
参数:tcp_syncookies
、tcp_synack_retries
、tcp_max_syn_backlog
、tcp_abort_on_overflow
syn cookie
Linux 实现了一种称为 SYN cookie 的机制,通过
net.ipv4.tcp_syncookies
控制,设置为 1 表示开启。简单说
SYNcookie
就是将连接信息编码在ISN(initialsequencenumber)中返回给客户端,这时服务端不需要将半连接保存在队列中,而是利用客户端随后发送的
ACK 带回的 ISN 还原连接信息,以完成连接的建立,避免了半连接队列被攻击
SYN 包填满。
SYN 半连接队列的大小是由
/proc/sys/net/ipv4/tcp_max_syn_backlog
这个内核参数控制的,有些内核似乎也受 listen 的 backlog
参数影响,取的是两个值的最小值。当这个队列满了,不开启 syncookies
的时候,服务端会丢弃新来的 SYN 包,而客户端在多次重发 SYN
包得不到响应而返回(connection timeout)错误。但是,当服务端开启了
syncookies=1,那么 SYN 半连接队列就没有逻辑上的最大值了,并且
/proc/sys/net/ipv4/tcp_max_syn_backlog
设置的值也会被忽略。