好久没更新博客了,水一篇以前的笔记 ping 一下探活 =w=
三次握手
三次握手的流程
- [C --> S] SYN=X
- [C <-- S] SYN=Y; ACK=X+1
- [C --> S] SEQ=X+1; ACK=Y+1 (此时已经可以携带数据了)
- [C --> S] SEQ=X+1; ACK=Y+1 (如果上一个包没携带数据,则为第一个数据包)
为什么第三个握手包与第一个数据包的序列号一致?
因为……
- ACK 不占用序列号;
- SYN 占用一个序列号;
为什么是三次?
我的理解,有两个理由:
理由一:防止历史数据包造成的混乱
收到第二个包之后,由于客户端 SYN 包序列号的随机性,客户端可以确认服务器此时确实在响应当前请求而非历史请求;
收到第三个包之后,由于服务端 SYN 包序列号的随机性,服务器可以确认客户端此时确实在响应当前请求而非历史请求;
理由二:双方需要各自确认两方的收发能力均正常
跟踪一下三个包的过程中对收发能力的确认状态:
序号 | C确认C的发送能力 | C确认C的接收能力 | C确认S的发送能力 | C确认S的接收能力 | S确认S的发送能力 | S确认S的接收能力 | S确认C的发送能力 | S确认C的接收能力 |
---|---|---|---|---|---|---|---|---|
第一次握手结束 | Y | |||||||
第二次握手结束 | Y | Y | Y | Y | Y | |||
第三次握手结束 | Y | Y | Y | Y | Y | Y | Y | Y |
SYN 泛洪攻击
SYN 泛洪攻击是什么?
在三次握手过程中,服务器发送第二个握手包之后的连接是一种「半连接」。如果客户端在短时间内发送大量的 SYN
握手包,服务器将需要维护大量的半连接(及其所占用的资源),而且需要不断重发第二个握手包,直至超时。
如何识别 SYN 泛洪攻击?
netstat
命令可以看到大量的 SYN_RCVD
连接。
如何防御这种攻击
- 增加半连接池的大小
- 缩短超时时间
- SYN Cookies
- 在第二个握手包的序列号中隐藏信息。服务器在收到第三个握手包之后,校验序列号有效后才为连接分配资源。
四次挥手
四次挥手的流程
- [C --> S] FIN=X
- [C <-- S] ACK=X+1
- [C <-- S] FIN=Y
- [C --> S] ACK=Y+1
前两次挥手与后两次挥手是对称且独立的,因此有半关闭连接的概念。
TCP 报文段结构
TCP 头部的典型长度为 20 Bytes(一般用 4 Bytes 宽度的表格来表示时,刚好是五行)。
其他小细节
- 序列号是构建在字节流之上的,而非报文段
- 确认号是期望收到的下一字节的序号(所以会+1)
- SYN、FIN 包均占用一个序列号,ACK 包不占用序列号
- 64240 是一个常见的窗口大小,因为它是 65536 以内 MSS 的最大整数倍(44 个 MSS 典型值 1460)
题图来自 Uriel SC Unsplash