Wireshark网络分析的艺术(txt+pdf+epub+mobi电子书下载)


发布时间:2020-11-15 09:08:52

点击下载

作者:林沛满

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Wireshark网络分析的艺术

Wireshark网络分析的艺术试读:

前言

Wireshark已经用不着我来做广告了,它早已被多家权威机构评为最佳嗅探器,从事网络工作的工程师都知道它。即便我如实地列举它的种种好处,都涉嫌违反广告法。这也许就是我的上一本书《Wireshark网络分析就这么简单》得以多次重印的原因,是神器总会流行的。读者的评价也超乎我的想象,随手复制两条书评过来满足一下我的虚荣心:“这本书陪了我几个深夜。没有大部头的催眠和艰涩,每一节都精炼易读,和咖啡一样令人上瘾。我是网络小新人,但是不觉得特别难,很容易顺下来。里面很多干货,厚积薄发,都是实际环境中的情况。畅快淋漓读完大呼不过瘾,搜了一下作者就这一本书。遗憾!”——亚马逊读者“这本书是我2014年读过的10本好书之一,如果说我对这本书有什么不满的话,就只有一个:书写薄了,意犹未尽,读着完全不过瘾呀呀呀。或许这本书浅显易懂、幽默风趣的语言风格让你在无障碍阅读的同时,会让你有一种这书太浅、适合初学者的感觉,但是这本书实际上是越读越有味道,我就读了好几次。”——豆瓣读者

既然有这么多人喜欢,我有什么理由不再写一本呢?于是就有了这本新书。虽然我在写稿这件事情上的拖延症不亚于洗碗,不过读者们的鼓励显然起了作用,最后收笔时间只比原计划晚了6个月。和老读者们期望的一样,它是上一本书的延续,尤其是在写作风格上。不同之处在于这一本不再着重分析基础协议,而更专注于解决现实问题。另外,考虑到现在手机上网日趋流行,本书也增加了一些手机App的内容,相信读者会喜欢。

就如我常在培训课上所讲的,学会Wireshark这个软件只需要几个小时,掌握一个网络协议也用不了几天,而养成解决问题的思路却需要经年累月的练习和思考。本书正提供了很多练习和思考的机会,本书30多篇文章,几乎都用了Wireshark来分析网络包。我希望每一篇都能让读者产生这样的感触:“啊,原来Wireshark还可以这样用!”“读完整本书,自然而然会形成看包的习惯和思维方式。本书组织结构

就像时尚女郎每天都在看包包一样,我也每天都在看包。看到有趣又有价值的,就会记录下来,久而久之就形成了这本书。因此它有别于包罗万象的网络教材,而更像一个技术博客的合集。

全书根据素材来源可分为四个部分。

第一部分的选材来自老读者的咨询,相信很有代表性,说不定其他读者也会遇到。

·《Linux为什么卡住了》分析了登录Linux时卡顿10秒钟的现象。虽然我是Linux领域的菜鸟,但是仍然可以用Wireshark发现原因并解决它。

·《像福尔摩斯一样思考》讲述的是如何根据网络包中的蛛丝马迹,找到被人为掩盖的线索。自己从网络包推理出来的东西,往往比对方提供的文档更可靠。

·《一篇关于VMware的文章》介绍了一位读者在VMware知识库发现的文章。我们纯粹依靠协议分析,找到了这篇文章的真正内涵,最后再用Wireshark看包加以确认。

·《来点有深度的》是在上一篇的基础上,通过发散思维,向读者“灌输”了一些相关的TCP知识。个人觉得TCP协议理解到这个深度就足够应付大多数性能问题了。

·《三次握手的小知识》是应某论坛网友的要求而写的TCP握手科普,分享了一些用Wireshark来处理握手问题的小经验,顺便演示了“SYN flood”攻击的网络包。

·《被误解的TCP》澄清了被读者广泛误解的两个TCP概念,比较了Linux、Windows和安卓手机的不同Ack频率。

