UDP又不关心丢包,TFTP是怎么保证数据完整性的呢?

题外话

有不少同学私信问我,为何要写公众号?

写文章最关心的一个指标是什么?是文章打开的数量!

知乎平台迟迟没有对于文章阅读的统计,我只能通过赞数、感谢数量来推测可能的阅读量,但这很不直观。有一天发现公众号具有这些详细的统计功能,于是决定把文章搬到这里来写。

从知乎一路追随过来的读者,感谢您们的支持,没有您们的阅读,我可能连半个文字也不愿多写!

大家关注这个公众号,还是希望学到一点有帮助的东西,那我就把多年积累的技术全部分享出来,少走一些弯路也是好的。

记得我写过一篇文章关于在读的大学生是否还需要考CCIE,收到很多读者的私信,私信的内容大同小异,对从事网络行业的前途担忧,是否网络行业从此就是夕阳产业了?

计算机网络作为互联网基础架构,在互联网方兴未艾的蓬勃上升期,怎么就一下子成为夕阳产业了?真要精通计算机网络,在几大互联网企业拿到七位数的年薪一点问题没有,问题是真的学好了吗?所谓学好了,就是把所有零碎的计算机网络知识点,串成有机的整体。如果有一天把这些知识点融为一体,不是你去求工作,而是工作来求你。

当我谈论TCP时,经常会谈到丢包、乱序,我会说到这些因素会严重影响TCP性能,因为影响缓存空间进而影响CWND,而作为影响TCP性能的另一个因素是RTT,一提到RTT就要想到Queue,Queue越深网络拥塞的时候RTT越大。

但是影响TCP性能还有segment size,小了TCP性能下降,大了会可能引起分片,最终事与愿违。在这里就可以与MTU串联在一起,MTU discovery的机制,分片/重组的原理,大小分片在经过queue优先级是一样的,还是遵循小包优先的原则?这样就会牵扯到后发先至的现象的发生,而为了克服这种困难,还是千方百计杜绝分片,只让应用层一次分片,其它层只有看的份。

在物理链路上,经常为了冗余备份,势必会有多路径的负载均衡,这里就牵扯到如何将IP报文分摊到物理链路上,但又要避免将属于同一个session的报文分摊到不同的链路上去,那样就有可能造成乱序,在这里就会深刻理解四元组、hash,而这个hash应用的范围很广,在安全领域到处都可以看到他的影子。

当把上文零碎知识点通过关键词串联在一起时,学习不再枯燥,仿佛找寻到一把钥匙,可以打开神秘的宝藏。。。

开始正题

最好的分析协议的方法,不是文字,还是协议分析软件,将它完整无缺展现在读者面前,读者就会豁然开朗。

噢,原来是这样。。。

为了回答这个问题,我做了一个小实验。我用TFTP传输了一个小文件,并用wireshark记录下整个过程,下图为捕获报文的截屏图片:

TFTP是Trivial FileTransfer Protocol的缩写,简单文件传输协议,使用UDP协议传输,服务器端在UDP端口69侦听客户端请求。

众所周知,UDP协议是一个无状态协议,一个不可靠协议。而文件传输却不允许有任何差错,需要可靠传输。既然UDP是指望不上了,那就让TFTP协议承担起所有可靠传输的任务吧。

曾经写过一篇文章,TCP的可靠传输的精髓是,发送方对发送的数据进行编号,接收方对接收到的编号进行确认。

TFTP拜了TCP为师,师傅,请多多指教!很快TFTP学会了这个简单的套路“编号、确认”。

捕获的报文一共10个报文,大体可以描述为:

发送方:“编号已发送”

接收方:“编号已确认”

发送方:“编号1已发送”

接收方:“编号1已确认”

发送方:“编号2已发送”

接收方:“编号2已确认”

发送方:“编号3已发送”

接收方:“编号3已确认”

发送方:“编号4已发送”

接收方:“编号4已确认”

如果任何一个编号在超时时间内,没有得到对方的确认,将会启动重传。重传这一招也是从TCP那儿学到的。

通过以上机制,可以将实现可靠的文件传输,无论怎样,只要中间没有坏人篡改文件,接收到的文件应该和发送的文件一摸一样。

数据完整性(Integrity)

通过抓包可以清晰地看出,TFTP协议是明文传输,如果TFTP在传输过程中被恶意篡改,接收方知道是否有人篡改过吗?不知道!

为了确保文件没有被篡改,那只有通过离线的方式,接收方事先知道文件的Hash (MD5)值,然后对接收到的文件也做一次MD5,如果两个MD5相同,校验成功则文件是完整的,否则文件被篡改!

那是否能把MD5值附在文件的末尾一起传输?

不可以,因为坏人能篡改文件,同样也能篡改MD5值。

接下来上两幅图片

发送方:“编号已发送”截图

注意这里,请求报文的源端口= 63394,目的端口= 69

接收方:“编号已确认”截图

令人惊奇的是,回复报文的源端口竟然不是69,而是62018。

更令人大跌眼镜的是,双方竟然能够通信好好的!

要我说这不能怪同学们,TCP连接的概念已经深入人心。如果换作TCP,客户端使用69端口号访问服务器,服务器必须使用69端口来响应,不是吗?

因为一个TCP连接时依靠四元组来决定的。

而UDP却不是连接,所以被动响应方可以选择自己的端口号来响应,而不一定使用侦听(listen)端口号。

写到这里,读者应该理解为何很多NAT打洞的软件,会选择UDP,而不会选择TCP的原因了吧?

返程UDP报文的源端口号可能已经不等于去向UDP报文的目的端口号,为了保证返程UDP报文的顺利通过NAT,NAT设备必须放松限制,在这个例子里可以表达为:

(10.1.1.2,63394,10.1.1.1,*)

可以表示为允许来自10.1.1.1任何端口的通行。还有更宽松的:

(10.1.1.2,63394,*,*)

后面的两个*表示为,任何主机IP、任何端口号都可以通行。

而TCP实现是这样的:

(10.1.1.2,63394,10.1.1.1,69)

很显然使用62018端口是无法通过NAT设备的。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180627G1FFHP00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券