TCP/IP之三次握手

2,127 阅读4分钟

TCP 通信过程

查看 tcp 的网络连接情况

netstat -anp |grep tcp

具体三次握手

关于三次握手的优化

TCP Fast Open

TCP快速打开(TCP Fast Open,TFO)是对TCP的一种简化握手手续的拓展,用于提高两端点间连接的打开速度。简而言之,就是在TCP的三次握手过程中传输实际有用的数据

三次握手的过程中,当用户首次访问server时,发送syn包,server根据用户IP生成cookie,并与syn+ack一同发回client;client再次访问server时,在syn包携带TCP cookie;如果server校验合法,则在用户回复ack前就可以直接发送数据;否则按照正常三次握手进行。

TFO提高性能的关键是省去了热请求的三次握手,这在充斥着小对象的移动应用场景中能够极大提升性能。

开启 tcp_fastopen

sysctl -w net.ipv4.tcp_fastopen=1

其中数字包含含义如下:
0: 关闭
1: 作为客户端时使用 TFO
2: 作为服务端时使用 TFO
3. 全部使用TFO

因需要相关代码支持开启 TCP_FASTOPEN 选项, 所以无法正常抓nginx请求包, 此图来源于网络.

从上面的示例中可以看到 TFO 的其中一个优点就是可以提高网络的利用率,尤其是有频繁网络建立的情景,TFO 的优势尤其明显。但是,除此之外,TFO 还有一个很大的优点就是可以防止 SYN泛洪攻击。

Message Flow:

 Requesting Fast Open Cookie in connection 1:

   TCP A (Client)                                      TCP B (Server)
   ______________                                      ______________
   CLOSED                                                      LISTEN

   #1 SYN-SENT       ----- <SYN,CookieOpt=NIL>  ---------->  SYN-RCVD

   #2 ESTABLISHED    <---- <SYN,ACK,CookieOpt=C> ----------  SYN-RCVD
   (caches cookie C)

   Performing TCP Fast Open in connection 2:

   TCP A (Client)                                      TCP B (Server)
   ______________                                      ______________
   CLOSED                                                      LISTEN

   #1 SYN-SENT       ----- <SYN=x,CookieOpt=C,DATA_A> ---->  SYN-RCVD

   #2 ESTABLISHED    <---- <SYN=y,ACK=x+len(DATA_A)+1> ----  SYN-RCVD

   #3 ESTABLISHED    <---- <ACK=x+len(DATA_A)+1,DATA_B>----  SYN-RCVD

   #4 ESTABLISHED    ----- <ACK=y+1>--------------------> ESTABLISHED

   #5 ESTABLISHED    --- <ACK=y+len(DATA_B)+1>----------> ESTABLISHED

安全问题之如何应对 SYN 泛洪攻击

TCP SYN泛洪发生在OSI第四层,这种方式利用TCP协议的特性,就是三次握手。攻击者发送TCP SYN,SYN是TCP三次握手中的第一个数据包,而当服务器返回ACK后,该攻击者就不对其进行再确认,那这个TCP连接就处于挂起状态,也就是所谓的半连接状态,服务器收不到再确认的话,还会重复发送ACK给攻击者。这样更加会浪费服务器的资源。攻击者就对服务器发送非常大量的这种TCP连接,由于每一个都没法完成三次握手,所以在服务器上,这些TCP连接会因为挂起状态而消耗CPU和内存,最后服务器可能死机,就无法为正常用户提供服务了。(来源:百度百科)

通过上图流程, 我们发现在 SYN 中间其实是维护了一个队列, SYN 攻击就是短时间内伪造不同 IP 地址的 SYN 报文, 快速占满 backlog 队列, 使服务不能提供正常服务.

我们观察图中, 在 server 端维护着两个队列, 分别是 syns queue 和 accept queue, 这两个队列的大小可以使用 tcp_max_syn_backlog 和 somaxconn 两个内核配置.

tcp_max_syn_backlog 是指定所能接受SYN同步包的最大客户端数量,即半连接上限
somaxconn 是指服务端所能accept即处理数据的最大客户端数量,即完成连接上限

其中还有两个内核参数我们经常接触:

tcp_abort_on_overflow

当 tcp 建立连接的 3 路握手完成后,将连接置入 ESTABLISHED 状态并交付给应用程序的 backlog 队列时,会检查 backlog 队列是否已满。若已满,通常行为是将连接还原至 SYN_ACK 状态,以造成 3 路握手最后的 ACK 包意外丢失假象 —— 这样在客户端等待超时后可重发 ACK —— 以再次尝试进入 ESTABLISHED 状态 —— 作为一种修复/重试机制。如果启用 tcp_abort_on_overflow 则在检查到 backlog 队列已满时,直接发 RST 包给客户端终止此连接 —— 此时客户端程序会收到 104 Connection reset by peer 错误。

tcp_syncookies

在 tcp 建立连接的 3 次握手过程中,当服务端收到最初的 SYN 请求时,会检查应用程序的 syn_backlog 队列是否已满。若已满,通常行为是丢弃此 SYN 包。若未满,会再检查应用程序的 backlog 队列是否已满。若已满并且系统根据历史记录判断该应用程序不会较快消耗连接时,则丢弃此 SYN 包。如果启用 tcp_syncookies 则在检查到 syn_backlog 队列已满时,不丢弃该 SYN 包,而改用 syncookie 技术进行 3 次握手。 (当队列未满时, 不会使用此方式).

参考文档

文中部分图片和知识来源于网络.

部分 TCP 内核参数彻底了解(blog.csdn.net/rain_qingti…)

更多精彩内容关注公众号 (呆呆熊的技术路) :