天天看点

Protocol(二)[TCP]1.TCP的特性2.TCP通讯时序图3.TCP的三次握手4.TCP 数据通信5.TCP的四次挥手6.TCP的状态转换7.TCP KeepAlive8.SYN攻击

Protocol-TCP

  • 1.TCP的特性
  • 2.TCP通讯时序图
  • 3.TCP的三次握手
    • 1.三次握手
    • 2.目的
    • 3.建立连接(三次握手)的过程
  • 4.TCP 数据通信
    • 1.数据通信过程
    • 2.滑动窗口概念
  • 5.TCP的四次挥手
    • 1.四次挥手
    • 2.关闭连接(四次挥手)的过程
  • 6.TCP的状态转换
    • 1.TCP的状态转换图
    • 2.状态转换详解
  • 7.TCP KeepAlive
  • 8.SYN攻击
    • 1.什么是 SYN 攻击(SYN Flood)
    • 2.如何检测 SYN 攻击
    • 3.如何防御 SYN 攻击

1.TCP的特性

  • TCP 提供一种面向连接的、可靠的字节流服务
  • 在一个 TCP 连接中,仅有两方进行彼此通信,广播和多播不能用于 TCP
  • TCP 使用校验和,确认和重传机制来保证可靠传输
  • TCP 给数据分节进行排序,并使用累积确认保证数据的顺序不变和非重复
  • TCP 使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制

注意

TCP 并不能保证数据一定会被对方接收到,因为这是不可能的。TCP 能够做到的是,如果有可能,就把数据递送到接收方,否则就(通过放弃重传并且中断连接这一手段)通知用户。因此准确说 TCP 也不是 100% 可靠的协议,它所能提供的是数据的可靠递送或故障的可靠通知。

2.TCP通讯时序图

TCP通讯的时序图。TCP连接建立断开。包含三次握手和四次握手。

Protocol(二)[TCP]1.TCP的特性2.TCP通讯时序图3.TCP的三次握手4.TCP 数据通信5.TCP的四次挥手6.TCP的状态转换7.TCP KeepAlive8.SYN攻击

在图中,首先客户端主动发起连接、发送请求,然后服务器端响应请求,然后客户端主动关闭连接。两条竖线表示通讯的两端,从上到下表示时间的先后顺序。

注意:数据从一端传到网络的另一端也需要时间,所以图中的箭头都是斜的。

3.TCP的三次握手

1.三次握手

所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个包。

2.目的

连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换TCP 窗口大小信息。在 socket 编程中,客户端执行 connect() 时,将触发三次握手。

3.建立连接(三次握手)的过程

  • 1.主动建立连接请求端(客户端), 发送 SYN 标志位, 携带 序号

客户端发送一个带SYN标志的TCP报文到服务器。这是TCP通讯时序图中三次握手过程中的段1。客户端发出SYN位表示连接请求。序号是1000,这个序号在网络通讯中用作临时的地址,每发一个数据字节,这个序号要加1,这样在接收端可以根据序号排出数据包的正确顺序,也可以发现丢包的情况。

另外,规定SYN位和FIN位也要占一个序号,这次虽然没发数据,但是由于发了SYN位,因此下次再发送应该用序号1001。

mss表示最大段尺寸,如果一个段太大,封装成帧后超过了链路层的最大长度,就必须在IP层分片,为了避免这种情况,客户端声明自己的最大段尺寸,建议服务器端发来的段不要超过这个长度。

  • 2.被动接受连接请求端(服务器), 接收 SYN 标志,回发 ACK 携带 确认序号, 同时 发送 SYN 标志位, 携带 序号

服务器端回应客户端,是三次握手中的第2个报文段,同时带ACK标志和SYN标志。表示对刚才客户端SYN的回应;同时又发送SYN给客户端,询问客户端是否准备好进行数据通讯。

服务器发出段2,也带有SYN位,同时置ACK位表示确认,确认序号是1001,表示“我接收到序号1000及其以前所有的段,请你下次发送序号为1001的段”,也就是应答了客户端的连接请求,同时也给客户端发出一个连接请求,同时声明最大尺寸为1024。

  • 3.主动建立连接请求端(客户端), 接收 SYN 标志, 回发 ACK 携带 确认序号。 —— 标志 3 次握手完成

客户必须再次回应服务器端一个ACK报文,这是报文段3。

客户端发出段3,对服务器的连接请求进行应答,确认序号是8001。在这个过程中,客户端和服务器分别给对方发了连接请求,也应答了对方的连接请求,其中服务器的请求和应答在一个段中发出。

Protocol(二)[TCP]1.TCP的特性2.TCP通讯时序图3.TCP的三次握手4.TCP 数据通信5.TCP的四次挥手6.TCP的状态转换7.TCP KeepAlive8.SYN攻击

客户端发起连接请求,携带SYN标志位、序号、数据大小【0字节】

