[Wireshark Lab v8.1] Lab: TCP

[Wireshark Lab v8.1] Lab 翻译与解题.

以下实验步骤均来自实验指导手册。
实验指导手册下载地址:Jim Kurose Homepage (umass.edu)

Lab TCP

这个Lab我们将使用和测试TCP协议, 通过从计算机到远程服务器下载一个150KB大小的文件(包括爱丽丝梦游仙境的内容)抓取TCP发送和接受的数据报. 我们能够学到TCP使用序列号和确认号来确保数据的可靠传输, TCP的拥塞控制算法--慢开始和拥塞避免, 以及接收窗口流量控制机制. 同样会简单考虑TCP连接建立流程, 及主机间TCP连接的性能(吞吐量和往返时间RTT)

在进行本次实验之前, 你应该需要重新回顾第3.5和3.7章的内容.

1. 捕获从你的电脑向远程服务器发送的TCP传输报文

在正式的对TCP进行探索之前, 我们先使用 Wireshark 获取一个TCP传输报文. 可以通过访问一个Web页面, 它允许你将计算机本地的文件通过HTTP POST请求上传到远程Web服务器上(书中2.2.3节). 之所以使用POST请求而不是GET请求是由于我们想要在计算机间传输大量的数据. 在上传的过程中使用 Wireshark 记录下来计算机发送和接收的TCP报文.

操作步骤如下:

  • 打开浏览器, 输入 http://gaia.cs.umass.edu/wireshark-labs/alice.txt 获取爱丽丝梦游仙境的ASCII拷贝. 以.txt后缀存储到计算机上

  • 跳转到 http://gaia.cs.umass.edu/wireshark-labs/TCP-wireshark-file1.html

  • 你将会看到如图的内容
    p1

  • 点击Browse按钮, 选中刚才下载好的文本文件, 先不要点击上传按钮

  • 现在启动 Wireshark 开始抓包(如果忘记操作可以查看 Wireshark Lab)

  • 返回浏览器, 按下上传按钮, 文件将会被上传到 gaia.cs.umass.edu 服务器上. 文件上传成功后浏览器将会显示一个简短的恭喜信息
    p2

  • 停止抓包

如果你无法在线运行 Wireshark 抓包, 你可以下载作者的计算机通过上述执行抓到的trace文件. 同时, 当回答下面问题时, 就算你可以进行自己的抓包, 现有的trace文件也会很有用.

2. 查看抓到的TCP包

在详细分析TCP连接之前, 我们先来对trace文件进行概要分析

首先从本地上传文件到 gaia.cs.umass.edu 服务器上的 HTTP POST 请求开始, 打开 Wireshark 软件, 并选中这条HTTP消息. 你的 Wireshark 显示应该如图3所示.

p3

有几件事情值得注意:

  • 应用层的 HTTP POST 消息的请求体包含了文本文件的内容, 这是一个大小超过152K字节的大文件. 尽管它不是过分的大, 但也使得这个HTTP消息超过一个TCP段能够承载的大小
  • 实际上, 如上图 Wireshark 窗口展示的那样, HTTP POST消息被106个TCP段来承载. 通过图中红色箭头所显示的那样. 如果你查看的更仔细的话, 你可以发现 Wireshark 也十分友好, 在图中的trace里显示第一个承载POST消息TCP段是报文#4, 承载消息的第二个TCP段是报文#5, 等等.

