TCP/UDP
TCP
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP 头部结构
TCP头部字段 | 描述 |
---|---|
源端口 | 发送方的端口号,范围(0~65535) |
目标端口 | 接收方的端口号,范围(0~65535) |
序列号 | 如果TCP数据过大(大于IP数据包的允许程度),则需要进行分段。这个序列号记录每个数据包的序列号,使接收端可以重新组合TCP数据。序列号字段的值是本报文段发送的数据的第一个字节的序列号。简称为seq |
确认号 | 为了确认接收端确实收到了发送端发送的数据包数据,当发送端收到这个确认码时,就可以确定之前传递的数据包已经被正确接收。这个确认号是期望收到对方下一个报文段的数据的第一个字节的序列号。简称ack |
头部长度 | 表示TCP头部的长度,范围(0~15),单位32位,例如值为5时,表示头部长度是20字节(160位),如果选项字段为空,则TCP头部长度为20字节,即值为5 |
URG | URG=1 表示存在紧急数据,紧急数据的最后一个字节由紧急数据指针指出,一般使用较少 |
ACK | ACK=1 表示确认号字段中的值是有效的,为0表示无效 |
PSH | URG=1 表示紧急指针字段有效,代表该数据包为紧急数据包。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据) |
RST | RSP=1 表示重建连接,如果接收到RST位时,通常发生了某些错误 |
SYN | SYN=1 表示这是一个连接请求或连接接受报文,一般用于握手阶段 |
FIN | FIN=1 表示此报文段的发送端的数据已发送完毕,并要求释放运输连接 |
接收窗口 | 用于流量控制,指示接收方愿意接收的字节数量,范围0~65535 字节 |
校验和 | 校验和覆盖了整个TCP报文段,即TCP头部和TCP数据,这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行验证 |
紧急数据指针 | 当URG=1 时有效,是一个正的偏移量,和序列号中的值相加表示紧急数据最后一个字节的序列号 |
选项 | 用于发送方和接收方协商最大报文长度(MSS)时(只存在于SYN报文)或在高速网络环境下用作窗口调节因子时使用,还可以存放时间戳数据 |
TCP 状态机
TCP 三次握手/四次挥手
三次握手过程
- 客户端发送
SYN=1
,并指明客户端的初始序列号ISN
,即x
. - 服务端发送自己的
SYN
段作为应答,同样指明自己的ISN
即y
。为了确认客户端的SYN
,将x+1
作为ACK
数值。这样,每发送一个SYN
,序列号就会加1. 如果有丢失的情况,则会重传。 - 为了确认服务器端的
SYN
,客户端将y+1
作为返回的ACK
数值。
TCP 四次挥手
- 客户端发送
FIN=1
,并包含一个自己当前的序列号x+2
。 同时还包含一个ACK=y+1
表示确认对方最近一次发过来的数据。 - 服务端将
x+2
值加1作为ACK
序号值,表明收到了上一个包。这时上层的应用程序会被告知另一端发起了关闭操作,通常这将引起应用程序发起自己的关闭操作。 - 服务端发起自己的
FIN=1
,seq=y+1
。 - 客户端确认, 向服务器发送
ACK=y+2
。
为什么要三次握手?作用是什么?
详情
TCP 建立连接的过程就是同步序列号的过程,SYN (Synchronize Sequence Numbers)就是同步序列号。因此,三次握手的目的就是使客户端(Client)和服务端(Service)获取到对方的序列号。
为什么要四次挥手?作用是什么?
详情
之所以需要四次挥手,是因为 tcp 是全双工协议,即客户端和服务端都可以主动发送消息,因此需要两端分别在传输完成后发送断开连接的指令,需要分别发送 FIN=1
指令断开,通过 ACK
判断是否发送成功。
如果连接时 SYN 超时会发生什么?
详情
假如客户端发送 SYN
指令,在服务器返回 SYN
指令之前掉线了,服务器会尝试重发 SYN-ACK
指令,linux 下默认重试 5 次,间隔时间从 1s 开始翻倍增长,即 1s, 2s, 4s, 8s, 16s
, 因此超时时间为 1s + 2s + 4s+ 8s+ 16s + 32s = 63s
。在超时之后 TCP 才会断开连接。
TCP 如何保证传输的可靠性?
TCP 通过以下几个特性保证数据传输的可靠性
- 序列号和确认应答
- 超时重传
- 流量控制
- 拥塞控制
- 校验和
序列号和确认应答信号
TCP 通过序列号可以对数据包进行排序和去重,同时通过 ACK 应答机制确保数据包成功送达,保证了数据的完整性。
超时重传
TCP 通过超时重传机制可以在数据包丢失或者延迟时,重新发送数据包直到收到 ACK 应答。
什么是RTT?什么是RTO?
详情
RTT代表往返时间(Round Trip Time),是指数据从发送方传输到接收方并返回所需的时间。RTT用于衡量网络延迟,即数据在传输过程中经过的总时间。
RTO代表重传超时时间(Retransmission Timeout),是指在网络通信中,发送方发送数据后等待确认(ACK)的时间。如果发送方在RTO时间内未收到确认,它会假设数据丢失,并重新发送该数据。
RTO的计算通常基于RTT的测量。发送方根据前一次的RTT来估计下一次发送数据的RTO。一般情况下,RTO的值会比RTT大一些,以确保在网络延迟较高或不稳定的情况下也能够成功重传数据。
RTO的计算方法可以根据具体的网络协议或实现而有所不同,但其目的是为了确保数据的可靠传输,以应对网络中的丢包、延迟和拥塞等问题。
RTO 长短对重传有什么影响?
详情
若 RTO 过长则重传时间会大大延长,降低传输效率。若 RTO 过短则可能会导致频繁重传,加剧网络的拥堵,进一步触发更多的重传。
常见的重传机制
详情
- 超时重传
超时重传有两种情况,发送的数据包丢失导致的超时,和返回的 ACK 数据包丢失导致的超时。超时重传机制下,在每次发送数据包的时候都会启动一个定时器,如果定时器到期则会触发重传。若重传失败,则下一次超时时间为当前值的两倍。超时重传的缺点是周期较长,可能会降低效率。
- 快速重传
在快速重传机制下,在数据包丢失后,接收端每接收一个失序的数据包就立即返回重复的确认报文段,告知发送端缺少的报文段。当发送方收到三个重复的确认报文段后,会立即重传缺失的报文段。
在快速重传的机制下,我们可以看到 3,4,5
的报文段返回的都是 ACK=2
, 因此还需要重传 3,4,5
报文段。有没有方法可以不需要重传 3,4,5
报文段?
- SACK (Selective Acknowledgment, 选择性确认)
SACK 方法 (RFC 2018) 在 tcp 的 option 字段添加了缓冲区,用于记录已传输的数据包,这样发送方可以看到未成功传输的数据包,使得发送方可以仅传输缺失的数据包而不需要额外重传其他数据包。
- D-SACK (Duplicate SACK, 重复选择性确认)
D-SACK (RFC 2883) 主要解决了 ACK 丢失的问题, D-SACK 使用 SACK 第一个段作为标志位,用于标记已经 ACK 的数据包。 当接收端接收到重复的报文段时会将该报文段写入 D-SACK 的标志位,告诉发送方已接收到报文段, ACK 可能已丢失。
流量控制
TCP 使用滑动窗口来控制流量,使得发送端可以根据接收端的接收能力控制发送数据的速度。
注意
接收端在应答 ACK
的时候会将当前可用的窗口大小写入 tcp 头部,发送端根据窗口大小调整发送速率。
拥塞控制
算法
- 慢开始
- 拥塞避免
- 快重传
- 快恢复
相关名词
- cwnd - 拥塞窗口
- ssthresh - 慢开始门限
重要
cwnd < ssthresh
,使用慢开始算法。cwnd > ssthresh
,使用拥塞避免算法。cwnd = ssthresh
,使用慢开始与拥塞避免算法任意一个。
慢开始
在慢开始阶段, cwnd
初始值为 1
, 每经过一个传播轮次,cwnd
都会翻倍,直到达到 ssthresh
。
拥塞避免
当 cwnd
达到 ssthresh
,则会执行拥塞避免算法,此时 cwnd
的增长从翻倍增长变为每经过一个传播轮次就加 1
。若发送方检测到网络拥塞(即发送的消息没得到及时的回应),就会将 ssthresh
设置为发生网络拥塞时的 cwnd
值的一半,同时 cwnd
的值将会重置为 1
,重新执行慢开始。
快重传和快恢复
快重传在前面已介绍过,即如果连续收到三个重复的确认就会立即发送尚未接收到的报文段。快恢复算法需要配合快重传算法使用。图中的 5 号为快恢复阶段。
快恢复算法
- 当发送端连续收到三个重复的确认时,将
ssthresh
减半。 - 将
cwnd
设置为ssthresh
的大小
校验和
TCP 还会对数据计算校验和,确保数据在传输过程中未丢失或出现错误。
UDP
UDP,全称用户数据报协议(User Datagram Protocol),是OSI(开放系统互联)参考模型中的一种无连接的传输层协议。它提供面向事务的简单不可靠信息传送服务,其正式规范是 IETF RFC 768
。
特点
- 无连接:UDP在传输数据前不需要在客户和服务器之间建立一个连接。
- 速度快:由于UDP不需要进行握手或检查数据是否正确到达,所以它能够比TCP更快地传输数据。
- 不可靠性:当报文发送之后,是无法得知其是否安全完整到达的。如果UDP数据报在传输过程中丢失,它不会重新发送。
- 应用广泛:UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。例如,许多互联网电话服务使用的IP语音 (VoIP) 通常是使用UDP发送的。
结构
字段 | 大小 | 描述 |
---|---|---|
源端口 | 16位 | 源端口号。若全为 0 则意味着不允许回信 |
目的端口 | 16位 | 目标端口号 |
长度 | 16位 | UDP用户数据报的长度,其最小值是8(仅有首部) |
检验和 | 16位 | 检测数据在传输过程中是否丢失或修改 |
广播类型
类型 | 描述 |
---|---|
单播 | 用于两个主机之间端对端的通信。即一对一(客户端与服务器端点到点连接) |
广播 | 用于一个主机对整个局域网上所有主机通信。即一对所有。广播禁止在Internet宽带网上传输(广播风暴) |
组播(多播) | 对一组特定的主机进行通信,而不是整个局域网上的所有主机。即一对一组 |
注意
- TCP 只支持一对一
- UDP 多播较为常用,广播仅用于局域网
TCP 和 UDP 区别
特性 | TCP | UDP |
---|---|---|
可靠传输 | 是 | 否 |
连接 | 面向连接 | 无连接 |
数据有序性 | 有 | 不保证 |
数据边界 | 不保存 | 保留 |
传输速度 | 相对慢 | 快 |
流量控制和拥塞控制 | 有 | 没有 |
协议类型 | 重量级 | 轻量级 |
首部长度 | 20字节 | 8字节 |
常见的 TCP/UDP 攻击
SYN Flood 攻击
SYN Flood 攻击的原理非常简单,实际上是利用了服务器的超时机制。我们知道接收方在收到 SYN
请求的时候会返回 SYN + ACK
响应,若接收方的响应没得到回复,会进行重试 (如果连接时 SYN 超时会发生什么?) , 维护一个半连接状态。攻击者只需要使用多个主机向服务器发送大量半连接请求,服务器最终会导致资源耗尽,无法提供服务。
[!tip]
如何检测 SYN Flood 攻击?
- 入站网络流量增加: SYN Flood 会导致服务器的入站网络突然增加
- 网络性能下降: SYN Flood 会导致网络性能下降
- 大量 SYN 半连接: SYN Flood 会产生大量半连接
- 服务器无响应: SYN Flood 会导致服务器无法响应请求
如何缓解?
防御措施 | 描述 |
---|---|
增加最大半连接数 | 增加最大半连接数允许服务器处理大量传入的 SYN 请求,从而提供针对泛洪尝试的缓冲区。 |
过滤 | 在网络设备中设置规则,根据特定模式或已知的恶意 IP 地址识别和阻止恶意 SYN 请求。 |
减少SYN-RECEIVED定时器时间 | 通过减少服务器在发送 SYN-ACK 后等待 ACK 响应的时间,可以更快地释放分配给半开连接的资源。 |
SYN缓存 | 服务器使用缓存来存储有关每个请求的较少信息,最大限度地减少资源消耗。 |
SYN Cookies | 服务器发回 SYN-ACK 响应,而不立即为连接分配资源,仅当收到合法的 ACK 响应时才分配资源。 |
负载均衡器 | 将传入的网络流量分布到多个服务器上,确保没有任何一台服务器会首当其冲地受到攻击。 |
防火墙和代理 | 部署防火墙和代理可以在恶意流量到达目标服务器之前过滤掉恶意流量,提供额外的防御层。 |
蜜罐和蜜网 | 蜜罐吸收和转移攻击,为攻击者提供有价值的干扰,并保护关键基础设施。蜜网通过收集攻击者策略的数据来提供威胁情报。 |
速率限制 | 限制传入连接请求的速率是防止 SYN 洪水攻击的重要策略。 |
混合方法 | 结合多种技术可以创建针对 TCP SYN Flood 攻击的分层防御,确保在一种方法失败时其他人仍然可以提供保护。 |
基于云的DDoS防护解决方案 | 利用基于云的 DDoS 防护解决方案可以将流量卸载并过滤到能够处理大规模攻击的专用平台。 |
什么是 UDP Flood 攻击?
[!important]
服务器在接收到 UDP 包时会发生以下操作:
- 检查对应端口是否有程序正在监听
- 若没有程序,则服务器使用 ICMP 包响应不可达的信息
因此攻击者通过频繁向服务器的多个端口发送大量 UDP 请求使得服务器在处理大量回应时资源耗尽而达到目的。
如何缓解?
可以通过限制 ICMP 响应时间来缓解,但是这也导致正常的 PING 请求受到影响。