写点什么

TechBits | TCP 使用 WireShark 进行抓包

作者:Java你猿哥
  • 2023-03-20
    湖南
  • 本文字数:13085 字

    阅读完需:约 43 分钟

了解 TCP 并使用 WireShark 进行抓包

前言:

我还记得有一次在工作中遇到一个网络情况:我通过调用第三方提供的接口,完成了一个采集任务。过来一段时间,采集数据出现了问题,我开始排除,发现请求对方接口出现一种现象:有的时候连接会超时,有的时候又不会超时,导致采集出现问题。但是,出现这个问题我无法判断问题出现在哪里,因此存在时而成功时而失败的问题,那就意味双方提供的接口都没有问题,那就是网络问题!。和对方沟通之后,打算在服务器上打印 TCPDump 文件,双方同时进行,查看报文是否有成功发送接受,对方是否有成功接受返回。(当然,那时我不会 wireshark,请大佬帮忙一起解决,看到大佬使用,我就对此感到兴趣,觉得我是不是也可以学习一下,简单使用呢?),最后发现 我这边的报文确实有发送过去,但是对方没有将数据发送回来,是因为对方防火墙做了改变导致的。

TCP

传输控制协议(英語:Transmission Control Protocol,縮寫:TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议

TCP 协议是在互联网协议中的传输层协议,它负责在不可靠的网络中提供安全、可靠的数据通信。并通过一系列的措施来保证数据包的可保数据包的可靠传输,包括序列号、确认应答、重传机制等。

为什么网络不可靠呢?

宽带限制

互联网上的宽带往往受到限制,因此可能发生拥塞和延迟,导致数据包丢失和传输失败

宽带

通常指在单位时间内可传输数据的最大速率,通常以 位/秒 (bps) 或者 兆位/秒(Mbps)

网络带宽通常使用“比特每秒”(bps)作为单位来表示。而在计算机领域中,通常使用“兆比特每秒”(Mbps)或“千兆比特每秒”(Gbps)来表示网络带宽。其中,1Mbps 等于 1,000,000 比特每秒,1Gbps 等于 1,000,000,000 比特每秒。

假设你想从你的电脑上传一个大小为 1 GB 的文件到云存储服务中。假设你的网络带宽是 100 Mbps(百兆比特每秒),那么根据带宽的定义,在理想情况下你可以在 10 秒内完成文件的上传。但实际情况可能会因为网络拥堵等因素而变得更慢。

文件大小为 1 GB

1GB=1∗1024∗1024∗1024∗8bit1GB = 1 * 1024 * 1024 * 1024 * 8 bit 1GB=1∗1024∗1024∗1024∗8bit

网络带宽为 100 Mbps

100Mbps=100∗1000∗1000bps100 Mbps = 100 * 1000 * 1000 bps 100Mbps=100∗1000∗1000bps

速率公式

时间=文件大小÷网络带宽时间 = 文件大小 ÷ 网络带宽 时间=文件大小÷网络带宽

计算结果:

(1∗1024∗1024∗1024∗8bit)÷[100∗1000∗1000(bps/s)]≈10.74 秒( 1 * 1024 * 1024 * 1024 * 8 bit ) ÷ [ 100 * 1000 * 1000 (bps/s) ] ≈ 10.74 秒 (1∗1024∗1024∗1024∗8bit)÷[100∗1000∗1000(bps/s)]≈10.74 秒

网络安全

⽹络中存在的恶意软件和攻击可能会导致数据包的损坏或丢失,这可能会影响数据的可靠性。

针对 TCP 常见的攻击

SYN 攻击:SYN 攻击是一种常见的 DoS(拒绝服务)攻击方式。攻击者发送大量伪造的 TCP SYN 连接请求,占用目标主机的连接队列资源,导致合法的连接请求无法被处理。

攻击方式:

攻击者伪造大量的 SYN 请求并向目标主机发送,这些请求看起来像是从合法的客户端发送的,但实际上这些请求并不会回复 ACK,从而使目标主机的连接队列堆积满,无法再接受新的连接请求。这样,合法用户将无法访问受攻击的网络服务。

攻击工具:

攻击者可以使用一些网络工具来发动 SYN 攻击,例如 hping、nmap 和 zmap 等工具。这些工具允许攻击者以高速和大量地向目标主机发送 SYN 请求,从而使其连接队列堆积满。

防御措施:

防火墙可以过滤掉来自恶意 IP 地址的 SYN 请求,而 IDS 可以监测网络流量和异常连接,从而及时发现和防御 SYN 攻击。

使用负载均衡技术。负载均衡技术可以将连接请求分散到多台服务器上,从而分摊连接队列的负载,减少单台服务器受到攻击的风险。


窗口扫描攻击: 窗口扫描攻击是一种利用 TCP 连接的方式进行端口扫描的攻击方法。攻击者发送大量的 TCP 连接请求,利用 TCP 连接的窗口大小信息探测目标主机的开放端口信息。

攻击方式:

窗口扫描攻击利用了 TCP 协议中的一个特性,即当客户端发送一个 SYN 包到服务器端时,如果服务器的端口是关闭的,那么服务器会返回一个 RST 包(复位包),表示拒绝连接。但如果服务器端的端口是打开的,服务器会发送 SYN/ACK 包,表示准备建立连接。攻击者可以通过观察服务器的 SYN/ACK 包的窗口大小来判断端口是否打开。

攻击工具:

攻击者可以通过编写程序或使用现成的扫描工具来进行窗口扫描攻击,如 Nmap 等扫描工具。攻击者使用窗口扫描工具发送一些特定的 TCP 报文给目标主机,通过观察返回的 TCP 报文,判断端口是否打开或关闭

防御措施:

关闭不必要的端口和服务,只打开必须的端口和服务,可以减少攻击者进行窗口扫描的机会

在防火墙上禁止 ICMP 和 UDP 报文的返回,只允许合法的 TCP 报文通过,可以有效地减少窗口扫描的攻击。


TCP Reset 攻击:TCP Reset 攻击是一种利用 TCP 连接复位(RST)报文强制中断 TCP 连接的攻击方式。攻击者发送伪造的 TCP RST 报文,欺骗目标主机终止正常的 TCP 连接。

攻击方式:

攻击者会发送虚假的 TCP 重置(RST)包给通信双方的一方,以终止这方的 TCP 连接。攻击者可以伪造 TCP RST 包的源地址和端口号,让另一端的主机误以为连接已经被重置,从而终止连接。

攻击工具:

攻击者可以使用一些网络工具来进行 TCP Reset 攻击,例如 Hping、Scapy、Nmap 等。

防御措施:

使用防火墙和入侵检测/防御系统(IDS/IPS)来监控和过滤网络流量,防止恶意的 TCP RST 包进入网络。

使用加密协议(如 TLS/SSL)来保护 TCP 连接,使攻击者无法窃取或篡改 TCP 数据流


TCP 序列号攻击:TCP 序列号攻击是一种利用 TCP 序列号的漏洞进行的攻击方法。攻击者通过分析 TCP 数据包的序列号,伪造合法的 TCP 数据包,欺骗目标主机接受恶意数据。

攻击方式:

攻击者可以利用被攻击主机上的 TCP/IP 栈的缺陷,推测出下一个 TCP 报文的序列号,并通过发送伪造的 TCP 报文来欺骗被攻击主机,从而实现窃取或篡改 TCP 数据流的目的

攻击工具:

攻击者可以使用一些工具来进行 TCP 序列号攻击,例如 Scapy、Nmap、hping 等。

防御措施:

使用加密协议(如 TLS/SSL)来保护 TCP 连接,使攻击者无法窃取或篡改 TCP 数据流。

配置 TCP/IP 栈的参数,例如通过启用 TCP Timestamps 或减少 TCP Time-Wait 状态的持续时间来增加随机性,减少被攻击的可能性


TCP 欺骗攻击:TCP 欺骗攻击是一种利用 TCP 协议的特性进行的攻击方式。攻击者伪造 TCP 连接请求,欺骗目标主机建立 TCP 连接,然后发送恶意数据进行攻击。

攻击方式:

攻击者通常需要先扫描目标主机上开放的端口和服务,然后发送伪造的 TCP 报文来欺骗目标主机。欺骗攻击可以分为两类:

  1. 短连接欺骗攻击:攻击者发送一个欺骗性的 SYN 报文,被攻击主机会向欺骗者返回 SYN/ACK 报文。攻击者可以选择忽略 ACK 报文,使得 TCP 连接无法完成建立,也可以发送一个 RST 报文,中断已经建立的连接。

  2. 长连接欺骗攻击:攻击者在成功建立一个 TCP 连接后,可以发送伪造的 TCP 数据流来窃取或篡改数据。

攻击工具:

攻击者可以使用一些工具来进行 TCP 欺骗攻击,例如 Scapy、Hping、Nmap 等。

防御措施:

使用加密协议(如 TLS/SSL)来保护 TCP 连接,使攻击者无法窃取或篡改 TCP 数据流。

配置网络设备(如路由器、防火墙等)以过滤非法的 TCP 报文,例如使用基于规则的访问控制列表(ACL)等技术。


网络拓补

星型拓扑(Star Topology)

星型拓扑是⼀种常⻅的物理拓扑结构,其中所有计算机节点都通过集线器(Hub)或交换机(Switch)与⼀个中⼼节点连接。中⼼节点是⽹络的核⼼,⽤于控制和管理数据流量,因此这种拓扑结构通常被⽤于较⼩的局域⽹中。

总线拓扑(Bus Topology)

总线拓扑是⼀种线性拓扑结构,其中所有计算机节点都通过⼀条共享的通信线(Bus)连接。这种拓扑结构的优点是简单和低成本,但是当⼀台计算机节点故障时,整个⽹络的运⾏都会受到影响。

环型拓扑(Ring Topology)

环型拓扑是⼀种闭合的拓扑结构,其中每个计算机节点都与相邻的两个节点连接。这种拓扑结构的优点是可以避免数据碰撞和冲突,但是如果其中⼀个计算机节点出现故障,整个⽹络就会瘫痪。

树型拓扑(Tree Topology)

树型拓扑是⼀种层次结构的拓扑结构,其中多个星型拓扑通过根节点相连。这种拓扑结构的优点是可以提供更⾼的容错性和可靠性,但是需要更多的⽹络设备和更复杂的配置。

⽹状拓扑(Mesh Topology)

⽹状拓扑是⼀种复杂的拓扑结构,其中每个计算机节点都与多个其他节点相连,形成⼀个⼤型的⽹状结构。这种拓扑结构的优点是具有更⾼的容错性和可靠性,但是需要更多的⽹络设备和更复杂的配置。这些拓扑结构都有各⾃的优缺点和适⽤场景,⽹络设计⼈员需要根据实际需求和资源情况选择最合适的拓扑结构。

TCP 如何保证可靠传输?

它通过⼀系列的措施来确保数据包的可靠传输,包括序列号、确认应答、重传机制等

确认应答机制

TCP 传输数据时,每发送⼀个数据包都会要求接收⽅发送⼀个确认应答,以确认数据包已被接收。如果发送⽅没有收到确认应答,就会重新发送数据包,直到接收到确认应答为⽌。

假设有两台计算机 A 和 B 通过 TCP 协议进⾏数据传输。A 发送⼀个数据包给 B,B 收到数据包后会发送⼀个 ACK 确认应答给 A,表示已经成功接收到数据包。如果 A 在规定时间内没有收到 B 的确认应答,就会认为数据包丢失,会重新发送数据包,直到 B 发送确认应答为⽌。

序列号机制

TCP 在传输数据时,给每个数据包赋予⼀个序列号。接收⽅通过检查序列号,可以判断是否有数据包丢失或重复,从⽽实现数据包的可靠传输。

假设有两台计算机 A 和 B 通过 TCP 协议进⾏数据传输。A 发送⼀个数据包给 B,这个数据包的序列号为 100,B 收到数据包后会检查其序列号是否为 100,如果是,则将其存储在缓存区中,并向 A 发送⼀个 ACK 确认应答,表示已经成功接收到数据包。如果 B 收到的是序列号为 99 的数据包,则会将其丢弃,因为数据包的序列号不正确。

序列号是⽤来标识 TCP 连接中每⼀个传输的字节的,序列号按照字节的顺序依次递增,保证了字节的唯⼀性和有序性。序列号的初始值是随机的,每发送⼀个字节,序列号就会增加⼀个字节。滑动窗⼝⼤⼩是⽤来控制发送⽅发送数据的数量的,接收⽅通告给发送⽅的滑动窗⼝⼤⼩代表了接收⽅还能接收多少字节的数据,如果接收⽅的滑动窗⼝⼤⼩为 0,则发送⽅必须等待接收⽅通告新的窗⼝⼤⼩才能继续发送数据。

如果发送⽅的序列号是 1000,窗⼝⼤⼩为 2000,那么发送⽅可以发送序列号在 1000 到 2999 之间的数据。接收⽅接收到数据后,会确认已经成功接收的字节序列的最⼤序号,⽐如确认号为 2000,这意味着接收⽅已经成功接收了序列号在 1000 到 1999 之间的数据,因此发送⽅可以发送序列号在 2000 到 3999 之间的数据。

滑动窗⼝机制

TCP 在发送数据包时,采⽤滑动窗⼝机制来控制发送速度。发送⽅和接收⽅各有⼀个窗⼝,通过动态调整窗⼝⼤⼩,控制发送和接收数据包的速度,从⽽保证数据包的可靠传输。

滑动窗⼝是 TCP 实现流量控制和拥塞控制的重要机制。发送⽅和接收⽅都有⾃⼰的滑动窗⼝,发送⽅的滑动窗⼝⽤于控制⾃⼰的发送速率,接收⽅的滑动窗⼝⽤于告诉发送⽅⾃⼰可以接收的数据量

TCP 的滑动窗⼝⼤⼩是由接收⽅来决定的,接收⽅通过通告接收窗⼝⼤⼩来告诉发送⽅可以发送多少数据。接收⽅的接收窗⼝⼤⼩取决于两个因素:其⼀是接收⽅缓存区的剩余⼤⼩、其⼆是接收⽅的处理能⼒

接收⽅在接收到数据后,将已经成功接收的字节序列的最⼤序号告诉发送⽅。根据这个序号,发送⽅就可以计算出已经被成功接收的字节数。如果接收⽅的接收缓存区已经满了,那么接收⽅就会通告⼀个零窗⼝,表示当前⽆法接收数据。发送⽅会收到这个通告,就会停⽌发送数据,等待接收⽅通告⼀个⾮零窗⼝。当接收⽅接收缓存区有⾜够的空间时,就会通告⼀个新的窗⼝⼤⼩,从⽽允许发送⽅继续发送数据。

超时重传机制

TCP 在发送数据包时,会设置⼀个超时时间。如果在超时时间内没有收到确认应答,就会重新发送数据包,直到收到确认应答或达到最⼤重传次数为⽌。

超时重传是指在 TCP 协议中,当发送⽅发出⼀个数据包后,在规定的时间内没有收到确认应答(ACK),就会重新发送该数据包,直到收到确认应答为⽌。这样可以保证数据的可靠传输。

超时时间是动态调整的。发送端首先会将超时时间设为一个较小的值,然后根据网络的拥塞情况和丢包率等动态调整超时时间。如果在超时时间内没有收到对应的 ACK,则会重新发送该数据包,并将超时时间加倍。如果重传次数达到一定的限制,则会认为连接出现了问题,关闭连接

默认的最大重传次数在不同的实现中可能会有所不同,通常为 3 次到 7 次不等。这个值可以通过修改操作系统的 TCP 参数来调整。但是过高的重传次数会导致网络拥塞,因此应该谨慎调整

三次握手和四次挥手

TCP 三次握手和四次挥手是 TCP 协议在建立连接和关闭连接时的基本过程。它们是为了确保数据的可靠性和完整性。

三次握手的意义

  1. 防止已经失效的连接请求报文段到达服务器,造成错误。

  2. 保证客户端和服务器的初始序列号是同步的,避免后续的数据传输出现混乱。

  3. 确保双方的接收和发送能力正常,可以正常通信。

过程:

第一步,客户端发送 SYN 报文段:

客户端发送 SYN 报文段,告诉服务器它想要建立连接。SYN=1 表示这是一个连接请求报文段,客户端生成一个随机的序列号 seq=x,表示从 x 开始传输数据。

客户端生成的随机序列号 seq=x 可以是任意一个 32 位的整数。一般情况下,操作系统会根据特定的算法生成随机序列号,比如基于当前时间、进程 ID 等信息生成一个随机数,然后用这个随机数来作为初始的 seq 值。这样做是为了使每次连接请求的 seq 值都是随机的,从而增加攻击者猜测 seq 值的难度,提高了连接的安全性。

   客户端                      服务器     |                          |     |  SYN = 1, seq=x          |     |  --------------------->  |     |                          |复制代码
复制代码

第二步,服务器回复一个 SYN+ACK 报文段:

服务器收到连接请求后,回复一个 SYN+ACK 报文段。其中 SYN=1 表示这是一个连接请求报文段,ACK=1 表示确认客户端的请求报文已经收到,服务器生成一个随机的序列号 seq=y,表示从 y 开始传输数据,同时也确认了客户端的序列号 seq=x+1(因为第 1 步中客户端的序列号为 x,所以服务器的确认序列号为 x+1)。

在接收到连接请求报文段之后,服务器会生成自己的随机序列号,并把这个序列号放入 SYN+ACK 报文段中返回给客户端,以表示服务器已经接受了客户端的请求,可以进行下一步的确认操作。(客户端和服务器生成的随机序列号 seq=x 和 seq=y,主要是为了标识数据传输中的字节流,并且保证每个报文段的序列号都是唯一的、随机的、不可预测的,从而提高连接的安全性和可靠性

  客户端                        服务器     |                           |     |  SYN = 1, seq=x           |     |  -----------------------> |     |                           |     |  SYN+ACK, seq=y,          |     |  ack=x+1                  |     |  <----------------------- |     |                           |复制代码
复制代码

第三步,客户端回复一个 ACK 报文段:

客户端收到服务器的 SYN+ACK 报文段后,再回复一个 ACK 报文段,表示客户端确认服务器的确认报文已经收到,客户端生成一个随机的序列号 seq=x+1,表示从 x+1 开始传输数据。

  客户端                        服务器     |                           |     |  SYN = 1, seq=x           |     |  -----------------------> |     |                           |     |  SYN+ACK, seq=y,          |     |  ack=x+1                  |     |  <----------------------- |     |                           |     |  ACK, seq=x+1,            |     |  ack=y+1                  |     |  -----------------------> |     |                           |复制代码
复制代码

四次挥手的意义

  1. 客户端向服务器发送 FIN 请求后,如果服务器还有未发送的数据,可以在回复 ACK 报文后继续发送数据,保证数据的完整性。

  2. 服务器可以在发送 FIN 请求后等待一段时间,等待已经发送的数据被客户端确认接收,保证数据的可靠性。

  3. 客户端和服务器都需要等待一段时间(一般为 2MSL),以确保对方已经接收到 FIN 请求和 ACK 确认,避免数据丢失和重传。

过程:

第一步:客户端发送关闭连接请求

客户端发送一个 FIN(终止)消息给服务端,表示它不再需要连接。这个消息的序列号是客户端最后一个发送的消息的序列号,因为客户端不会再发送数据了。

客户端               服务端  |                    |  |-----FIN----->      |  |    (FIN_WAIT_1)    |  |                    |复制代码
复制代码

第二步:服务端回复确认消息

服务端接收到 FIN 消息后,会发回一个 ACK(确认)消息,告诉客户端已经收到了关闭请求。ACK 消息的序列号是服务端最后一个接收的消息的序列号,同时确认客户端的 FIN 消息,ACK 消息的确认号为客户端的序列号+1。

客户端               服务端  |                    |  |-----FIN----->      |  |    (FIN_WAIT_1)    |  |                    |  |<----ACK------------|  |    (CLOSE_WAIT)    |  |                    |复制代码
复制代码

客户端接收到服务端的 ACK 数据包后,进入 FIN_WAIT_2 状态,等待服务端发送关闭请求

客户端               服务端  |                    |  |-----FIN----->      |  |    (FIN_WAIT_1)    |  |                    |  |<----ACK------------|  |    (CLOSE_WAIT)    |  |                    |  |                    |  |    (FIN_WAIT_2)    |  |                    |复制代码
复制代码

第三步:服务端发送关闭连接请求

服务端也需要关闭连接,所以它会发送一个 FIN 消息给客户端,序列号是服务端最后一个发送的消息的序列号,确认号为客户端的序列号+1。

客户端               服务端  |                    |  |-----FIN----->      |  |    (FIN_WAIT_1)    |  |                    |  |<----ACK------------|  |    (CLOSE_WAIT)    |  |                    |  |                    |  |<----FIN-------------|  |    (LAST_ACK)      |  |                    |复制代码
复制代码

第四步:客户端回复确认消息

客户端接收到服务端的 FIN 数据包后,发送 ACK 数据包,表示已经接收到服务端的关闭请求,并进入 TIME_WAIT 状态,等待 2MSL 时间后进入 CLOSED 状态。

客户端               服务端  |                    |  |-----FIN----->      |  |    (FIN_WAIT_1)    |  |                    |  |<----ACK------------|  |    (CLOSE_WAIT)    |  |                    |  |                    |  |<----FIN-------------|  |    (LAST_ACK)      |  |                    |  |-----ACK----------> |  |    (TIME_WAIT)     |  |                    |复制代码
复制代码

服务端接收到客户端的 ACK 数据包后,进入 CLOSED 状态,连接关闭

客户端               服务端  |                    |  |-----FIN----->      |  |    (FIN_WAIT_1)    |  |                    |  |<----ACK------------|  |    (CLOSE_WAIT)    |  |                    |  |                    |  |<----FIN-------------|  |    (LAST_ACK)      |  |                    |  |-----ACK----------> |  |    (TIME_WAIT)     |  |                    |  |                    |  |<----ACK-------------|  |     (CLOSED)       |  |                    |复制代码
复制代码

客户端等待 2MSL 时间后,进入 CLOSED 状态,连接关闭

客户端               服务端  |                    |  |-----FIN复制代码
复制代码

这些设置可以保证 TCP 协议的可靠性和完整性。TCP 协议是面向连接的协议,每个连接都需要经过三次握手建立,保证连接的正常建立和通信。在关闭连接时,四次挥手可以保证数据的完整性和可靠性。这些设置可以避免数据传输出现错误和丢失,保证 TCP 协议的可靠性和稳定性。

其他重要知识补充:

时间戳选项:TCP 在头部中添加⼀个选项字段,⽤于记录当前数据包发送的时间戳。时间戳选项可以让发送⽅根据时间戳来计算序列号,从⽽增加序列号的范围。

时间窗⼝机制:TCP 还引⼊了时间窗⼝机制,⽤于限制发送⽅在⼀个时间段内发送的数据包数量。发送⽅通过计算接收⽅的接收窗⼝⼤⼩,来确定当前可以发送的数据包数量。如果接收⽅的接收窗⼝很⼩,说明缓存区已经满了,此时发送⽅就需要等待接收⽅确认应答之后再继续发送数据包。这样可以避免发送⽅⼀次性发送过多的数据包,从⽽减少序列号的重复。

拥塞控制机制: 来避免⽹络拥塞,保证⽹络的稳定性和可靠性。拥塞控制的实现主要分为两个⽅⾯:慢启动和拥塞避免。

慢启动机制是指在 TCP 连接刚建⽴时,发送⽅先发送少量数据,然后根据对⽅接收的情况逐渐增加发送量,以此来适应⽹络的传输速度

步骤:

1、发送⽅每经过⼀个往返时间(Round-Trip Time,RTT),就将拥塞窗⼝的⼤⼩增加 1,即窗⼝⼤⼩变为原来的 1 + 1/mss(mss 表示 TCP 报⽂段的最⼤⻓度)

2、如果⽹络出现拥塞,接收⽅会发送⼀个重复确认(Duplicate Acknowledgement),表示某个报⽂段已经被接收⽅接收了多次。当发送⽅连续收到 3 个重复确认时,就意味着⽹络可能已经发⽣拥塞,于是发送⽅将慢启动阈值设置为当前拥塞窗⼝的⼀半,并将拥塞窗⼝的⼤⼩重新设置为慢启动阈值,重新开始慢启动阶段。

TCP 协议需要解决什么问题?

1、如何将数据包从源主机传输到⽬标主机

TCP 通过 IP 协议实现⽹络互联,它将数据划分成多个数据包,每个数据 包都有⼀个 TCP 头和⼀个 IP 头。TCP 使⽤IP 地址来确定源和⽬的主机, 使⽤端⼝号来确定⽬标进程

2、如何确定数据包传输时的路由路径

在路由选择⽅⾯,TCP 使⽤IP 协议提供的 路由选择功能来确定数据包的路由路径。为了保证数据包的可靠传 输

3、确保数据包可靠传输

TCP 通过分段将数据分成更⼩的数 TCP 通过分段将数据分成更⼩的数据 包进⾏传输,以确保可靠性和有序性。在数据传输过程中,TCP 还能够检测并纠正数据传输中出现的错误据包进⾏传输,以确保可靠性和 有序性。在数据传输过程中,TCP 还能够检测并纠正数据传输中出现的错误

TCP 通过使⽤校验和机制来纠正数据包。每个 TCP 报⽂段都有⼀个 16 位 校验和字段,⽤于检查报⽂段中的错误。在发送端,TCP 计算数据段 的校验和并将其添加到数据包头部。在接收端,TCP 重新计算接收到 的数据段的校验和,如果检测到错误,则丢弃该数据段并请求发送端 重新发送该数据段

假设 TCP 报⽂段中的数据为:0x4500 003c 1c46 4000 4006 b2a3 ac10 0a63 ac10 0a0c,

TCP 头部信息为:0x4d2f 71b0 0000 0000 8002 ffff 29cc 0000 0204 05b4 0000。

则 TCP 计算出的校验和为:0xbce8。该校验和与 数据包⼀起发送到接收⽅,接收⽅同样按照相同的算法计算数据包的 校验和,并将其与发送⽅传来的校验和进⾏⽐较。如果两个校验和相等,则表明数据传输过程中没有发⽣错误

计算方式:

首先将 TCP 头部和 TCP 数据字段看作一个连续的字节序列。 将该字节序列划分为 16 位的块,如果最后剩下的不足 16 位,则在末尾添加 0,使得该字节序列的长度为偶数个字节。 将所有 16 位块进行二进制反码求和,将得到一个 16 位的结果。 将上一步得到的 16 位结果再次取反得到最终的 TCP 校验和值。

TCP 结构

TCP 报⽂段头部:TCP 协议将需要传输的数据分成多个 报⽂段,每个报⽂段都包含⼀个 TCP 报⽂段头部,TCP 报⽂段头部 包含了 TCP 协议所需的各种控制信 息,如源端⼝号、⽬标端⼝号、 序列号、确认号、窗⼝⼤⼩等。

1 源端⼝号(Source Port)和⽬标端⼝号(Destination Port): 分别指发送端和接收端的端⼝号。TCP 协议使⽤端⼝号来区分不同的 应⽤程序。

2 序列号(Sequence Number):指本次传输数据的第⼀个字 节在数据流中的序列号。⽤来保证接收⽅可以正确地重组数据流。

3 确认号(Acknowledgment Number):指接收端期望下⼀个 收到的字节在数据流中的序列号。⽤来实现可靠传输,接收⽅发送⼀ 个 ACK 报⽂确认已经成功接收到数据。

4 数据偏移(Data Offset):指 TCP 头部的⻓度,以 4 字节为单 位。TCP 头部⻓度最⼩为 20 字节,最⼤为 60 字节。

5 保留(Reserved):暂时未使⽤,保留字段。

6 控制位(Flags):包含了 TCP 协议的⼀些控制信息,如 URG、ACK、PSH、RST、SYN、FIN 等标志位。这些标志位⽤来控制 TCP 连接的建⽴、维护和释放。

7 窗⼝⼤⼩(Window Size):表示接收⽅可以接收的字节数 量。⽤来实现流量控制。

8 校验和(Checksum):⽤于检测 TCP 报⽂段是否出现了错 误。TCP 报⽂段头部和数据部分的校验和都要计算,如果出现了错 误,接收⽅会丢弃这个报⽂段。

9 紧急指针(Urgent Pointer):⽤于实现紧急数据传输。紧急 指针指出了紧急数据在数据流中的位置。

10 选项(Options):可选字段,包含了⼀些 TCP 协议的可选参 数,如时间戳、最⼤报⽂段⻓度等

数据部分:TCP 协议的 数据部分是需要传输的数据,其 ⼤⼩不⼀定是报⽂段的整数倍, 因此需要进⾏分段操作。

TCP 报⽂段尾部:TCP 报⽂段尾部是 TCP 协议为了保证传 输数据的可靠性⽽添加的冗余校 验信息,主要⽤于校验数据是否 在传输过程中发⽣了损坏或丢失

WireShark

要分析和解读 TCP 报⽂,你需要使⽤⽹络分析⼯具(例如 Wireshark),并且需要⼀些⽹络协议和 TCP 报⽂的基础知识。以下是 ⼀个⼤致的步骤:

1 捕获⽹络数据包:打开 Wireshark,选择正确的⽹络接⼝ (例如 Wi-Fi 或以太⽹),开始捕获数据包。

2 过滤出 TCP 报⽂:使⽤过滤器过滤出 TCP 报⽂。可以使⽤ 过滤器表达式 "tcp" 或者过滤源、⽬的 IP 和端⼝号等信息。

3 选中⼀个 TCP 报⽂:在捕获到的 TCP 报⽂列表中选择⼀个 TCP 报⽂。

4 解读 TCP 报⽂头部:在 Wireshark 中,可以展开 TCP 报⽂的头部部分,并查看每个字段的值。例如,源端⼝和⽬的端⼝、序列 号、确认号、标志位、窗⼝⼤⼩等信息。

5 解读 TCP 数据:在 Wireshark 中,可以查看 TCP 报⽂的数据部分,并尝试解析出其中的应⽤层数据。例如,如果 TCP 报⽂是 HTTP 请求,可以在数据部分中找到 HTTP 请求头和主体。

需要注意的是,对于加密的 TCP 报⽂,Wireshark 可能⽆法解析出应⽤层数据。此时,你需要了解加密算法和密钥,才能够解密出其中的数据

通过分析数据包可以确定⽹络是否存在异常情况,如⽹络延迟、丢包 等问题,可以采⽤以下⽅法:

1 查看时延(Delay):时延是指从源主机发送数据包到⽬的 主机接收数据包的时间差。可以通过抓包分析的⽅式,查看数据包的 时间戳,并计算数据包到达时间与发送时间的差值,得到数据包的时 延。如果某些数据包的时延过⼤,就可能存在⽹络延迟的问题。

2 检查丢包(Packet loss):丢包是指数据包在传输过程中未 能到达⽬的地。可以通过抓包分析的⽅式,查看数据包的序列号和确 认号,以及 TCP 报⽂段头部的窗⼝⼤⼩和校验和等信息,判断数据包 是否有丢失。如果某些数据包的序列号和确认号不连续,就可能存在 数据包丢失的问题。

3 检查拥塞(Congestion):拥塞是指⽹络中的流量过⼤,导 致⽹络性能下降。可以通过抓包分析的⽅式,查看 TCP 报⽂段头部的 窗⼝⼤⼩和拥塞窗⼝⼤⼩,以及 TCP 报⽂段的时间戳、序列号和确认 号等信息,判断是否存在⽹络拥塞的问题。

4 查看重传(Retransmission):重传是指发送⽅未收到确认消 息,⽽重新发送数据包。可以通过抓包分析的⽅式,查看 TCP 报⽂段 头部的序列号和确认号,以及 TCP 报⽂段的时间戳、校验和等信息, 判断是否存在数据包重传的问题

使用 WireShrak 分析 TCP 协议

前提准备:

一台虚拟机,没有的可以去阿里云申请一个几小时免费云服务器


一个 wireShark,官网有免费的,不需要去别处下载!!!

Wireshark · Go Deep 在最下面



分析 TCP 三次握手 和 四次挥手

三次握手


注意想要点击连接,在点击结束






四次挥手

点击捕获按钮,在连接状态的虚拟机或者服务器。在输入虚拟机或者服务器输入(exit)。或者叉掉 Xshell 连接等等。注意这是服务器请求客户端断开连接!!

通过上述步骤,点开流量图,便可找到挥手过程的蛛丝马迹


当然也可以通过简单百度来查看 TCP 连接


简单包分析:

553	2023-03-18 15:46:47.998179	36.152.44.96	192.168.1.8	TCP	66	443 → 6241 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1452 WS=32 SACK_PERM复制代码
复制代码
  • 时间戳:2023-03-18 15:46:47.998179

  • 源 IP 地址:36.152.44.96

  • 目的 IP 地址:192.168.1.8

  • 协议类型:TCP

  • 数据包长度:66 字节

  • TCP 标志:[SYN, ACK],表示 TCP 三次握手的第二个阶段

  • 源端口号:443

  • 目的端口号:6241

  • TCP 序号:Seq=0,表示发送方传输的数据字节流的序号

  • TCP 确认号:Ack=1,表示接收方期望下一个字节的序号

  • TCP 窗口大小:Win=8192,表示发送方缓冲区大小

  • TCP 最大报文段长度:MSS=1452,表示 TCP 连接双方所支持的最大报文段长度

  • TCP 窗口扩展选项:WS=32,表示 TCP 连接双方启用了窗口扩展功能

  • TCP SACK Permitted:SACK_PERM,表示 TCP 连接双方启用了 SACK (Selective Acknowledgment) 选项

SYN 表示请求建立连接,ACK 表示确认收到之前一个数据包,因此这个数据包是 TCP 三次握手的第二个阶段,表示客户端已经收到服务端发送的 SYN 包并发送了 ACK 包作为应答,完成了连接的第二个阶段,即建立连接

1711	2023-03-18 15:46:48.642308	20.205.115.81	192.168.1.8	TCP	60	443 → 6231 [RST, ACK] Seq=6357 Ack=612 Win=0 Len=0复制代码
复制代码
  • 时间戳:2023-03-18 15:46:48.642308

  • 源 IP 地址:20.205.115.81

  • 目的 IP 地址:192.168.1.8

  • 协议类型:TCP

  • 数据包长度:60 字节

  • TCP 标志:[RST, ACK],表示 TCP 连接重置

  • 源端口号:443

  • 目的端口号:6231

  • TCP 序号:Seq=6357,表示发送方传输的数据字节流的序号

  • TCP 确认号:Ack=612,表示接收方期望下一个字节的序号

  • TCP 窗口大小:Win=0,表示发送方缓冲区大小

  • TCP 数据长度:Len=0,表示本次 TCP 数据传输的数据长度为 0 字节

其中,RST 表示重置连接,ACK 表示确认收到之前一个数据包,因此这个数据包是 TCP 连接重置的包,表示当前的 TCP 连接已经被重置,这种情况通常是由于网络故障或应用程序主动关闭连接引起的,需要进一步分析原因并重新建立连接。

143	2023-03-18 15:46:46.180381	202.89.233.96	192.168.1.8	TCP	1506	[TCP Out-Of-Order] 443 → 6215 [ACK] Seq=11593 Ack=5862 Win=4194560 Len=1452复制代码
复制代码
  • TCP 标志:[ACK],表示确认收到之前一个数据包

  • TCP Out-Of-Order,表示收到了乱序的 TCP 数据包

ACK 表示确认收到之前一个数据包,因此这个数据包是 TCP 的确认包,表示接收方已经收到发送方发送的数据包,并发送了确认包作为应答。TCP Out-Of-Order 表示收到了乱序的 TCP 数据包,通常发生在数据包在传输过程中被重排序或丢失后被重传,需要进一步分析原因并对数据包进行重新排序。

151	2023-03-18 15:46:46.180453	192.168.1.8	202.89.233.96	TCP	66	[TCP Dup ACK 150#1] 6215 → 443 [ACK] Seq=5862 Ack=15727 Win=263424 Len=0 SLE=18631 SRE=19805复制代码
复制代码
  • TCP 标志:[TCP Dup ACK 150#1],表示重复的 TCP 确认包

TCP Dup ACK 表示收到了重复的 TCP 确认包,通常发生在网络中出现数据包丢失时,接收方尝试重复发送之前已经发送过的确认包,以通知发送方需要重新传输数据包。在这个包中,确认号为 15727,说明接收方期望下一个字节的序号是 15727,而 Seq=5862 表示发送方传输的数据字节流的序号,说明发送方传输的数据包中序号 5862 的数据包可能在传输过程中丢失了。此时,接收方向发送方发送重复的 TCP 确认包,以便发送方重传丢失的数据包。

261	2023-03-18 15:46:47.005075	192.168.1.8	23.49.60.176	TCP	66	[TCP Retransmission] [TCP Port numbers reused] 6229 → 443 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 WS=256 SACK_PERM复制代码
复制代码
  • TCP 标志:[TCP Retransmission] [TCP Port numbers reused],表示重传的 TCP SYN 包,同时端口号被重新使用

TCP Retransmission 表示重传的 TCP 包,通常发生在网络中出现数据包丢失时,发送方尝试重新传输之前已经传输过但是没有得到确认的数据包。在这个包中,TCP SYN 标志表示建立连接请求,Seq=0 表示发送方传输的数据字节流的序号。同时,TCP Port numbers reused 表示在端口号被重新使用,可能是之前的连接已经被关闭,新的连接需要使用该端口号。

总结:

可能有人就会疑惑? 就这就这。我看完确实能看 TCP 三次握手和四次挥手。但除了对它们有了更深的了解还有什么帮助呢? 其实我觉得现阶段好像是这样,但是我们是不是可以通过 举一反三 是不是就可以通过这个工具来分析 相关 TCP 连接 那一步出现问题了?例如下面的报文我们连接请求发送过去,却端口拒绝连接了。那是不是可以简单的判断是对方那边做了限制。虽然下面的例子(由于端口错误)或许不需要我们通过工具就可以很简单的解决。

用户头像

Java你猿哥

关注

一只在编程路上渐行渐远的程序猿 2023-03-09 加入

关注我,了解更多Java、架构、Spring等知识

评论

发布
暂无评论
TechBits | TCP 使用 WireShark 进行抓包_Java_Java你猿哥_InfoQ写作社区