TCP 内核参数
内核的 TCP 参数大部分保存在 /proc/sys/net/ipv4/ 目录,以 tcp 开头。
客户端参数
tcp_syn_retries
SYN 报文重试次数。
SYN 报文就是指的初始的连接报文,属于 TCP 三次握手的第一次。
客户端发送 SYN 报文之后进入 SYN_SEND 状态,该状态下会等待服务端的 SYN + ACK 报文,如果超时则重传。
在 5.4.0 版本的内核中,默认为 6,加上指数退避的影响,一次 SYN 的最长发送时间可以拉长到 1min。
服务端参数
tcp_max_syn_backlog
TCP 的 SYN 队列(半连接队列)的最大长度。
服务端接收到客户端的 SYN 报文之后,会将对端信息保存在半连接队列中,然后回复己方的 SYN + ACK。
调大 backlog 参数来应对 Syn-Flood 攻击基本就是饮鸠止渴,该参数更多的是考虑瞬时的并发连接数
tcp_synack_retries
SYN + ACK 报文重试次数。
对接收到的 SYN 报文,服务端都需要返回 SYN + ACK 报文。
tcp_syncookies
服务端参数。
0 表示永久关闭,1 表示在半连接队列满时启用,2 表示永久启用。
syncookies 是用于阻塞 Syn-Flood 攻击的有效手段,一般情况下,服务端在接受到 SYN 报文之后,会将连接的对端信息保存在半连接队列,并回复 ACK,Syn-Flood 攻击就是使用大量恶意的 SYN 报文打满半连接队列,迫使服务端丢弃正常的 SYN 报文。
syncookies 的原理是不使用半连接队列,而是直接 ISN 等信息记录在 ACK 报文中,在客户端回复的时候抽取 ACK - 1,可以复原初始参数。
syncookies 并没有被纳入 TCP 规范,因为摘要并无法保存完整的管道协商参数,并且有加解密消耗。
somaxconn
表示 accept 队列(全连接队列)的长度。
服务端发送了 SYN + ACK 报文之后,接受到客户端的 ACK 报文,也就是第三次握手的时候,会将对端数据从半连接队列转移到全连接队列,等待 accpet 的系统调用包装为客户端 Socket 的形式。
如果没有其他配置,accept 队列满时会选择丢弃已经建立完成的连接。
全连接队列和半连接队列共同影响了 TCP 在瞬时并发上的性能。
在 5.4.0 的内核中,半连接队列默认长度为 1024,全连接长度默认为 4096。
tcp_abort_on_overflow
表示全连接队列满时的操作逻辑。
0 表示全连接队列满时,服务端会直接丢弃客户端的 ACK。
1 表示队列满时,服务端会回复一个 RST 报文。
RST 报文表示连接重置,是非正常关闭的一种。
RST 报文通常在以下几种情况产生:
- 服务端希望取消连接(就是全连接队列满的情况)
- 服务端并不存在该连接
- 服务端并未监听 SYN 报文请求端口
当 tcp_abort_on_overflow 为 0 时,客户端会以为连接已经建立,如果发送报文到服务端,服务端也会返回 RST。
tcp_fastopen
tcp 的快速打开机制,用于绕过三次握手的延时,但是必须是已经连接过的客户端。
因为安全存疑,所以默认都是关闭的。