最好的分析协议方法,不是文字,而是协议分析软件,将它完整无缺展现在读者面前,读者就会豁然开朗。噢,原来是这样。。。
为了回答这个问题,作者做了一个小实验。用TFTP传输了一个小文件,并用wireshark记录下整个过程,下图为捕获报文的截屏图片:
TFTP是Trivial File Transfer Protocol的缩写,简单文件传输协议,使用UDP协议传输,服务器端在UDP 端口69侦听客户端请求。
众所周知,UDP协议是一个无状态协议,一个不可靠协议。而文件传输却不允许有任何差错,需要可靠传输。既然UDP是指望不上了,那就让TFTP协议承担起所有可靠传输的任务吧。
曾经写过一篇文章,TCP的可靠传输的精髓是,发送方对发送的数据进行编号,接收方对接收到的编号进行确认。
TFTP拜了TCP为师,师傅,请多多指教! 很快TFTP学会了这个简单的套路“编号、确认”。
捕获的报文一共10个报文,大体可以描述为:
发送方:“编号0已发送”
接收方:“编号0已确认”
发送方:“编号1已发送”
接收方:“编号1已确认”
发送方:“编号2已发送”
接收方:“编号2已确认”
发送方:“编号3已发送”
接收方:“编号3已确认”
发送方:“编号4已发送”
接收方:“编号4已确认”
如果任何一个编号在超时时间内,没有得到对方的确认,将会启动重传。重传这一招也是从TCP那儿学到的。
通过以上机制,可以将实现可靠的文件传输,无论怎样,只要中间没有坏人篡改文件,接收到的文件应该和发送的文件一摸一样。
数据完整性(Integrity)
通过抓包可以清晰地看出,TFTP协议是明文传输,如果TFTP在传输过程中被恶意篡改,接收方知道是否有人篡改过吗? 不知道!
为了确保文件没有被篡改,可以通过离线的方式,接收方事先知道文件的MD5值,然后对接收到的文件也做一次MD5,如果两个MD5值相同则校验成功,文件是完整的,否则文件无效!
那是否能把MD5值附在文件的末尾一起传输?
不可以,因为坏人能篡改文件,同样也能篡改MD5值。
接下来呈上两幅图片:
发送方:“编号0已发送”的截图
注意这里,请求报文的源端口 = 63394,目的端口 = 69
接收方:“编号0已确认”的截图
令人惊奇的是,回复报文的源端口竟然不是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设备的。