服务端响应客户端的连接请求,携带ACK标志位,确认序号【客户端请求序号+1】,同时向客户端发起连接请求,携带SYN标志位、序号、数据大小【0字节】

客户端响应请求,携带ACK标志位,确认序号【服务端请求序号+1】

三次握手完成,对应于socket编程的client的Dial( )函数返回,server端的Accept( )函数返回

因此一共有三个段用于建立连接,称为三次握手。在建立连接的同时,双方协商了一些信息,例如,双方发送序号的初始值、最大段尺寸等。

4.TCP 数据通信

1.数据通信过程

  • 1.客户端发出段4,包含从序号1001开始的20个字节数据

    发送端发送数据同时携带序号。

  • 2.服务器发出段5,确认序号为1021,对序号为1001-1020的数据表示确认收到,同时请求发送序号1021开始的数据,服务器在应答的同时也向客户端发送从序号8001开始的10个字节数据。

    接收端接收数据后需要给发送端发送 ACK 应答以及确认序号 (回执),确保TCP通信模式下,数据可靠的传输。。

  • 3.客户端发出段6,对服务器发来的序号为8001-8010的数据表示确认收到,请求发送序号8011开始的数据。

2.滑动窗口概念

滑动窗口:实时通知对端,本端存储数据的缓冲区大小。

在数据传输过程中,ACK和确认序号是非常重要的,应用程序交给TCP协议发送的数据会暂存在TCP层的发送缓冲区中,发出数据包给对方之后,只有收到对方应答的ACK段才知道该数据包确实发到了对方,可以从发送缓冲区中释放掉了,如果因为网络故障丢失了数据包或者丢失了对方发回的ACK段,经过等待超时后TCP协议自动将发送缓冲区中的数据包重发。

注意

数据传输中的是否丢包,与选择哪一种通信方式无关,和当前的网络环境有关系,所以说选择TCP通信方式进行数据传输一定不会丢包的说法是错误的。

5.TCP的四次挥手

1.四次挥手

TCP 的连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),也叫做改进的三次握手,指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。客户端或服务器均可主动发起挥手动作,在 socket 编程中,任何一方执行 close() 操作即可产生挥手操作。

2.关闭连接(四次挥手)的过程

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

  • 1.客户端发出段7,FIN位表示关闭连接的请求。
  • 2.服务器发出段8,应答客户端的关闭连接请求。
  • 3.服务器发出段9,其中也包含FIN位,向客户端发送关闭连接请求。
  • 4.客户端发出段10,应答服务器的关闭连接请求。

建立连接的过程是三次握手,而关闭连接通常需要4个段,服务器的应答和关闭连接请求通常不合并在一个段中,因为有连接半关闭的情况,这种情况下客户端关闭连接之后就不能再发送数据给服务器了,但是服务器还可以发送数据给客户端,直到服务器也关闭连接为止。

Protocol(二)[TCP]1.TCP的特性2.TCP通讯时序图3.TCP的三次握手4.TCP 数据通信5.TCP的四次挥手6.TCP的状态转换7.TCP KeepAlive8.SYN攻击

6.TCP的状态转换

1.TCP的状态转换图

TCP状态图对排除和定位网络或系统故障时非常有帮助,总共有11中状态。

Protocol(二)[TCP]1.TCP的特性2.TCP通讯时序图3.TCP的三次握手4.TCP 数据通信5.TCP的四次挥手6.TCP的状态转换7.TCP KeepAlive8.SYN攻击

CLOSED:表示初始状态。

LISTEN:该状态表示服务器端的某个SOCKET处于监听状态,可以接受连接。

SYN_SENT:这个状态与SYN_RCVD遥相呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,随即进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。

SYN_RCVD: 该状态表示接收到SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂。此种状态时,当收到客户端的ACK报文后,会进入到ESTABLISHED状态。

ESTABLISHED:表示连接已经建立。

FIN_WAIT_1: FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。区别是:

FIN_WAIT_1状态是当socket在ESTABLISHED状态时,想主动关闭连接,向对方发送了FIN报文,此时该socket进入到FIN_WAIT_1状态。

FIN_WAIT_2状态是当对方回应ACK后,该socket进入到FIN_WAIT_2状态,正常情况下,对方应马上回应ACK报文,所以FIN_WAIT_1状态一般较难见到,而FIN_WAIT_2状态可用netstat看到。

FIN_WAIT_2:主动关闭链接的一方,发出FIN收到ACK以后进入该状态。称之为半连接或半关闭状态。该状态下的socket只能接收数据,不能发。

TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,等2MSL后即可回到CLOSED可用状态。如果FIN_WAIT_1状态下,收到对方同时带 FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。

CLOSING: 这种状态较特殊,属于一种较罕见的状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。

