TCP连接的\”三次握手\”及其异常分析
- TCP连接的\”三次握手\”
- TCP连接”三次握手“的异常情况
- 1、客户端第一个【SYN】包丢了
- 2、服务器端收到【SYN】回复,但是回复的【SYN,ACK】包丢了
- 3、客户端收到【SYN,ACK】包,在回复时丢失【ACK】包
- 4、客户端故意不发最后一次【SYN】包
TCP连接的\”三次握手\”
- 开始时,客户端和服务器端都处于CLOSE状态,服务器为了提供服务,会主动监听某个端口,进入LISTEN状态
- 客户端主动发送连接的 【SYN】 包,之后进入SYN-SENT状态,服务端在收到客户端发来的 【SYN】包后,回复 【SYN , ACK】包,之后进入 SYN-RCVD 状态。
- 客户端收到服务端发来的【SYN ,ACK】包后,可以确认对方的的存在,回复 【ACK】包,进入ESTABLISHED状态
- 服务端收到最后一个[ACK]包后,也进入ESTABLISHED状态
正常的三次握手之后,双端都进入ESTABLISHED状态,然后开始传输数据。
TCP连接”三次握手“的异常情况
1、客户端第一个【SYN】包丢了
- 如果在TCP连接中,客户端的第一个【SYN】包丢了,而此时跟服务器端并无联系,所以处理办法在客户端。
- 在TCP协议中,任何一端的【请求——应答】过程中,在一定时间范围内没哟接收到对方的回应的【ACK】包,就会认为是丢包,此时触发超时重传机制。
- 此时会重传【SYN】包,会重传3次,时间间隔分别是: 5.8s、24s、48s,三次时间大约是 76s 左右,而大多数伯克利系统将建立一个新连接的最长时间,限制为 75s。
总结:
客户端第一个【SYN】包丢了:客户端会进行三次重传【SYN】包,总的尝试时间大约在75s左右。
2、服务器端收到【SYN】回复,但是回复的【SYN,ACK】包丢了
- 对于客户端来说,在规定时间内没有接收到来自服务器端的回复,会认为是自己丢包了,会进行重传【SYN】包。
- 对于服务器端来说,发出的【SYN,SCK】迟迟没有客户端的【ACK】回复,会触发重传,此时服务端处于 SYN_RCVD 状态,会依次等待 3s、6s、12s 后,重新发送【SYN,ACK】包;而【SYN,ACK】的重传次数,不同操作系统有不同的配置,例如在 Linux 下可以通过 tcp_synack_retries 进行配置,默认值为 5。如果这个重试次数内,仍未收到【ACK】应答包,那么服务端会自动关闭这个连接。
- 同时由于客户端在没有收到【SYN,ACK】时,也会进行重传,当客户端重传的【SYN】收到后,会立即重新发送【SYN,ACK】包。
总结:
服务器端收到【SYN】回复,但是回复的【SYN,ACK】包丢了:客户端会进行如上的重传;服务器端也会进行重传。
3、客户端收到【SYN,ACK】包,在回复时丢失【ACK】包
- 对于客户端,在发送【ACK】包后进入 ESTABLISHED 状态。多数情况下,客户端进入ESTABLISHED 状态后,认为连接已建立,会立即发送数据。
- 对于服务端,因为没有收到【ACK】会走重传机制,但是服务端因为没有收到最后一个【ACK】包,依然处于 SYN-RCVD 状态。
- 当服务端处于 SYN-RCVD 状态下时,接收到客户端真实发送来的数据包时,会认为连接已建立,并进入ESTABLISHED状态。
原因:
当客户端在 ESTABLISHED 状态下,开始发送数据包时,会携带上一个【ACK】的确认序号,所以哪怕客户端响应的【ACK】包丢了,服务端在收到这个数据包时,能够通过包内 ACK 的确认序号,正常进入 ESTABLISHED 状态。
总结:
客户端收到【SYN,ACK】包,在回复时丢失【ACK】包:客户端会进入 ESTABLISHED状态,向服务器端发送数据;服务器端虽然没有接收到客户端最后发来【ACK】包,但是因为数据包携带ACK的确认序号,所以在接收到数据包时,会认为连接已经建立,变为ESTABLISHED状态。
4、客户端故意不发最后一次【SYN】包
如果客户端是恶意的,在发送【SYN】包后,并收到【SYN,ACK】后就不回复了,那么服务端此时处于一种半连接的状态,虽然服务端会通过 tcp_synack_retries 配置重试的次数,不会无限等待下去,但是这也是有一个时间周期的。
如果短时间内存在大量的这种恶意连接,对服务端来说压力就会很大,这就是所谓的 SYN FLOOD 攻击。
常见的防御 SYN 攻击的方法有如下几种:
- 缩短超时(SYN Timeout)时间
- 增加最大半连接数
- 过滤网关防护
- SYN cookies技术