现在查看TCP报文段来进行一些实践吧.

  • 首先, 对 Wireshark 应用“tcp”过滤(小写, 无双引号, 如果你的输入正确, Wireshark将会出现一个下拉选项列表). 软件的显示应如下图所示, 在图中我们可以注意到 TCP段的SYN位设置为了1. 这是向 gaia.cs.umass.edu 建立TCP连接的三次握手并最终发送 HTTP POST消息和文本文件的第一个TCP报文. 同样可以注意到 SYN+ACK 报文(三次握手的第二步), 以及携带POST消息和文本文件开始的TCP段(如上所述, 报文#4). 当然, 如果你使用的是自己的trace文件, 报文编号将会不同, 但它们的逻辑行为将与图中相同.

p4

使用自己或提供的trace来回答下列问题

  1. 客户端计算机传输文本文件到 gaia.cs.umass.edu 所使用的IP地址和TCP端口号是多少? 为了回答该问题,最简单方式就是选中 HTTP报文, 并在“报文头详情窗口”中打开承载 HTTP报文的TCP包.
  2. gaia.cs.umass.edu 的IP地址是多少? 在这次连接中接受和发送TCP段的TCP端口号是多少?

当然本次lab是关于TCP协议而非HTTP的, 现在切换 Wireshark 的“捕获包列表”窗口, 显示承载HTTP消息的TCP段, 这正是我们要找的, 你的主机和 gaia.cs.umass.edu 之间通信的TCP段

3. TCP基础

根据TCP报文段回答下列问题:

  1. 用来建立客户端到服务器主机之间的TCP SYN段的序列号是多少?(注意是TCP段中携带的序列号, 不是Wireshark窗口中定义的报文编号. 注意TCP和UDP并没有“报文编号”这个概念, 序列号也不是这次TCP会话的相对传输编号.) 这个TCP段中, 标记成为SYN段的标志是什么? 这次会话TCP接收方允许使用SACK“Selective Acknowledgments”么(允许TCP以类似于“选择重复”接收者的方式运行, 见书中3.4.5节)
  2. 由 gaia.cs.umass.edu 发送给客户端主机响应SYN包的SYN+ACK包中的序列号是多少? 标记该段是SYN+ACK段的标志是什么? 该报文的响应字段的值是什么? 服务端主机是如何决定该值的?
  3. 包含HTTP POST消息头的TCP段的序列号是多少? 注意为了找到POST报文的头的包, 你需要深入 Wireshark 包数据窗口查看报文的内容, 在数据显示中找到 “POST” ASCII文本. 这个TCP段中的负载(数据)部分包含了多少字节的数据?
  4. 考虑承载HTTP “POST” 字段的TCP段作为在TCP连接的数据传输的第一个报文
  • 在数据传输阶段中 TCP 连接在什么时间发送第一个报文(包含HTTP POST的)
  • 第一个包含数据的报文的ACK是在什么时间被接收的
  • 第一个数据报文的RTT是多少
  • 第二个有数据的TCP包和他的ACK的RTT是多少
  • 第二个有数据包的ACK被接收到后, EstimatedRRT(书中3.5.3节) 的值是多少, 假设在接收到第二个数据包的ACK之后进行计算, EstimatedRTT的初始值是第一个数据报RTT的测量值. 计算公式使用书中242页的等式, 其中a=0.125
    注意: Wireshark 有一个很好用的特性, 可以画出每个发出TCP报文的RTT. 在“捕获报文列表”中选中发送给服务器的TCP段, 之后选中Statistics->TCP Stream Graph->Round Trip Time Graph
  1. 前四个数据报文的长度(首部加附载)是多少?(给出的trace中, TCP报文长度不会超过1480字节, 这是因为获取trace的计算机的最大IP报的长度被设置为1500字节, 且TCP/IP头数据最小为40字节. 1500是经典的因特网IP数据报的最大长度)
  2. 在前四个TCP数据报文中, 由服务器向客户端设置的最小数量的可用缓冲区空间是多少? 是否由于接收缓存区大小限制前四个TCP数据报的发送?
  3. trace文件中是否有重传的报文? 你需要检查什么来回答该问题
  4. 客户端发送给服务器的前十个数据传输报文中, 在ACK包里通常有多少数据被确认了. 你能识别出在这十个数据报中是否存在, 接收端在ACK其他所有收到的报文(见书中表3.2)的情况么
  5. TCP连接的吞吐量是多大(单位时间传输的字节数)? 解释如何计算该值.

4. 实战TCP拥塞控制

现在让我们演示单位时间中从客户端发送到服务器上的数据量. 相较于(无趣的)从 Wireshark 窗口中计算二进制数据, 我们可以使用 Wireshark TCP 图形化工具--时序图, 来展示数据

  • 在“捕获报文列表”中选中一个客户端发送的TCP报文, 之后选中选中Statistics->TCP Stream Graph->Time-Sequence-Graph(Stevens) 你应该能看到类似图中的图表, 这是根据给出的trace文件中的数据构成的. 你可能需要对图中轴上的间隔进行拉伸,缩放与平移来使得你的图表与给出的图表相似.

p5

在图中, 每个点表示发送的一个TCP报文, 绘制出发出的报文的序列号随着时间的变化. 注意一系列的点被堆叠在其他的点上表示一系列的报文(也被叫做报文的“舰队”)被客户端“back-to-back”(我理解就是连续)的发送

根据抓取的TCP报文回答下列问题:

  1. 使用时序图绘制工具来观察从客户端发送给服务器的序列号随着时间的变化. 考虑报文“舰队”的发送间隙t=0.025,0.053,0.082和0.1. 分析TCP分别是处在慢开始阶段, 拥塞避免阶段或是其他阶段.
  2. 报文“舰队”显然具有周期性, 这个周期有什么特点?
  3. 对于你抓取的TCP报文回答上述两个问题.

解答:

首先我们在HTTP报文中可以看到有很多TCP包组成了HTTP消息内容, 找到第一个报文的#开头编号, 去掉http filter, 找到该编号对应报文就是第一个TCP数据包, 根据端口号和Wireshark的连线可以找到打开TCP连接的SYN包, 我们来看一下TCP报文头的内容

|16位源端口|16位目的端口|
|32位传输编号|
|32位确认编号|
|4位首位长度|6位保留|URG|ACK|PSH|RST|SYN|FIN|16位窗口大小|
|16位校验和|16位紧急指针|

  1. 对照格式可以发现传输编号字段并不为0, 但解析后相对值为0, 并且SYN包的SYN位为1, 其次是SACK, 它是TCP的一个额外选项, 该字段附加在选项头中, 我发出的SYN包设置了该字段. (这里有一个我一直混淆的概念, 传输编号表示的是当前传输的数据字节的编号, 而不是发送出的包的编号, 比如我当前的包发送了10字节的数据, 后续的传输编号就会增加10)
  2. 随后跟随的包就是服务端响应的SYN+ACK包, 它的传输编号也不为0, 但响应字段并没有与ACK包中的传输编号对应, 而是产生了一个新值, 后续客户端传输的编号都跟随了该新值.
  3. 在三次握手后第一个包, 包含了HTTP报文头内容, 且只包含了报文头, 没有HTTP请求体的内容
  4. 关于如何找包的对应ACK, 可以找端口号相反, ACK对应SEQ的包.
  • 时间: 该报文发送时间与SYN包发送时间间隔了0.3毫秒, 主要的耗时是发出SYN到接受SYN+ACK的时延, 也就是1RTT, 之后发送完第三次握手包后续就可以直接发数据包了.
  • 针对该数据包的ACK接受时间, 大约延后了0.287851.
  • 第二个数据报的RTT为0.288565
  • EstimatedRTT = (1 - a) × EstimatedRTT + a × SampleRTT
  1. 819(http 头), 1454(http 体, 因为SYN+ACK设置了最大报文大小为1400)
  2. 接受窗口也是由SYN+ACK包确立的, 我的大小为28960, 因此不会影响前4个数据包的发送.
  3. 关于检查报文的重传, 我觉得可以从发送端Seq大小是否降低判断, 在我的trace中没有发现该现象
  4. 发送端的Seq为[1,754,2142,3530,4918,6306,7694,9082,10470,11858,], 服务端ack为[754,2142,3530,4918,6306,SACK,SACK,10470,]可见一个发送对应一个ack, 如果出现乱序则通过SACK解决.
  5. 可以在统计里画吞吐量图查看, 如果要求手算, 我认为可以有两种算法, (算/不算握手和挥手)时间/总数据大小.

然后是使用时序图, 这里我自己抓出来的包阶段变化没有那么多, 只有慢开始和拥塞避免, 且发送间隙也是按照1RTT来的.

但当分析给出的trace的时序图时, 又产生了一些疑惑, 总体上看, 发送“舰队”的大小增长还是满足指数增张的, 且它们的间隔满足RTT规律, 但中间会有几个零散的报文发出, 是什么控制它们的发出呢? 猜测有可能是接受到ACK后填充发送窗口.

再补充说明两点:

  1. 打开绘制窗口后可能看不到数据, 选择Switch Direction进入发送方向的统计,
  2. Stream, 这个概念是 Wireshark 附加的, 表示区分当前 trace 中, TCP不同的链接传输的数据.

附一张我抓到trace的时序图.

p6

posted @ 2022-05-26 21:54  新新人類  阅读(1567)  评论(0编辑  收藏  举报