·《最经典的网络问题》是我近年遇到过的最经典的案例了。虽然很多年前就听说过Nagle算法遇到延迟确认会出问题,但是在现实中还是第一次遇到,赶紧记录下来。

·《为什么丢了单子?》讲述了一位销售朋友的遭遇,说明用Wireshark有助于发现产品的不足,并且找到改进之处。如果能用Wireshark分析自家产品与竞争对手产品的网络包,一定能找到不少差别,从而改进销售策略。

·《受损的帧》分析了因为硬件等原因导致帧损坏,从而在Wireshark上体现出的奇怪症状。事情往往没有表面上看到的那么简单。

·《虚惊一场》是因为一位眼尖的读者发现了我书中的一处“错误”(或者可以说是TCP的一个bug),后来研究了很久才发现是虚惊一场,不过排查过程还是很值得分享的。这位读者还从“作者简介”的照片中,看到我手上的《TCP/IP详解卷1:协议》是影印版,然后特意从美国帮我寄来了一本原版书。再次表示感谢!

·《NTLM协议分析》是这部分唯一的基础协议介绍,据说NTLM在中国用得还很多,所以才特意写了一篇。

·《Wireshark的提示》收集了读者感兴趣的很多Wireshark提示信息。文中不但介绍了每一个提示信息的意义,还分析了其产生的原因,希望让读者能够知其所以然。

第二部分是我自己在工作中遇到的网络问题。这部分讲得最细、最深,问题本身也最复杂。在阅读这一部分时,可能要多花点时间。

·《书上错了吗?》解释了为什么对于同一个TCP连接,在两端抓到的网络包顺序是不同的。明白了这一点才能理解后面两篇的内容。

·《计算“在途字节数”》介绍了如何从网络包中计算“已经发送但未被确认”的数据量。不用害怕数学,简单的加减法就够用了。

·《估算网络拥塞点》在前两篇的基础上,提供了一个估算网络拥塞点的方法。掌握了这个技能,此后再优化TCP性能时就胸有成竹了。

·《顺便说说LSO》讲的是现在越来越普遍的Large Segment Offload。在估算拥塞点的时候很可能会被LSO所干扰,因此我特意为它写了一篇。

·《熟读RFC》分析了一个颇为棘手的性能问题,即使擅长Wireshark也很难解决,向大家展示了熟悉RFC的重要性。

·《一个你本该能解决的问题》用Wireshark分析了一个UDP导致的性能问题,从本质上分析UDP和TCP的差别。这一篇我在微博上发过,还引发了一场不小的讨论。

·《几个关于分片的问题》其实是上一篇的后续。很多读者看到UDP包被分片之后出现了性能问题,所以对分片很感兴趣,问了不少问题。

·《MTU导致的悲剧》分享了几个MTU配置出问题而导致的事故。这类问题其实很多见的,尤其是对于实施和运维人员来说。

·《迎刃而解》是来自一个运维部门的技术问题,相当隐蔽而且诡异,最终在Wireshark的辅助下迎刃而解。

·《昙花一现的协议》回忆了一个我曾经支持过的协议。今天才学习它可能没有实际意义,但是其理念和创意还是值得借鉴的。当你对一个协议了解到一定程度时,肯定也会有改造它的想法。

·《另一种流控》介绍的是Pause Frame(暂停帧)流控。有别于TCP的“端到端”流控,它是“点到点”的,在有些场合很好用。

·《过犹不及》分享了一个多线程传输的案例,说明不是增加连接数就一定能提高性能,有时候甚至有负面效果。

·《治疗强迫症》演示了如何用Wireshark研究文本编辑软件的工作方式。也许这类软件不是你的兴趣所在,但是可以举一反三,用相同的方式研究其他软件。

·《技术与工龄》算是半篇技术文章。除了介绍Window Scale这个技术点,还希望每个人都能正视工龄,善待新人。

·《一个面试建议》只是分享面试经验,完全无关技术。文章写得很不严肃,目的是让读者休息一下,乐一乐。

·《如何科学地推卸责任》不是想把你“教坏”,而是分享了如何在技术上划分责任。如果你是乙方工程师,肯定会需要的。

