3. 镜像格式与结构
TFTP 这玩意儿,说白了就是网络启动里的“送餐员”。它不搞复杂认证,也不玩加密,就是闷头把文件从服务器搬到客户端。但你别小看它——PXE 启动的第一口饭,全靠它喂。我见过太多启动失败,最后查出来是 TFTP 没搭对。
今天咱们就把 tftp-hpa 这个最常用的实现,从安装到权限控制,掰开揉碎了讲清楚。
3.1 为什么选 tftp-hpa?
Linux 下 TFTP 服务器有好几个:tftpd、atftpd、dnsmasq 内置的 TFTP 模块……但我个人习惯用 tftp-hpa。为什么?
- 轻量:二进制包才几百 KB,不依赖一堆库。
- 稳定:H. Peter Anvin 维护的,跟 syslinux、pxelinux 是同一拨人出品,兼容性最好。
- 安全:默认 chroot 到根目录,客户端看不到外面的世界。
3.2 安装 tftp-hpa
不同发行版包名略有差异,但核心就两个组件:服务器端(tftpd-hpa)和客户端(tftp-hpa)。客户端用来调试,建议一起装。
Debian / Ubuntu 系
apt update
apt install tftpd-hpa tftp-hpa -y
RHEL / CentOS / Rocky 系
yum install tftp-server tftp -y
# 或者用 dnf
dnf install tftp-server tftp -y
装完后,检查一下服务状态:
systemctl status tftpd-hpa # Debian 系
systemctl status tftp.socket # RHEL 系
嗯,这里要注意:RHEL 系默认走 systemd socket 激活,服务不会常驻,有请求才启动。Debian 系则是独立服务,一直跑着。
3.3 根目录结构:TFTP 的“文件仓库”
TFTP 服务器需要一个根目录,所有客户端能访问的文件都放在这里。默认路径是 /srv/tftp(Debian)或 /var/lib/tftpboot(RHEL)。
我个人习惯统一用 /srv/tftp,好记。目录结构长这样:
/srv/tftp/
├── pxelinux.0 # PXE 引导程序
├── ldlinux.c32 # syslinux 库文件
├── menu.c32 # 菜单模块
├── chain.c32 # 链式加载模块
├── pxelinux.cfg/ # PXE 配置文件目录
│ ├── default # 默认配置
│ └── 01-aa-bb-cc-dd-ee-ff # 按 MAC 地址的配置
├── images/ # 内核和 initrd
│ ├── vmlinuz-5.10.0
│ └── initrd.img-5.10.0
├── efi/ # UEFI 启动文件
│ ├── bootx64.efi
│ └── grubx64.efi
└── iso/ # 可选的 ISO 文件
└── netboot.iso
pxelinux.cfg/default,实际对应 /srv/tftp/pxelinux.cfg/default。不要搞错相对路径和绝对路径。
3.4 传输模式:octet 与 netascii
TFTP 支持两种传输模式:
| 模式 | 说明 | 适用场景 |
|---|---|---|
| netascii | 文本模式,会做换行符转换(LF ↔ CRLF) | 纯文本配置文件(极少用) |
| octet | 二进制模式,原样传输,不做任何转换 | 内核、initrd、引导程序、ISO 文件 |
说白了,网络启动里 99% 的情况都用 octet 模式。你想想看,vmlinuz 是二进制文件,如果 netascii 给你把 0x0A 换成 0x0D 0x0A,内核直接就崩了。
3.5 权限控制:别让 TFTP 成为后门
TFTP 没有用户认证,谁都能读文件。所以权限控制全靠文件系统权限和 chroot 机制。
3.5.1 文件权限
TFTP 服务器通常以 tftp 用户运行。根目录和内部文件必须让这个用户可读:
chown -R tftp:tftp /srv/tftp
chmod -R 755 /srv/tftp
注意:不要给写权限。除非你明确需要客户端上传文件(比如网络备份场景),否则写权限就是安全隐患。
3.5.2 chroot 隔离
tftp-hpa 默认启用 chroot。客户端看到的根目录就是 /srv/tftp,它无法访问 /etc/passwd、/var/log 等系统文件。配置在 /etc/default/tftpd-hpa(Debian)或 /etc/xinetd.d/tftp(RHEL)里:
# Debian /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure --create"
关键参数说明:
--secure:启用 chroot,把根目录锁定在TFTP_DIRECTORY。--create:允许客户端创建文件(上传)。默认不开启,需要时才加。--blocksize 1468:我建议加上这个,能提升大文件传输效率。
3.5.3 防火墙放行
TFTP 使用 UDP 69 端口。别忘了在防火墙里放行:
# ufw
ufw allow 69/udp
# firewalld
firewall-cmd --add-port=69/udp --permanent
firewall-cmd --reload
3.6 核心流程一览
下面这张图总结了 TFTP 服务器搭建的完整逻辑:
3.7 验证搭建是否成功
装完别急着走,先验证一下。在另一台机器上执行:
tftp 192.168.1.100
tftp> get pxelinux.0
tftp> quit
如果文件能正常下载,说明 TFTP 服务器跑起来了。如果超时或报错,按下面顺序排查:
- 防火墙:UDP 69 端口通了吗?
- SELinux:RHEL 系记得检查
getenforce,必要时setenforce 0测试。 - 文件权限:tftp 用户能读根目录下的文件吗?
- chroot 路径:配置文件里的目录路径写对了没?
tcpdump -i any port 69 -X。能看到客户端请求了什么文件,服务器返回了什么错误。这招帮我解决过无数疑难杂症。
3.8 小结
TFTP 服务器搭建,说白了就五步:安装、配目录、选模式、控权限、放防火墙。每一步都不难,但漏掉一个就可能让 PXE 启动卡住。我个人建议把根目录结构固定下来,以后所有项目都用同一套,省心。