CLOSE_WAIT: 此种状态表示在等待关闭。当对方关闭一个SOCKET后发送FIN报文给自己,系统会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,察看是否还有数据发送给对方,如果没有可以 close这个SOCKET,发送FIN报文给对方,即关闭连接。所以在CLOSE_WAIT状态下,需要关闭连接。

LAST_ACK: 该状态是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,即可以进入到CLOSED可用状态。

2MSL (Maximum Segment Lifetime) 和与之对应的TIME_WAIT状态,可以让4次握手关闭流程更加可靠。4次握手的最后一个ACK是是由主动关闭方发送出去的,若这个ACK丢失,被动关闭方会再次发一个FIN过来。若主动关闭方能够保持一个2MSL的TIME_WAIT状态,则有更大的机会让丢失的ACK被再次发送出去。注意,TIME_WAIT状态一定出现在主动关闭这一方。

2.状态转换详解

Protocol(二)[TCP]1.TCP的特性2.TCP通讯时序图3.TCP的三次握手4.TCP 数据通信5.TCP的四次挥手6.TCP的状态转换7.TCP KeepAlive8.SYN攻击

TCP 状态转换图:

主动连接端(客户端):

CLOSED --> 发送 SYN --> SYN_SENT --> 接收 ACK、SYN,发送 ACK --> ESTABLISHED --> 数据通信

主动关闭端(客户端):

ESTABLISHED --> 发送 FIN --> FIN_WAIT_1 --> 接收 ACK --> FIN_WAIT_2 (半关闭) --> 接收FIN,发送 ACK --> TIME_WAIT --> 等待 2MSL 时长 --> CLOSED

—— FIN_WAIT_2、TIME_WAIT、2MSL 只出现 主动端。

被动连接端(服务器):

CLOSED --> LISTEN --> 接收SYN, 发送 ACK, SYN --> SYN_RCVD --> 接收 ACK–>>ESTABLISHED --> 数据通信

被动关闭端(服务器):

ESTABLISHED --> 接收 FIN, 发送ACK --> CLOSE_WAIT (对应主动端的 FIN_WAIT_2) --> 发送 FIN --> LAST_ACK --> 接收 ACK --> CLOSED

7.TCP KeepAlive

TCP 的连接,实际上是一种纯软件层面的概念,在物理层面并没有“连接”这种概念。TCP 通信双方建立交互的连接,但是并不是一直存在数据交互,有些连接会在数据交互完毕后,主动释放连接,而有些不会。在长时间无数据交互的时间段内,交互双方都有可能出现掉电、死机、异常重启等各种意外,当这些意外发生之后,这些 TCP 连接并未来得及正常释放,在软件层面上,连接的另一方并不知道对端的情况,它会一直维护这个连接,长时间的积累会导致非常多的半打开连接,造成端系统资源的消耗和浪费,为了解决这个问题,在传输层可以利用 TCP 的 KeepAlive 机制实现来实现。主流的操作系统基本都在内核里支持了这个特性。

TCP KeepAlive 的基本原理是,隔一段时间给连接对端发送一个探测包,如果收到对方回应的ACK,则认为连接还是存活的,在超过一定重试次数之后还是没有收到对方的回应,则丢弃该 TCP连接。

TCP KeepAlive 的局限。首先 TCP KeepAlive 监测的方式是发送一个 probe包,会给网络带来额外的流量,另外 TCP KeepAlive 只能在内核层级监测连接的存活与否,而连接的存活不一定代表服务的可用。例如当一个服务器 CPU 进程服务器占用达到 100%,已经卡死不能响应请求了,此时 TCP KeepAlive 依然会认为连接是存活的。因此 TCP KeepAlive 对于应用层程序的价值是相对较小的。需要做连接保活的应用层程序,例如 QQ,往往会在应用层实现自己的心跳功能。

8.SYN攻击

1.什么是 SYN 攻击(SYN Flood)

在三次握手过程中,服务器发送 SYN-ACK 之后,收到客户端的 ACK 之前的 TCP 连接称为半连接(half-open connect)。此时服务器处于 SYN_RCVD 状态。当收到 ACK 后,服务器才能转入ESTABLISHED 状态.

SYN 攻击指的是,攻击客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送SYN包,服务器回复确认包,并等待客户的确认。由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,导致目标系统运行缓慢,严重者会引起网络堵塞甚至系统瘫痪。

SYN 攻击是一种典型的 DoS/DDoS 攻击。

2.如何检测 SYN 攻击

检测 SYN 攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击。在 Linux/Unix 上可以使用系统自带的 netstats命令来检测 SYN 攻击。

3.如何防御 SYN 攻击

SYN攻击不能完全被阻止,除非将TCP协议重新设计。我们所做的是尽可能的减轻SYN攻击的危害,常见的防御 SYN 攻击的方法有如下几种:

  • 1.缩短超时(SYN Timeout)时间
  • 2.增加最大半连接数
  • 3.过滤网关防护
  • 4.SYN cookies技术