第三部分的选材是日常生活中的抓包,包括手机App。在未来一两年,可能会有越来越多的人去抓手机上的包,因为用得多了,问题也会跟着增加。

·《假宽带真相》本是央视某一期节目的名字,说测速软件“有明显的设计缺陷”。我用Wireshark进行了验证,结果如何呢?读了全文就知道了。

·《手机抓包》讲解的是如何在家里搭建适合抓手机包的WiFi环境。如果你经常需要抓手机上的包来研究,相信我,是该改造一下家里的网络了。

·《微博为什么会卡》分析了微博在WiFi环境下经常卡顿的问题,最后找出来的原因竟然是DNS。本文对很多App的优化有借鉴作用。

·《寻找HttpDNS》讲述了一个“失败”的探索过程,因为到最后都没有找到想要的包。不过失败本身也有价值,因为我们知道了真相不过如此。

·《谁动了我的网络》详细地讲解了被劫持的网络包有什么特征,以及如何在Wireshark中找到它们。下一次你怀疑自家网络被劫持时,就可以抓一个包自己分析了。

·《一个协议的进化》介绍的是当前HTTP 1.1在性能上的落后之处,以及可能改进的空间。可惜现在HTTP 2的包还不容易抓到,否则我们还可以增加一些内容。

·《假装产品经理》分析了在微博发图片的网络包,我们可以从中看到它的压缩比例、上传行为、CDN服务商等。不用派卧底去新浪,就可以侦察到不少“机密”。

·《自学的窍门》也无关技术,只是分享了本人的学习经验,希望对新人有些参考价值。

第四部分的内容很少,却花费了我不少时间,因为写的是两个项目/产品。

·《打造自己的分析工具》介绍了我自己打造的一个性能分析网站,让大家体验一下量身定制的工具有多好用。本文也分享了开发过程的一些经验。

·《一个创业点子》讲的是我曾经想做的一个网络加速器。里面知识点还是挺多的,也适合用Wireshark来研究。你可能会问的一些问题

1.阅读此书需要什么基础?

只需要具备网络常识,比如在学校里上过网络课或者考过CCNA就够了。如果读过《Wireshark网络分析就这么简单》是最好的,会觉得衔接顺畅。对于缺乏网络基础的Wireshark用户,建议先阅读Richard Stevens的《TCP/IP详解卷1:协议》。英文好的读者可以通过 http://www.tcpipguide.com/free/index.htm页面免费阅读《The TCP/IP Guide》一书,里面的插图画得尤其好。由于读免费书籍很难坚持下去,你可以点击页面下方的Donate按钮给作者捐款,由此增加进一步学习的功力。

2.本书的选材为何如此广泛?

我写这本书是为了让读者学有所获,因此选材也从读者的兴趣点出发。比如现在流行手机上网,因此我增加了这部分的内容;又比如技术圈正在热议HttpDNS,所以我就去做了一系列实验……不同读者的关注点肯定会有所不同,如果某一篇的话题不是你感兴趣的,直接跳过也不影响后面的阅读。

3.为什么我觉得有些内容太简单了?

人们读书时都会有这样的反应——读到自己不懂的内容时,就会觉得高大上;读到自己擅长的领域时,又会觉得太简单。这就是为什么有些作者喜欢把书写得很玄乎,然而我的风格恰恰相反,会尽可能地把复杂的问题简单化。我的技术培训也是坚持这样的风格,会假设所有听众都是刚毕业的文科妹子(嗯,这样也会使我的心情好一些)。

4.为什么没有随书光盘?

我也希望能把这本书里的网络包都共享出来,但由于大多是在客户的生产环境中抓到的,所以不适合公开。毕竟从包里能暴露出来的安全隐患太多了,希望读者能理解这个苦衷。为了方便阅读,我已经尽量把Wireshark截图做清晰。建议大家在自己的环境中抓包分析,这会比看示例包更有价值。

5.怎样联系作者?

