3、TFTP 协议详解

TFTP(Trivial File Transfer Protocol,简单文件传输协议)是 PXE 引导过程中最核心的文件传输协议。客户端从 DHCP 服务器获取 IP 地址和引导文件位置后,必须通过 TFTP 下载引导加载程序(如 pxelinux.0、bootx64.efi)及配置文件。本章深入剖析 TFTP 的协议特点、与 FTP 的差异、端口号及传输模式,为后续搭建 TFTP 服务器和调试启动参数打下坚实基础。

3.1 TFTP 协议特点

TFTP 设计之初就定位为“轻量级、无状态、适用于无盘启动和嵌入式环境”。与 FTP 相比,它牺牲了功能丰富性,换取了极低的实现复杂度和资源占用。

特性 说明
传输层协议 基于 UDP(而非 TCP),端口号固定为 69(服务器监听端口)。
无状态 每个连接独立,服务器不维护会话状态,崩溃后重启不影响已完成的传输。
简单确认机制 使用停等协议(Stop-and-Wait):发送一个数据块后必须等待 ACK 确认,超时则重传。
固定数据块大小 默认每个数据块 512 字节(最后一块可小于 512 字节)。
无认证/加密 不提供用户认证、目录列表、文件删除等操作,仅支持读(RRQ)和写(WRQ)。
最小实现 代码量极小(约 2-3 KB),适合嵌入到 PXE ROM、UEFI 固件或小型引导加载器中。
PXE 为什么选择 TFTP? 因为 PXE 客户端运行在网卡固件或 UEFI 环境中,内存和代码空间极其有限,无法加载完整的 TCP/IP 协议栈。TFTP 基于 UDP,实现简单,仅需几十 KB 的代码即可完成文件下载,是网络引导场景下的最优解。

3.2 TFTP 与 FTP 的区别

虽然 TFTP 和 FTP 都用于文件传输,但两者在设计哲学、协议栈、安全性和适用场景上存在本质差异。下表从 8 个关键维度进行对比:

对比维度 TFTP FTP
传输层 UDP(无连接) TCP(面向连接)
端口号 69(固定) 21(控制连接)+ 20(数据连接)
会话状态 无状态,每个请求独立 有状态,维护会话和用户上下文
认证机制 无 用户名/密码(明文或加密)
目录操作 不支持(仅读写文件) 支持 ls、cd、mkdir、rm 等
传输模式 octet(二进制)、netascii(文本) ASCII、Binary、EBCDIC 等
可靠性 停等协议 + 超时重传 TCP 滑动窗口 + 拥塞控制
适用场景 无盘启动、嵌入式、固件升级 大文件传输、交互式文件管理
关键区别总结: TFTP 是“最小可行传输协议”,适合受限环境下的简单文件下载;FTP 是“企业级文件管理协议”,功能丰富但开销大。在 PXE 引导中,TFTP 是唯一的选择,因为 PXE 客户端无法运行完整的 FTP 客户端。

3.3 端口号 69 与协议流程

TFTP 服务器在 UDP 端口 69 上监听客户端的读请求(RRQ)或写请求(WRQ)。一旦请求被接受,服务器会动态分配一个临时端口(通常为 1024-65535 之间的随机端口)进行后续数据传输,端口 69 仅用于初始连接建立。

防火墙注意事项: 在搭建 PXE 环境时,必须确保防火墙允许 UDP 端口 69 入站。同时,由于 TFTP 数据连接使用临时端口,某些严格防火墙可能需要开启 UDP 端口 1024-65535 的入站规则,或使用 TFTP 代理/中继来规避此问题。

下图展示了 TFTP 读请求(RRQ)的完整交互流程:

TFTP 读请求(RRQ)交互流程 TFTP 读请求(RRQ)交互流程 PXE 客户端 TFTP 服务器 监听 UDP 69 ① RRQ (读请求, 文件名, octet) 分配临时端口 发送 DATA 块 (512B) ② DATA (块编号 1, 512 字节) 发送 ACK (块编号 1) ③ ACK (确认块 1) 重复步骤 ②-③,直到最后一块 < 512 字节 最后一块 < 512 字节时,客户端发送 ACK 后传输结束
协议流程要点:
  1. RRQ 请求: 客户端向服务器 UDP 69 端口发送读请求,包含文件名和传输模式(octet)。
  2. 数据发送: 服务器分配临时端口,将文件拆分为 512 字节的数据块(DATA),每个块附带块编号(从 1 开始)。
  3. ACK 确认: 客户端收到 DATA 后,发送 ACK 确认块编号。服务器收到 ACK 后发送下一个块。
  4. 传输结束: 当最后一块数据小于 512 字节时,客户端发送 ACK 后传输完成。如果文件大小恰好是 512 的整数倍,服务器会发送一个 0 字节的 DATA 块作为结束标志。

3.4 传输模式:octet 与 netascii

TFTP 定义两种传输模式,PXE 引导场景下必须使用 octet 模式:

传输模式 说明 PXE 适用性
octet(二进制) 以原始字节流传输文件,不做任何转换。适用于二进制文件(引导加载程序、内核、镜像)。 必须使用。所有 PXE 引导文件(pxelinux.0、vmlinuz、initrd.img)都是二进制文件,任何字节转换都会导致引导失败。
netascii(文本) 将文件中的换行符转换为网络标准格式(CR+LF),适用于纯文本文件。 不推荐。即使传输配置文件(如 pxelinux.cfg/default),也应使用 octet 模式,避免换行符转换导致解析错误。
常见错误: 如果 TFTP 服务器或客户端配置为 netascii 模式传输引导文件,二进制文件中的 0x0A(LF)和 0x0D(CR)会被错误转换,导致文件损坏。PXE 客户端启动时会出现“Could not find kernel image”或“Invalid or corrupt kernel image”等错误。务必确认服务器和客户端都使用 octet 模式。

3.5 TFTP 协议报文格式

理解 TFTP 报文结构有助于调试网络抓包和排查传输问题。TFTP 报文头部固定为 2 字节的操作码(Opcode),后续字段因操作类型而异。

Opcode 操作类型 报文格式
1 RRQ(读请求) Opcode(2B) + 文件名(可变) + 0x00 + 模式(可变) + 0x00
2 WRQ(写请求) Opcode(2B) + 文件名(可变) + 0x00 + 模式(可变) + 0x00
3 DATA(数据块) Opcode(2B) + 块编号(2B) + 数据(0-512B)
4 ACK(确认) Opcode(2B) + 块编号(2B)
5 ERROR(错误) Opcode(2B) + 错误码(2B) + 错误信息(可变) + 0x00

以下是一个典型的 RRQ 请求报文抓包示例(使用 tcpdump 或 Wireshark 查看):

# 使用 tcpdump 抓取 TFTP 流量(端口 69)
tcpdump -i eth0 -nn -s0 -X port 69

# 输出示例(RRQ 请求):
# 16:45:32.123456 IP 192.168.1.100.49152 > 192.168.1.10.69: [udp sum ok]
#   TFTP, length 28, RRQ "pxelinux.0" octet
#   0x0000:  0001 7078 656c 696e 7578 2e30 006f 6374  ..pxelinux.0.oct
#   0x0010:  6574 00                                  et.

# 输出示例(DATA 块):
# 16:45:32.124567 IP 192.168.1.10.49153 > 192.168.1.100.49152: [udp sum ok]
#   TFTP, length 516, DATA block 1 (512 bytes data)
#   0x0000:  0003 0001 [512 bytes of binary data...]
调试技巧: 使用 tcpdump -i any port 69 -X 可以实时查看 TFTP 请求的文件名和传输模式。如果看到模式字段为 netascii 而非 octet,说明客户端或服务器配置有误,需要立即修正。

3.6 TFTP 在 PXE 引导中的角色

在 PXE 引导流程中,TFTP 承担了“文件下载通道”的关键角色。下图展示了 PXE 客户端从 DHCP 获取信息后,通过 TFTP 下载引导文件的完整链路:

PXE 引导中 TFTP 的角色 PXE 引导中 TFTP 的角色 PXE 客户端 (网卡固件) DHCP 服务器 (IP + 引导文件位置) TFTP 服务器 (端口 69) 引导文件 pxelinux.0 / vmlinuz / initrd DHCP 交互 next-server + filename TFTP RRQ (octet) 读取 TFTP DATA + ACK
PXE 引导文件下载顺序:
  1. 客户端通过 DHCP 获取 next-server(TFTP 服务器地址)和 filename(引导文件路径,如 pxelinux.0)。
  2. 客户端向 TFTP 服务器(端口 69)发送 RRQ 请求,以 octet 模式下载 pxelinux.0。
  3. pxelinux.0 运行后,通过 TFTP 下载配置文件 pxelinux.cfg/default(或基于 MAC/IP 的个性化配置)。
  4. 根据配置文件中的 kernel 和 initrd 指令,继续通过 TFTP 下载 Linux 内核和初始 RAM 磁盘。

3.7 常见 TFTP 问题与排查

问题现象 可能原因 排查方法
TFTP 超时(Timeout) 防火墙阻止 UDP 69 端口;服务器未运行;网络不通 tcpdump -i any port 69 检查是否有请求到达;systemctl status tftp 检查服务状态
文件未找到(File not found) 文件名路径错误;文件权限不足;TFTP 根目录配置错误 检查 TFTP 服务器根目录(如 /var/lib/tftpboot)下文件是否存在;使用 tftp 客户端手动测试
传输模式错误 客户端或服务器使用 netascii 模式传输二进制文件 抓包检查模式字段;确保服务器配置强制使用 octet 模式
文件大小限制 某些 TFTP 服务器默认限制文件大小(如 32 MB) 检查服务器配置(如 tftp-hpa 的 --blocksize 和 --max-timeout 参数)
手动测试 TFTP 服务器:
# 安装 tftp 客户端(如果未安装)
sudo apt install tftp-hpa   # Debian/Ubuntu
sudo yum install tftp       # RHEL/CentOS

# 手动下载文件测试
tftp 192.168.1.10
tftp> mode octet
tftp> get pxelinux.0
tftp> quit

# 如果成功,当前目录下会生成 pxelinux.0 文件