TFTP协议详解
一 TFTP协议简介
TFTP协议全称为Trivial File Transfer Protocol。目标是在UDP之上上建立一个类似于FTP的但仅支持 文件上传 和下载功能的传输协议,所以它不包含FTP协议中的目录操作和用户权限等内容。
与FTP相似,TFTP传输过程中也有传输模式之分,模式的意思是如何解释数据包里的内容,比如是字符串还是二进制等。目前有三种模式:
- l netascii型:一种修改的8bit ascii码
- l octet型:即binary普通的二进制型
- l mail型:过时,不再使用
另外,通讯双方也可以自定义所需的传输模式。
二 TFTP协议分析
本分析以RFC1350为主,结合Ethereal截包软件。TFTP服务器使用Cisco TFTP Server。客户器使用Cisco TFTP Client。
2.1 TFTP包格式
TFTP共定义了五种类型的包格式,格式的区分由包数据前两个字节的Opcode字段区分,分别是:
- l 读文件请求包:Read request,简写为RRQ,对应Opcode字段值为1
- l 写文件请求包:Write requst,简写为WRQ,对应Opcode字段值为2
- l 文件数据包:Data,简写为DATA,对应Opcode字段值为3
- l 回应包:Acknowledgement,简写为ACK,对应Opcode字段值为4
- l 错误信息包:Error,简写为ERROR,对应Opcode字段值为5
1. 读写文件请求包 RRQ/WRQ
读写文件请求包的内容如图2.1所示。
图2.1 读写文件请求包
图2.2是利用Ethereal截获的写文件请求包。
图2.2 Ethereal截获的写文件请求包
从图2.2可以看出,虽然RFC1350中描述的读写文件请求包中并未明确包含option字段,但由于Mode项表示的是一个字符串,故可以把相关内容组合成一个字符串数组放到Mode段里边。
这个包里的option选项有:
- l 数据包大小(blksize)为512字节
- l 超时时间(timeout)10秒
- l 文件大小(tsize)6656000字节
2. 文件数据包 DATA
数据包的格式如图2.3所示。
图2.3 DATA包格式
图2.4 Ethereal截获的DATA包
图2.4为Ethereal截获的数据包。
从图2.4可以看出,该包的包号由Block字段给出,目前该包号为1,最大值为65535,轮流使用。数据包的起始包号从1开始。
另外,TFTP规定,DATA包中数据大小最大为512字节。当DATA包中数据字节小于512时,就表示这是读写文件数据的最后一个包了,我们姑且可称之为结束DATA包。
3. 回应包 ACK
回应包格式如图2.5所示。
图2.5 ACK包格式
图2.6所示为Ethereal截获的对上面的DATA包回复的ACK包。
图2.6 对Block1数据包的回应包
ACK中的包号为锁确认的数据包的包号,例如数据包的包号为100,则该ACK包的包号也为100。
4. 错误信息包 ERROR
错误包格式如图2.7所示。
图2.7 ERROR包格式
其中,RFC1350中ErrorCode定义了7个值,其值和含义分别如下:
- l 0 Not defined, see error message(if any)
- l 1 File not found
- l 2 Access violation
- l 3 Disk full or allocation exceeded
- l 4 Illegal TFTP operation
- l 5 Unknown transfer ID
- l 6 File already exists
- l 7 No such user
图2.8为Ethereal截获的ERROR包。
图2.8 错误包
红色警告的原因是因为该字符串未以0结尾。可能是客户端的软件bug
TFTP规定,ERROR包不会重传也不需要确认,所以有可能对方收不到ERROR包,TFTP建议采用某种ERROR包超时处理机制,但并没有给出具体信息。
2.2 TFTP工作流程
TFTP的工作都是由客户端发起一个RRQ或者WRQ开始的。这里分别以WRQ和RRQ为例,讲述读写的工作过程,以及错误处理等内容。
用S表示Server,C表示Client。
1. WRQ工作流程
- l S在端口为69的UDP上等待C发出写文件请求包
- l C通过UDP发送符合TFTP请求格式的WRQ包给S。从UDP包角度看,该UDP包的源端口由C随意选择,而目标端口则是S的69。
- l S收到C的这个请求包后,需发送ACK给C。对于写请求包,S发送的ACK包确认号为0。
- l C发送DATA数据给S,S接收数据并写文件
- l 当C发送的DATA数据长度小于512字节时,S认为这次WRQ请求完成
这里我们要明确一点,如果有多个C同时向S发起请求的话,S如何正确发送包到对应的C呢。
在TFTP中,一次请求中所有包的源和目标都由Transfer ID(TID)来标示。TFTP规定TID值就是UDP包中的源和目标端口。也就是说,一次请求过程中,S和C通过UDP包的源和目标端口来判断这个包是不是发给自己的。
以WRQ为例,C向S的69端口发送一个文件请求包,这个文件请求包中UDP的源端口号为C的TID(假设C选择4845作为它的TID),目标端口为69(这个时候由于请求还未接受,所以这次请求的UDP包中目标端口不是TID)。S收到这个请求后,将另外采用一个UDP端口(应该另启动了一个UDP Socket)假设为4849来回复这个请求的ACK。这样,这个回复的UDP包的源端口就是S的TID(=4849),目标就是C的UDP端口(TID=4845)。以后,这次请求的后续所有包都在端口为4845和4849中来往。
上述过程隐含了一定程度上的容错处理。例如,C收到一个TID不是4849的包,则认为这个包是错误的。
另外,S对于每个请求,都要采用一个不重复的新的UDP端口号作为它的TID,也就是说,S上同时存在的n个请求的TID都将不同。
这里再介绍下TFTP的回复ACK机制。虽然TFTP中有指定的ACK包作为回应,但在普遍意义上,DATA包和ERROR包都可以作为上一次发送包的响应。
一般来说,C发送了一个非结束DATA包给S,如果在超时时间内,C未收到S发送的ACK,则C继续发送这个DATA直到S回复ACK。这种情况是比较好理解的。
但假如S回复了上一个非结束DATA包ACK后,C在S的超时时间内没有发送下一个DATA包,则S将继续发送这个ACK。从这个角度看,S等待的这个新DATA包是对上一次ACK的确认。
2. RRQ的工作流程
RRQ和WRQ类似。
- l S在端口为69的UDP上等待C发出读文件请求包
- l C通过UDP发送符合TFTP请求格式的RRQ包给S。
- l S收到C的这个请求包后,将直接发送DATA包给C,这个DATA包中含S选择的TID作为UDP的源端口和C的TID作为UDP目标端口,起始包号为1。
- l C接收来自S的DATA包并回复ACK。直到请求完成
3. 连接和错误处理
UDP实际上没有连接的概念。但从上面分析的RRQ和WRQ看,S在69端口上等待请求,而且S总是生成一个新的UDP来完成和C的交互。这个过程和TCP的listen以及Accept非常类似。所以TFTP把这种交互也称作connection。只不过这种连接是隐含在请求中的。
一般情况下,连接的建立由一次成功的请求来发起,当最后一个DATA包发送完毕并且ACK回复了后,则连接正常关闭。在传输过程中,如果出现错误,假设S向C发送了一个ERROR包,如果C收到ERROR包,则连接关闭。如果C没有收到ERROR包,则需要启动ERROR超时检测机制。需要强调的是对于ERROR包,S和C都不会重传也不需要ACK确认。
TFTP建议在连接正常关闭的情况,S可在发送确认结束DATA包的ACK后稍等片刻后再关闭连接。例如,当C发送结束DATA包后,S回复ACK后再等一段时间才关闭。再次等待时间中,如果ACK包丢失,C将再次发送结束DATA包或者超时处理。S如果又收到一次结束DATA包后,就知道ACK包丢失了。S可以关闭连接也可以再次发送ACK包。
2.3 TFTP总结
整体上来说,TFTP的一个重要特点就是简单及易于实现,这也是设计TFTP协议的一个初衷。
优点:
- l 每个数据包大小固定,这样在内存分配处理的时候比较直接
- l 实现简单
- l 每个数据包都有确认机制,可以实现一定程度的可靠性
缺点:
- l 传输效率不高
- l 滑动窗口机制太简单,并且该窗口仅有一个包的大小
- l 超时处理机制并不完善,RFC1350并没有给出详细的处理机制说明
三 范例
这里用流程图表示S和C端的实现过程。
服务器端:
图3.1 服务端工作流程
客户端:
图3.2 客户端工作流程
根据上面这两个流程图,可以很容易实现TFTP的客户端和服务器端,具体的超时重传和错误处理机制,可以自己设计并实现。