如果对书中的内容有疑问,或者自己抓了包却不知道怎么分析,都可以联系作者,邮箱地址为linpeiman@hotmail.com。你也可以在微博上@林沛满,但不建议关注,因为他是个整天晒园艺图片的话痨。答读者问

在过去几年中,有不少读者、同事和网友向我咨询过网络问题,其中大部分都记录在案。我一直把这些案例视为珍贵的财富,因为既真实又有广泛的代表性,比我自己在实验室中“制造”出来的好多了。本书从中选择了最经典的部分,希望读者会感兴趣。如果你在工作或生活中遇到网络问题,也欢迎抓个包来找我分析。Linux为什么卡住了?

到今天为止,已经有5位读者向我求助过这个问题了。症状请看图1,他们通过SSH登录Linux服务器时,输完用户名就卡住了,要等待10秒钟才提示密码输入。这究竟是什么原因导致的呢?其实我也是Linux菜鸟,虽然尝试过搜索“ssh hang”等关键词,但是没找到相关信息。图1

10秒钟的时间并不算长,吃个薯片喝口咖啡就过去了。但是作为强迫症患者,我还是容不得它的存在,因此便决定写篇文章,向大家演示一下怎样用Wireshark一步步解决这个问题。

首先是抓包,步骤如下。

1.在Linux服务器上启动抓包。

2.从笔记本SSH到Linux服务器,输入用户名并回车。

3.等待10秒左右,直到登录界面提示输入密码。

4.停止抓包。

这样就可以得到一个涵盖该现象的网络包了。一般在实验室中没有干扰流量,不用过滤也可以分析,不过我们最好在做实验时就养成过滤的习惯,以适应生产环境中抓到的包。因为我们是通过SSH协议登录的,所以可以直接用“ssh”来过滤,如图2所示。SSH包都是加密了的,因此我们看不出每个包代表了什么意思,不过这并不影响分析。从图2中可以看到,21号包和25号包之间恰好就相隔10秒。图2

这两个包之间所发生的事件,可能就是导致这个现象的原因。于是我再用“frame.number>21&&frame.number<25”过滤,结果如图3所示。图3

从图3中可以看到,Linux服务器当时正忙着向DNS服务器查询10.32.200.23的PTR记录(即反向解析),试图获得这个IP地址所对应的域名。该IP属于我们测试所用的笔记本,但由于DNS服务器上没有它的PTR记录,所以两次查询都等了5秒钟还没结果,总共浪费了10秒钟。

我们由此可以推出,这台Linux服务器在收到SSH访问请求时,会先查询该客户端IP所对应的PTR记录。假如经过5秒钟还没有收到回复,就再发一次查询。如果第二次查询还是等了5秒还没回复,就彻底放弃查询。我们甚至可以进一步猜测,如果DNS查询能成功,就不用白等那10秒钟了。

为了验证这个猜测,我在DNS服务器中添加了10.32.200.23的PTR记录,如图4所示,然后再次登录。图4

这一次果然立即登录进去了。从图5的Wireshark截屏可见,DNS查询是成功的,所以21号包和26号包之间几乎是没有时间停顿的。图5

明白了DNS查询就是问题的起因,接下来就知道怎么进一步研究了。只要在Google搜索“ssh dns”,第一页出来的链接都是关于这个问题的。随便挑几篇阅读一下,就连我这样的Linux初学者都能把这个问题研究透了。原来这个行为是定义在“/etc/ssh/sshd_config”文件中的,默认配置是这样的:

[root@Linux_Server~]#cat/etc/ssh/sshd_config|grep-i usedns

#UseDNS yes

改成下面这样就可以解决了,不用去动DNS服务器上的配置:

[root@Linux_Server~]#cat/etc/ssh/sshd_config|grep-i usedns

UseDNS no

我经常说技能比知识更重要,这就是例子之一。学会了使用Wireshark,其他知识也会跟着来的。像福尔摩斯一样思考

