建连接时SYN超时问题
如果 server 端因为某种情况没有收到 client 回来的 ACK,那么,这个连接处还处于一个未建立的状态。于是,server端如果在一定时间内没有收到,则 server 端的 TCP 会重发 SYN_ACK。
在Linux下,默认重试次数为5次,重试的间隔时间从1s开始每次都翻倍,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s,总共31s,第5次发出后还要等32s都知道第5次也超时了。如果第五次重传之后,还未收到客户端的 ACK,server 端的 TCP 才会把断开这个连接。
关于SYN Flood攻击
攻击者短时间伪造不同 IP 地址的 SYN 报文,服务端每接收到一个 SYN 报文,就进入SYN_RCVD 状态,但服务端发送出去的 ACK + SYN 报文,无法得到未知 IP 主机的 ACK 应答,久而久之就会占满服务端的 SYN 接收队列(未连接队列),使得服务器不能为正常用户服务。
避免方式
设置 tcp_syncookies = 1。当 SYN 队列满了后,TCP 会通过源地址端口、目标地址端口和时间戳打造出一个特别的 Sequence Number 发回去(又叫cookie)。
如果是攻击者则不会有响应,如果是正常连接,则会把这个 SYN Cookie 发回来,然后服务端可以通过 cookie 建连接。
设置 netdev_max_backlog 的值,确定链接队列的大小。当网卡接收数据包的速度大于内核处理的速度时,会有一个队列保存这些数据包。
通过设置 netdev_max_backlog 的值,确定 SYN_RCVD 状态连接的最大个数。
通过设置 tcp_abort_on_overflow 的值。当超出处理能时,对新的 SYN 直接回报 RST,丢弃连接。
断开连接中的异常
TIME_WAIT数量太多
从上面的描述可以知道,TIME_WAIT 是个很重要的状态,但是如果在大并发的短链接下,TIME_WAIT 就会太多。TIME_WAIT过多会占用大量的内存资源和端口资源。
优化法一:tcp_tw_reuse
设置tcp_tw_reuse = 1,则可以复用处于 TIME_WAIT 的 socket 为新的连接所用。
有一点需要注意的是,tcp_tw_reuse 功能只能用客户端(连接发起方),因为开启了该功能,在调用 connect() 函数时,内核会随机找一个 time_wait 状态超过 1 秒的连接给新的连接复用。
使用 tcp_timestamps = 1 选项,还有一个前提,需要打开对 TCP 时间戳的支持,即这个时间戳的字段是在 TCP 头部的「选项」里,用于记录 TCP 发送方的当前时间戳和从对端接收到的最新时间戳。
由于引入了时间戳,我们在前面提到的 2MSL 问题就不复存在了,因为重复的数据包会因为时间戳过期被自然丢弃。
优化法二:tcp_max_tw_buckets
这个值默认为 18000,当系统中处于 TIME_WAIT 的连接一旦超过这个值时,系统就会将后面的 TIME_WAIT 连接状态重置。
这个方法过于暴力,而且治标不治本,带来的问题远比解决的问题多,不推荐使用。
全部0条评论
快来发表一下你的评论吧 !