《TCP/IP详解 卷一》第13章 TCP连接管理

目录

[13.1 引言](#13.1 引言)

[13.2 TCP连接的建立与终止](#13.2 TCP连接的建立与终止)

[13.2.1 TCP半关闭](#13.2.1 TCP半关闭)

[13.2.2 同时打开与关闭](#13.2.2 同时打开与关闭)

[13.2.3 初始序列号](#13.2.3 初始序列号)

[13.2.4 例子](#13.2.4 例子)

[13.2.5 连接建立超时](#13.2.5 连接建立超时)

[13.2.6 连接与转换器](#13.2.6 连接与转换器)

[13.3 TCP 选项](#13.3 TCP 选项)

[13.3.1 最大段大小选项](#13.3.1 最大段大小选项)

[13.3.2 选择确认选项](#13.3.2 选择确认选项)

[13.3.3 窗口缩放选项](#13.3.3 窗口缩放选项)

[13.3.4 时间戳选项与防回绕序列号](#13.3.4 时间戳选项与防回绕序列号)

[13.3.5 用户超时选项](#13.3.5 用户超时选项)

[13.3.6 认证选项](#13.3.6 认证选项)

[13.4 TCP的路径最大传输单元发现](#13.4 TCP的路径最大传输单元发现)

[13.4.1 例子](#13.4.1 例子)

[13.5 TCP状态转换](#13.5 TCP状态转换)

[13.5.1 TCP状态转换图](#13.5.1 TCP状态转换图)

[13.5.2 TIME_WAIT 状态](#13.5.2 TIME_WAIT 状态)

[13.5.3 静默时间](#13.5.3 静默时间)

[13.5.4 FIN_WAIT_2 状态](#13.5.4 FIN_WAIT_2 状态)

[13.5.5 同时打开与关闭的转换](#13.5.5 同时打开与关闭的转换)

[13.6 重置报文段](#13.6 重置报文段)

[13.6.1 请求端口不存在](#13.6.1 请求端口不存在)

[13.6.2 终止一条连接](#13.6.2 终止一条连接)

[13.6.3 半开连接](#13.6.3 半开连接)

[13.6.4 时间等待错误](#13.6.4 时间等待错误)

[13.7 TCP服务器选项](#13.7 TCP服务器选项)

[13.7.1 TCP 端口号](#13.7.1 TCP 端口号)

[13.7.2 限制本地IP地址](#13.7.2 限制本地IP地址)

[13.7.3 限制外部节点](#13.7.3 限制外部节点)

[13.7.4 进入连接队列](#13.7.4 进入连接队列)

[13.8 与TCP连接管理相关的攻击](#13.8 与TCP连接管理相关的攻击)

[13.9 总结](#13.9 总结)


13.1 引言

建立连接时,通信双方通过TCP选项交换参数。

某些选项只被允许在连接建立时发送。

TCP头部中选项最多为40字节。

13.2 TCP连接的建立与终止

ISN:初始序列号。发起方设置的随机的序列号。

上图连接关闭时,四次挥手中二三次报文序列号Seq都是L,这是因为没有发送数据。

TCP的SYN报文可承载应用数据。由于伯克利的socket API不支持,所以使用少。

每个TCP连接基本开销是7个报文段(三次握手,四次挥手)。

如果只传输少量数据,可用UDP协议,减少开销。但UDP存在拥塞管理,流量控制等问题。

13.2.1 TCP半关闭

如下图:关闭连接时,四次挥手只完成其中两次。此时即TCP半关闭状态。

场景:已完成数据发送,并发送FIN给对方,但仍希望接收来自对方数据,直到收到对方的FIN。

半关闭API:

shutdown(sock_fd, SHUT_WR);

关闭套接字写入端,但允许接收对方数据。

shutdown和close对比:

shutdown:

通过不同参数选择只关闭套接字读或写某一方向,或读写同时关闭。

不会立即关闭套接字,而是进入半关闭状态

close:

完全关闭套接字,读写均关闭,并释放资源。

13.2.2 同时打开与关闭

同时打开:

两个对等端同时发送连接请求(SYN),并相互确认(ACK)对方的连接请求。

作用:

同时发送连接请求,可减少连接延迟。

同时发送连接请求,可使NAT设备进行连接追踪conntrak正确处理连接。避免TCP连接失败。

报文交互:

4次握手( SYN+ACK,SYN+ACK)

同时关闭:

两个对等端同时发送连接关闭请求(FIN),并相互确认(ACK)对方的关闭请求。

13.2.3 初始序列号

初始序列号:即ISN。

每个TCP连接都有不同初始序列号,不与其他连接重复。

ISN作用:

用于数据包排序和重组。

防止旧连接延迟报文段被视为新连接的有效数据。

防止伪造合法TCP报文段。

Linux生成初始序列号ISN方法:

当前时钟+随机偏移量。

随机偏移量:连接标识(即4元组)散列得到。

13.2.4 例子

TCP有的选项不能在连接建立时使用,而有的选项可以。

13.2.5 连接建立超时

如服务器关闭,连接建立超时。

net.ipv4.tcp_syn_retries:

若未收到第二次握手SYN + ACK报文,第一次握手SYN报文最大重传次数。

通常为5。

net.ipv4.tcp_synack_retries:

若未收到第三次握手ACK报文,第二次握手SYN+ACK报文最大重传次数。

通常为5。

SYN和SYN+ACK两个报文重传时间都遵循指数回退原则。

13.2.6 连接与转换器

TCP计算校验和时会生成伪头部,伪头部包含源目IP等。

NAT转换后,会更改报文源IP,所以需要重新计算TCP校验和。

在NAT转换中也会读取TCP状态机,方便跟踪连接,包括当前状态、序列号,ACK号。

13.3 TCP 选项

下面按章节讲解常见选项。

13.3.1 最大段大小选项

最大段大小:即MSS。

即TCP载荷最大值,不包含TCP头。

TCP连接建立时,双方都在SYN报文的MSS选项中指明各自MSS。

最后选择双方较小的MSS,作为该连接MSS。未指明时默认536。

MSS典型值:

IPv4 MSS通常为1460字节(1500 MTU - 20 IP头 - 20 TCP头)

IPv6 MSS通常为1440字节。IPv6头部比IPv4多20个字节。

MSS协商成功后,双方在连接过程中不接收大于MSS报文段。

13.3.2 选择确认选项

传统的TCP只能确认收到的连续字节,而不能确认中间丢失的数据。

选择确认:即SACK。

SACK选项允许接收方报告成功接收的连续数据段以及中间丢失部分,使发送方只重传中间丢失部分,提高网络效率。

SACK选项两部分组成:

SACK Permitted:表示是否支持SACK 选项。

SACK Blocks:指示已成功接收的数据段范围。

TCP头部选项空间有限,一个报文段最多3个SACK Blocks。

13.3.3 窗口缩放选项

缩放:SCALE

窗口缩放选项(Window Scale Option):

TCP头的窗口缩放选项中包含一个缩放因子,指示对方的窗口大小应按比例缩放。

TCP头部本来有窗口字段值,再乘以缩放因子,实现窗口缩放。

窗口缩放选项只能出现SYN报文段。

可根据网络丢包/延迟情况动态调整窗口大小,提高传输性能。

适用于:

高速网络:传统TCP窗口太小,无法充分利用网络带宽。

长距离网络

高丢包率网络

13.3.4 时间戳选项与防回绕序列号

时间戳选项(TSOPT):

在TCP头中加入时间戳信息,用于测量传输延迟,计算往返时间RTT。

时间戳选项包含两个值:

TSval:Timestamp Value

发送端发送TCP报文时记录的时间戳。

TSecr:Timestamp Echo Reply

接收端表示接收到报文时的时间戳。

通过TSval ,TSecr值即可计算RTT。

RTT是衡量网络性能和稳定性的重要指标。

RTO(Retransmission Timeout):

用于确定数据包的重传的时间间隔。

RTO值通常设为众多RTT采样值中较大一个,以便RTT波动大或网络拥塞时,仍能够正常传输,避免过早重传。

时间戳选项其他作用:

序列号回绕:指当TCP序列号达到最大值后(2^32-1),重新从0开始计数。

即使在序列号回绕时,时间戳选项提供了另一个递增的、唯一的标识符,避免序列号重叠问题,提高传输稳定性。

13.3.5 用户超时选项

用户超时(UTO)选项:

表示未收到数据ACK之前等待最长时间。

该选项允许应用程序自定义的超时时间,以便快速检测连接异常,并定制化超时处理策略。

设置TCP UTO选项:

int utimeout_ms = 5000;

setsockopt(sockfd, IPPROTO_TCP, TCP_USER_TIMEOUT, &utimeout_ms, sizeof(utimeout_ms)) ;

检测TCP UTO是否超时:

getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len);

if (error == ETIMEDOUT) {

//UTO超时处理,如重传等。

}

NAT设备可将UTO时间设置为NAT连接活动计时器。

13.3.6 认证选项

目的:替换TCP-MD5机制。

TCP 认证选项(TCP Authentication Option, TCP-AO)

作用:握手时身份验证,密钥协商,加密通信。

13.4 TCP的路径最大传输单元发现

路径最大传输单元:PMTU,路径中所有设备MTU最小值。

13.4.1 例子

PPPoE的MTU为1492字节(以太网MTU 1500,减6字节PPPoE头,再减2字节PPP头)

配置接口MTU:

ifconfig ppp0 mtu 288

该接口向外发出报文最大为288字节,但是接收不受288限制。

内核参数net.ipv4.route.min_pmtu:

手动设置本地IPv4的PMTU。

本地转发IP数据包时,如果数据包大于min_pmtu,可分片。

13.5 TCP状态转换

13.5.1 TCP状态转换图

13.5.2 TIME_WAIT 状态

不携带数据的ACK不会消耗序列号

ACK丢失,不会重传ACK,而是对方等待ACK超时后,重传之前数据。

TIME_WAIT状态:等待2MSL时候后才变为CLOSED状态。

MSL:最大段生存期(Maximum Segment Lifetime)

一个TCP段在网络上能存在的最长时间。

TIME_WAIT状态等待一段时间才完全关闭连接。

作用:

如果服务器要重传FIN时,以便再次回复ACK。

处理延迟/重传数据:可等待接收因网络延迟或重传数据,之后再彻底关闭连接。

防止收到旧连接报文:

TIME_WAIT状态时,不允许建立新连接,所以不存在新连接接收到旧连接数据。

(除非使用了SO_REUSEADDR socket选项)

防SYN泛红攻击:TIME_WAIT状态时,不允许新连接,自然不处理SYN报文。

拓展:使用SO_REUSEADDR选项立即建立新连接后,如果收到TIME_WAIT旧连接的延迟数据,如何处理?

  1. 区分数据:

内核通常通过检查序列号SN等标识来区分TIME_WAIT连接和新连接数据。

  1. 处理:

如果数据与TIME_WAIT连接有关,内核丢弃数据。

13.5.3 静默时间

13.5.4 FIN_WAIT_2 状态

FIN_WAIT_2:

表示本端已发送关闭连接请求(FIN),并收到对方ACK。等待对方发送FIN报文。

对应内核参数net.ipv4.tcp.fin.timeout:

表示FIN_WAIT_2等待状态的最长时间,默认60秒。

如果在此时间内未收到对端的FIN报文,内核将释放/复位此连接。

13.5.5 同时打开与关闭的转换

13.6 重置报文段

即TCP头中带RST标志位的报文。

作用:强制终止TCP连接。

使用场景:

终止异常连接,如系统崩溃。

收到了不期望的SYN连接请求时,服务器拒绝连接请求。

收到非法数据流,终止连接。

下面章节详细介绍使用场景。

13.6.1 请求端口不存在

收到一个报文,本地没有监听该报文目的端口时:

UDP:回复ICMP目的地不可达(端口不可达)。

TCP:回复RST重置报文段。

13.6.2 终止一条连接

终止一条TCP连接的两种方法:

FIN:即正常四次挥手,有序释放,所有排队数据都已发送后再发送FIN,通常不会出现丢失数据情况。

RST:发送RST报文,断开连接。任何排队的数据都将被抛弃。

调用 close函数关闭套接字时,内核会尝试将套接字的发送缓冲区中的数据发送出去。

如果还有数据包没收到对端ACK,close函数会阻塞等待ACK确认或超时。

如果不启用SO_LINGER,会立即关闭套接字,而不管发送缓冲区中是否有未发送数据。

13.6.3 半开连接

半开连接:

含义:只单方面关闭一个方向连接。

造成原因:

客户端发送了FIN,并收到服务器ACK。但是服务器一直没有发送FIN。

此时只断开了单方向连接。客户端不能发送数据,但可从服务器接收数据。

典型场景:

通信一方的主机崩溃,断电,拔网线。

如果不通过半开连接传输数据,就无法检测出另一端已崩溃。

解决方法:

周期发送TCP keepalive消息来检测连接状态。

若超时没收响应,使用RST报文终止连接。

13.6.4 时间等待错误

时间等待错误(TIME-WAIT Assassination TWA)

网络滞留段有使得TIME_WAIT状态被意外结束。

举例:

TCP A收到旧连接延迟数据,并回复ACK。

TCP B收到莫名其妙的ACK后,会发出RST报文。

TCP A收到RST包后,TCP A提前从TIME-WAIT状态变为CLOSED状态。

解决方法:TIME_WAIT状态时忽略所有RST报文。

13.7 TCP服务器选项

13.7.1 TCP 端口号

查看本地TCP连接详细信息,包括使用的端口号:

netstat -antp

-a:显示所有连接,包括正连接和已建立。

-n:使用数字形式显示地址和端口。

-t: 仅显示TCP连接信息。

-p: 显示TCP连接的进程名和PID。

Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program

tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN -

tcp 0 0 172.19.254.6:22 172.19.1.46:49244 ESTABLISHED -

tcp 0 0 172.19.254.6:445 172.16.15.62:65306 SYN_RECV -

13.7.2 限制本地IP地址

如果本地有多个IP,可指定使用哪个IP地址用于TCP连接。

server_addr.sin_addr.s_addr = inet_addr("192.168.1.100");

bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));

反之:

server_addr.sin_addr.s_addr =INADDR_ANY;

此时服务器将监听所有网络接口上的数据。

13.7.3 限制外部节点

作用:

等待一个指定的客户端IP+端口发起主动连接。

伯克利套接字API没有该实现,即没有对应socket选项,只能等待连接到来后,再检查客户端的IP地址与端口号。

13.7.4 进入连接队列

半连接队列:

即SYN队列。

收到客户端的SYN报文时,服务器将连接请求放入半连接队列。此时服务器为SYN_RCVD 状态。

全连接队列:

当服务器调用accept函数接受连接,服务器将连接请求从半连接队列中移出,并放入全连接队列。此时服务器为ESTABLISHED状态。

内核参数net.ipv4.tcp_max_syn_backlog:

当服务器的SYN_RCVD状态的连接数超过该阈值,拒绝新连接请求。

未完成连接(backlog):

已完成TCP三次握手,但还没有通过accpet函数接收连接。

backlog队列最大值为:net.core.somaxconn,默认128。

服务器队列溢出时,如果收到客户端连接请求,如何处理?

如果回复RST报文给客户端,客户端会认为服务器存在并繁忙,后续会继续请求连接。

所以最好不回复任何消息,让客户端以为服务器不存在。

13.8 与TCP连接管理相关的攻击

  1. SYN泛洪攻击:

含义:

随机伪造源IP,发起大量SYN连接请求,使服务器维护大量半连接,耗尽系统资源尽。

半连接队列满后,服务器无法接受新连接请求,从而实现DoS攻击。

防攻击方法:

开启SYN cookies机制。

对应文件/proc/sys/net/ipv4/tcp_syncookies

SYN cookies工作原理:

服务器收到SYN包时,根据报文参数(如源目IP地址、源目端口号等)计算哈希值。

服务器将哈希值作为SYN+ACK包的序列号,将SYN+ACK发送给客户端。

客户端收到SYN+ACK包后,解析出序列号,并+1后作为ACK中确认号,将ACK回复给服务器。

服务器收到客户端ACK包后,将确认号-1,和之前的哈希值比较,若一致是合法请求。

开启SYN cookies后,不会在收到SYN报文后立刻创建半连接队列。

只有三次握手完毕才分配内存。

  1. MTU非常小的ICMP PTB packet too big

PTB:Packet Too Big

含义:

伪造ICMP PTB消息,其中包含非常小的下一跳MTU。

被攻击方TCP被迫只能发送非常小数据包,降低性能。

解决方法:

当ICMP PTB消息的下一跳MTU小于576字节时,禁用路径最大传输单元发现(PMTUD)功能。

  1. 欺骗攻击

含义:伪造4元组和校验都正确的RST报文,发给一个TCP连接。

解决方法:使用TCP-AO选项认证每一个报文。

13.9 总结

相关推荐
IPFoxy66629 分钟前
探索路由器静态IP的获取方式
网络·智能路由器
menge23331 小时前
VLAN:虚拟局域网
网络·智能路由器
ZachOn1y1 小时前
计算机网络:计算机网络概述 —— 初识计算机网络
网络·计算机网络·知识点汇总·考研必备
三金121382 小时前
SpringIoC容器的初识
网络·网络协议·rpc
狼头长啸李树身3 小时前
眼儿媚·秋雨绵绵窗暗暗
大数据·网络·服务发现·媒体
SizeTheMoment4 小时前
初识HTTP协议
网络·网络协议·http
哲伦贼稳妥4 小时前
一天认识一个硬件之机房地板
运维·网络·经验分享·其他
hgdlip6 小时前
如何快速切换电脑的ip地址
网络·tcp/ip·电脑
程序员-珍7 小时前
虚拟机ip突然看不了了
linux·网络·网络协议·tcp/ip·centos
4647的码农历程8 小时前
Linux网络编程 -- 网络基础
linux·运维·网络