有位读者在豆瓣上评论我的上一本书,说有阅读侦探小说的感觉。我对此并不觉得惊讶,因为用Wireshark排查问题,和侦探破案的思路是一致的。神探福尔摩斯的破案秘诀是“溯因推理”——先观察所有细节,比如鞋根上的泥疙瘩甚至烟灰;然后作出多种推理和假设;接着刨去各种不可能,最后剩下的“无论多么难以置信,肯定没错。”用Wireshark分析网络包时也类似,我们先要在网络包中寻找各种线索,然后根据网络协议作出推理,接着刨去人为(有意或无意)掩盖的证据,才能得到最后的真相。尤其是和保密机构打交道的时候,工程师进不了机房,文档也不能公开,所以一切线索只能自己在包里找,感觉就更像破案了。

我最近帮一位读者解决的问题就非常典型。他供职的机构内部网站有时候会发生诡异的现象,比如Web服务器的端口号会随机发生变化(具体症状就不多讲了,和本文关系不大)。后来做了排查,把客户端和Web服务器直连,问题就消失了,确认了Web服务器和客户端都没有问题。难道根本原因就出在网络路径上了?可是管理员又声称网络拓扑非常简单,不会出问题的。见图1,客户端和Web服务器在不同的子网里,中间由一个路由器转发。图1

凭我的经验,这个网络拓扑的确简单到没有出问题的可能。可是已经到了山穷水尽的地步了,只好抓包试试。Web服务器不允许我们登录,所以只能在客户端抓,更糟糕的是抓包时那个诡异的现象并没有发生。你一定会纳闷,正常状况抓的包有什么看头啊?人在走投无路的时候,要求都是很低的,能抓到一点算一点。图2就是抓到的包,看起来一切都很正常:前3个包是三次握手,接着客户端发了个HTTP GET请求,服务器也确认收到了。图2

既然表面上都是好的,我们再看看每个包的详细信息。1号包的详情见图3,客户端把包交给了一个叫c0:62:6b:e2:bd:88的MAC地址,该地址属于默认网关。将包交给默认网关是合理的,因为Web服务器在另一个子网中,需要路由转发。也就是说,从1号包中没有发现任何异常。图3

再看看图4的2号包详情。这个包让人眼前一亮,信息量实在太大了。在阅读下面的文字之前,建议你自己先在图中找找亮点。图4

首先这个包竟然是从MAC地址00:10:f3:27:61:86发过来的,而不是之前提到的默认网关c0:62:6b:e2:bd:88。我不知道这个MAC地址属于什么设备,但这至少说明2号包和1号包走了条不一样的路径。再看其Time to live(TTL)居然是64,理论上经过一次路由的包,TTL应该减去1,变成63才对。根据这两条信息,可以推测管理员提供的拓扑图有误。真正的网络包流向应该接近图5,即客户端发出去的包是经过路由的,而Web服务器发过来的包没经过路由。图5

其实到这里就可以去找管理员说理了,不过别急,继续往下看。到了图6的第5号包,发现Identification竟然是49031,而同样是来自Web服务器的2号包(见图4)中,Identification却是0。一般发出Identification为0的机器永远都发0,不会一下子跳到49031。也就是说,其实2号包和5号包是两台不同的设备发出来的,这意味着在Web服务器和客户端之间,可能存在一台设备在代理三次握手,而能够代理握手的设备很可能是应对Syn flood攻击的防火墙。图6

因此图5的拓扑图还不够准确,应该更正成图7的样子。管理员忽视了这台防火墙,可能就错过了发现问题根源的机会。图7

把以上分析反馈给管理员之后,他果然通过MAC地址00:10:f3:27:61:86找到了一台防火墙。也正是防火墙上的一些错误配置,导致他们遇到了那些诡异症状,改正之后症状就消失了。本文的目的是演示如何在网络包中寻找被掩盖的线索,而不是防火墙知识,所以就不展开了。

从头到尾再复习一下整个过程,是不是很有当侦探的感觉?

注意:为了保护客户隐私,本文截图里的IP地址和MAC地址都被PS过,这就是为什么有些截图看上去不太自然。一篇关于VMware的文章

有位读者在VMware的知识库里找到一篇文章,觉得很像他正在遭遇的一个性能问题,便转发给我确认。作为好为人师的技术员,我当然不能让读者失望。

