协议特点
- TFTP(Trivial File Transfer Protocol)
- 使用 UDP 作为传输协议,区别于 FTP 使用 TCP 端口21。
- 可访问远程服务器,上传/下载文件及发送邮件,传输数据字节为8位。
- 不支持
- list 文件夹
- 用户鉴权及加密功能。
- 最大支持 4GB 大小文件
运用
- 常部署于 PXE 环境传输文件。
- 部署 tftp 服务完成 pxe 装机流程
- 可配合 python pytftp 库动态生成 pxe 相关配置文件
- 不推荐部署于公共网络,适用于私有网络小文件传输。
传输机制
- 以 Read/Write 报文发起传输请求,返回 Data/Ack 建立传输。
- Data 报文未填满 Data 字段最大长度时,则后续还有数据,反之则传输完成。
- 单次报文传输时,可能会在网络中丢失。报文接收方等待超时后,会重传上一份报文,以触发发送方重传。
- 发送完最后一个 Ack 报文时,发送端会等待一段时间,如果又收到 data,则会重发 Ack 以保证结束传输。(即使最后 data 发送方未收到 Ack,超时且重传结束后,依旧会判定传输成功,关闭连接)。
- 发送 Error 报文会提前结束传输,不会重传和等待响应。因此需要超时机制来触发 Error。
- 为什么不直接基于 tcp 协议呢
抓包
我们以抓包的方式,来展示一次成功的文件传输。
Tips:
- 69 端口为服务端用来监听 tftp 请求的固定端口。服务端确定操作合法后,会以一个新端口应答,避免影响其它请求的响应。
- tftp 中传输的端口被称为 TID(transfer identifiers)。
成功传输小文件
# 在服务端抓取 udp 包,不能只抓 69 端口
sudo tshark -i bond0 -f 'udp'
# 抓包使用 -V 参数,还可见以下网络头部
# Ethernet layer2: 14 bytes+padding
# IP HEADER: 20 bytes
# UDP HEADER: 8 bytes
# TFTP
# 从 hosta 访问 hostb:69 下载文件
# hosta:10.0.0.94
# hostb:10.0.0.125
curl tftp:hostb/netboot.seed.yml
# 抓包结果
# Read Request, 其中附带 option 额外参数
# 10.0.0.94:50504 -> 10.0.0.125:69
1 0.000000000 10.0.0.94 → 10.0.0.125 TFTP 97 Read Request, File: netboot.seed.yml, Transfer type: octet, tsize=0, blksize=512, timeout=6
# 此处服务端用新的端口响应会话
# 10.0.0.125:52483 -> 10.0.0.94:50504
2 0.007549332 10.0.0.125 → 10.0.0.94 TFTP 67 Option Acknowledgement, blksize=512, tsize=5072
# 10.0.0.94:50504 -> 10.0.0.125:52483
3 0.007736889 10.0.0.94 → 10.0.0.125 TFTP 60 Acknowledgement, Block: 0
# 开始传输文件(558bytes 去掉头, tftp 段总大小 516bytes,data 段大小为 512bytes)
4 0.007877492 10.0.0.125 → 10.0.0.94 TFTP 558 Data Packet, Block: 1
5 0.008066622 10.0.0.94 → 10.0.0.125 TFTP 60 Acknowledgement, Block: 1
# 省略中间若干个 block
...........
# 结束传输(data 段小于 512bytes)
22 0.009778727 10.0.0.125 → 10.0.0.94 TFTP 510 Data Packet, Block: 10 (last)
23 0.009928020 10.0.0.94 → 10.0.0.125 TFTP 60 Acknowledgement, Block: 10
协议报文
报文以操作码为标识,可分为以下五种数据报文:
- Read request (RRQ)
- Write request (WRQ)
- Data (DATA)
- Acknowledgment (ACK)
- Error (ERROR)
ACK & ERROR 响应 WRQ & DATA
DATA & ERROR 响应 RRQ & DATA
ERROR 响应任何其他类型
协议头
---------------------------------------------------
| Local Medium | Internet | Datagram | TFTP |
---------------------------------------------------
Read/Write Req
报文格式
2 bytes string 1 byte string 1 byte
------------------------------------------------
| Opcode | Filename | 0 | Mode | 0 |
------------------------------------------------
报文字段
- Opcode: 操作码 1/2 为读写报文类型
- Filename: 字符串类型,以 1byte 长度的 0 字节结尾。
- Mode:
- Netascii: ASCII 的一种制定格式,定义于 RFC764
- Octet: 8位字节,传输文件字节数据
- Mail: 以 Netascii 传输邮件内容,且 Filename 字段应标识接受者地址
Ps: 传输均以读写请求作为开端。
Data
报文格式
2 bytes 2 bytes n bytes
----------------------------------
| Opcode | Block # | Data |
----------------------------------
报文字段
- Opcode: 操作码 3 为数据报文类型
- Block: 从 1 开始递增的数据块编码,用于识别新/旧数据块
- Data:
- 0~511bytes 则表示该数据块为最后一块,文件传输结束
- 512bytes,则数据未传输结束
- Data 总大小扩增:
- RFC 1350 基础定义 Data 长度为 512
- 512 bytes/block x 65535 blocks = 32 MB
- RFC 2348 将 Data 长度扩增至 65535,以适应更大的文件
- 65535 bytes/block x 65535 blocks = 4 GB
- RFC 1350 基础定义 Data 长度为 512
- 响应 RRQ
Acknowledgment
报文格式
2 bytes 2 bytes
---------------------
| Opcode | Block # |
---------------------
报文字段
- Opcode: 操作码 4 为响应报文类型
- Block 响应块编号:
- 响应WRQ: Block 0
- 响应DATA: Block 编号
Error
报文格式
2 bytes 2 bytes string 1 byte
----------------------------------------
| Opcode | ErrorCode | ErrMsg | 0 |
----------------------------------------
报文字段
- Opcode: 操作码 5 为响应报文类型
- Error:
- Value Meaning
- 0 Not defined, see error message (if any).
- 1 File not found.
- 2 Access violation.
- 3 Disk full or allocation exceeded.
- 4 Illegal TFTP operation.
- 5 Unknown transfer ID.
- 6 File already exists.
- 7 No such user.
网友评论