这篇文章大概讲了这样一件事。

问题描述

某些iSCSI存储阵列在出现网络拥塞时处理不当,会严重影响VMware的读写性能。这和它们的TCP实现方式有关。

解决方式

在VMware和存储阵列上关闭延迟确认(Delayed ACK)

VMware和iSCSI存储阵列是什么?我在知识库里找到一个网络拓扑,看起来很简单,大概如图1所示。我们无需理解得很深,只要把iSCSI存储阵列当作一台服务器,再把VMware当作其客户端就行了,两者通过以太网传输数据。图1

乍一看,这个“问题描述”与“解决方式”简直风马牛不相及。网络拥塞怎么能靠关闭延迟确认来解决?不过出于对VMware的一贯信任,我决定还是好好研究一下。

我们先要明白什么叫延迟确认,它可以用一个简单的例子来说明:在上海的笔记本上启动Wireshark抓包,然后用Putty远程登录一台位于悉尼的服务器。由图2可见,在上海发出一个SSH请求之后,经过149毫秒左右(即1号包和2号包之间的时间差)收到了悉尼的回复,这是正常的往返时间。但是笔记本收到回复之后,却没有立即确认,而是延迟了200毫秒以上(即2号包和3号包之间的时间差)才确认。图2

这个现象就是传说中的延迟确认,我在上一本书中也介绍过。为了让大家更好地理解它,我们再做个对比实验:我在笔记本上关闭了延迟确认,然后再次连接悉尼的服务器。从图3可见2号包和3号包之间几乎没有时间差了(只有0.000121秒,可以忽略)。图3

启用延迟确认是有好处的,假如在这等待的200毫秒里,上海的笔记本恰好有数据要发,就可以在发数据时捎带确认信息,省去了一个纯粹的确认包。图4就符合这种情况。笔记本收到11号包之后,等了41毫秒左右(即11号包和12号包之间的时间差)恰好又有一个SSH请求要发,就顺便把确认捎带过去了,因此省掉了一个纯粹的确认包。之所以有很多TCP协议栈默认启用延迟确认,正是基于这个原因——少一些确认包可以节省带宽嘛。图4

延迟确认的坏处也很明显,就是会凭空多出一段延迟。这个机制的作用很像你中午懒得去食堂吃饭,便等到下午出门上课时顺便去吃一点。结果就是少跑了一趟食堂,但是吃饭时间却被延后了。

理解了延迟确认的原理,我们再回顾VMware的那篇文章。一般来说,偶尔浪费200毫秒的等待时间并不算严重的问题,VMware为什么要这么在意呢?又不是等待很多个200毫秒。当我联想到“很多个”时,终于明白了——这世界上还真的存在一种很老的TCP的实现(RFC 2582),会导致拥塞时出现多个200毫秒的等待时间。详情且看下文分析。

图5从客户端的视角演示了启用延迟确认时,某些TCP协议栈在处理网络拥塞时的状况。图5

这个传输过程发生了以下事件。

1.客户端在同一时刻(或者说同一窗口)发送了9个TCP包,其中3、4、5号因为拥塞丢失了。

2.到达服务器的6、7、8、9号包触发了4个“Ack 3”,于是客户端快速重传3号包,此时它并不知道4号包也丢了。

3.由于服务器上启用了延迟确认,所以它收到3号包之后,等待了200毫秒才回复Ack 4。

4.客户端重传4号包,然后服务器又等待了200毫秒才回复Ack 5。

5.客户端重传5号包,然后服务器又等待了200毫秒才回复Ack 10。

6.客户端传输新的10号包,自此该网络拥塞就完全恢复了。

由于当时没有抓包,因此以上分析仅是我的推测。还有另一种可能是在某个200毫秒的延迟过程中,那些丢包的RTO(Retransmission Timeout)已经被触发,所以进入了超时重传阶段。无论符合哪一种可能,性能都会严重下降,因此VMware 建议关闭延迟确认是很有道理的,只不过没把原理说清楚。我甚至怀疑写这篇文章的人也没真正理解,因为里面还提到了慢启动之类不太相关的东西。

假如把延迟确认关闭掉,那该TCP协议栈处理拥塞的过程就变成图6所示。包还是那些包,不过浪费在延迟确认上的600毫秒就省下来了。只要往返时间不是太长,那些丢包也不会触发超时重传,所以避免了第二种可能。图6

我把分析结果告诉了那位读者,确保这个修改没什么副作用。于是他壮着胆子关闭了延迟确认,果然VMware的性能就飙升了。图7是他在关闭之后抓的网络包,和上文分析的一模一样,果然连续丢了很多包,而且每个重传都需要确认一次。图7

我以前分享的案例都是先在Wireshark中找到症状,然后再结合协议分析找到原因的。而这次纯粹是依靠协议分析,预测能从包里看到什么,然后再用Wireshark验证的。听起来似乎是完全靠灵感,但灵感不是天生的,它来自长期的训练。只有在Wireshark中看过了延迟确认和大量重传的样子,才可能意识到它们放在一起会出大问题。

注意:如果对那篇VMware的文章感兴趣,可以在其知识库http://kb.vmware.com中搜索1002598来找到它。来点有深度的

前一篇文章发布后,被一些公众号转发了。于是就有资深技术人员找到我,说读完觉得不过瘾,希望来点有深度的。好吧,那篇的确只从表面上介绍了延迟确认在网络发生拥塞时的影响,要往深处分析的话还是有不少料的。

先发散一下思维:除了VMware所建议的关闭延迟确认,还有其他的方法可以解决这个问题吗?

答案是肯定的。既然VMware的文章说“某些提供iSCSI访问的存储阵列在出现网络拥塞时处理不当”,就说明还有些存储阵列是处理得当的,即使打开延迟确认也不怕。那它们又是如何处理的呢?我做了很多研究之后,发现它们其实就是启用了TCP SACK(Selective Acknowledgement)功能,因此在大量丢包的时候不需要每个重传包都确认一次,也就不怕延迟确认的影响了。图1从客户端的角度演示了同样丢包的情况下,启用SACK的TCP协议栈是怎样处理重传的。图1

这个传输过程发生了以下事件。

1.客户端在同一时刻(或者说同一窗口)发送了9个TCP包,其中3、4、5号因为拥塞丢失了。

2.到达服务器的6、7、8、9号包触发了4个“Ack 3”。

3.由于启用了SACK,所以服务器可以在4个“Ack 3”中告知客户端哪些包已经收到了。

4.因为客户端已经知道哪些包丢了,哪些包已经收到,所以它可以一口气完成重传。

SACK信息在Wireshark中很容易看到。如图2所示,只要把“Ack=656925”和“SACK:661857-663035”这两个因素结合起来,客户端就知道排在后面的数据段661857-663035已经送达,但排在前面的656925-661856(共4932字节)反而丢失了,因此它需要重传这段数据。从图3可以看到每个重传包的Len值,四个包加起来恰好就等于4932字节。图2图3

由此可见启用SACK其实比关闭延迟确认更高效,因为它可以一次性重传多个丢包,而不用每重传一个就等待一次Ack,白费多个往返时间。这在局域网环境中的优势还不太明显,如果是在远程镜像中,一个正常的往返时间都要花上百毫秒,那就更应该启用SACK了。我真的很好奇VMware为什么不提供这个建议。

说完SACK,再讲一个更加有深度的知识点:除了大量重传之外,延迟确认还会在什么场景下严重影响性能?

从本质上看,延迟确认之所以会在大量重传时影响性能,是因为它在该场景下会多次出现(甚至因为延迟太久而导致超时重传)。那么还有什么场景会导致延迟确认多次出现呢?凭空想象是很难得到答案的,不过当你看过的网络包足够多时,肯定会遇到一些。我个人遇到最多的是TCP窗口极小的情况,此时启用延迟确认简直就是雪上加霜。图4演示了服务器接收窗口只有2920字节(相当于两个MSS),且关闭了延迟确认时的场景。因为客户端每发两个包就会耗光窗口,所以不得不停下来等待服务器的确认。假如这时候在服务器上启用了延迟确认,那29号和30号之间、32号与33号之间……以及38号和39号之间都需要多等待200毫秒,意味着传输效率会下降数百倍。这个场景下的延迟确认杀伤力巨大,又非常隐蔽,所以第一次遇上的工程师根本不知所措。图4

其他的场景我也遇到过一些,不过次数很少,就不一一列举了。更值得关注的,是如何在Wireshark中发现延迟确认,并计算它所带来的影响。

由于延迟确认是一个正常的TCP机制,有其积极的一面,所以Wireshark是不会把它当作问题标志出来的,而且点击Analyze→Expert Info菜单也是不会统计延迟确认的。难道我们只能靠人工去计算每个确认包的等待时间吗?我几年前就因此吃过一次亏——有位同事找我分析一个性能相关的网络包,我用 Wireshark看了半天都没有发现问题,所以就斩钉截铁地说跟网络无关。后来客户自己尝试关闭了延迟确认,性能居然就飙升了,导致我和同事都非常尴尬。最后写分析报告的时候才想到办法:只要用“tcp.analysis.ack_rtt>0.2and tcp.len==0”过滤一下,就可以把所有超过200毫秒的确认都筛出来了(当然筛出来的不一定全都是延迟确认,追求精确的话就逐个检查)。图5正是我当年遇到的那个网络包,只要把过滤出来的包数乘以0.2秒,就知道大概浪费了多少时间。图5

这两篇文章所列举的案例,其实在现实环境中广泛存在。不过由于症状只是性能差,所以很多用户以为是带宽不足导致的,就一直忍着。用Wireshark抓个包看看吧,很可能无需升级硬件,也可以帮你的系统大幅度提升性能的。三次握手的小知识

我原本以为TCP三次握手不值得写,没想到在某技术社区上被提问好几次了。看来感兴趣的人还真不少,还是写一篇吧。

我们知道TCP需要通过三次握手来建立连接,过程如图1所示。图1

从Wireshark上看到的握手过程就是图2这样的,你可以把Seq号和Ack号代入图1中,看看是否符合规律。图2

当X和Y的值太大时,看起来就不太友好,尤其是需要对这些号码做加减运算时。于是Wireshark提供了一个功能——把Seq和Ack的初始值都置成0,即用“相对值”来代替“真实值”。我们可以在Edit→Preferences→Protocols→TCP菜单中勾上Relative Sequence Numbers来启用它。启用之后,图2的包就变成图3这样,是不是清爽了很多?图3

成功的握手都是一样的,失败的握手却各有不同,因此解决起来还是需要一些技巧的。当我们遭遇TCP连接建立失败时,最稳当的排查方式就是用Wireshark来分析。网络包不多的时候很容易入手,用肉眼观察就行,但如果抓到的包特别大就需要过滤技巧了。根据我的经验,握手失败一般分两种类型,要么被拒绝,要么是丢包了。因此用两道过滤表达式就可以定位出大多数失败的握手。

表达式1:(tcp.flags.reset==1)&&(tcp.seq==1)

从表面上看,它只是过滤出Seq号为1,且含有Reset标志的包,似乎与握手无关。但在启用Relative Sequence Numbers的情况下,这往往表示握手请求被对方拒绝了,结果如图4所示。接下来只需右键选中过滤出的包,再点击Follow TCP Stream就可以把失败的全过程显示出来,见图5。此次握手失败的原因是服务器没有在监听80端口,所以拒绝了客户端的握手请求。图4图5

表达式2:(tcp.flags.syn==1)&&(tcp.analysis.retransmission)

这道表达式可以过滤出重传的握手请求。一个握手请求之所以要重传,往往是因为对方没收到,或者对方回复的确认包丢失了。这个重传特征正好用来过滤,结果如图6所示。接下来右键点击过滤出的包,再用Follow TCP Stream就可以把失败过程显示出来,见图7。此次握手失败的原因是丢包,所以服务器收不到握手请求。

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载