3、TFTP服务器配置:安装与配置tftpd-hpa、文件目录结构、权限设置、传输模式

TFTP 这玩意儿,说白了就是个简化版的 FTP。它没有认证,没有目录浏览,甚至没有可靠的错误恢复机制。那你可能会问:这么简陋的东西,为什么还在用?

嗯,因为它足够简单。在 PXE 网络启动的场景里,客户端(也就是那台还没装系统的裸机)的网卡固件里只烧录了最基本的网络协议栈。你让它跑一个完整的 FTP 或者 HTTP 客户端?不现实。TFTP 的代码量极小,刚好能塞进网卡的 Option ROM 里。所以,它成了网络启动中传输内核和 initrd 的默认选择。

3.1 安装 tftpd-hpa

我个人的习惯是,在 Ubuntu/Debian 系系统上,直接用 apt 搞定。tftpd-hpa 是目前最主流的 TFTP 服务器实现,由 H. Peter Anvin 维护——对,就是那个搞 SYSLINUX 的大神。

sudo apt update
sudo apt install tftpd-hpa -y

安装完成后,服务默认是启动的。你可以检查一下状态:

sudo systemctl status tftpd-hpa

如果看到 active (running),说明已经跑起来了。不过别急,默认配置不一定适合你的网络环境,我们得调一调。

小提示: 如果你用的是 CentOS/RHEL 系,包名可能叫 tftp-server,配合 xinetd 管理。但我更推荐 tftpd-hpa,配置更直观,性能也更好。

3.2 配置文件详解

tftpd-hpa 的主配置文件在 /etc/default/tftpd-hpa。打开它,你会看到类似这样的内容:

# /etc/default/tftpd-hpa

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure --create"

我来逐行解释一下这些参数,顺便聊聊我在项目中踩过的坑。

参数 说明 我的建议
TFTP_USERNAME 运行服务的系统用户 保持默认 tftp,不要用 root
TFTP_DIRECTORY TFTP 根目录 我习惯用 /srv/tftp,清晰明了
TFTP_ADDRESS 监听地址和端口 0.0.0.0:69 表示监听所有网卡
TFTP_OPTIONS 启动选项 --secure 必须加,--create 按需

--secure 这个选项特别重要。它限制了客户端只能访问 TFTP 根目录以内的文件,不能通过 ../ 跳出去。我曾经见过有人没加这个选项,结果客户端直接下载了 /etc/shadow……嗯,那场面相当尴尬。

--create 选项允许客户端上传文件时自动创建新文件。如果你的 PXE 环境只需要下载(比如传输内核和 initrd),可以不加这个选项,更安全。

3.3 文件目录结构

目录结构的设计,直接影响到后续维护的便利性。我推荐这样组织:

/srv/tftp/
├── pxelinux.0          # PXE 引导程序
├── ldlinux.c32         # SYSLINUX 库文件
├── vesamenu.c32        # 图形菜单模块
├── chain.c32           # 链式加载模块
├── memdisk             # 内存磁盘工具
├── pxelinux.cfg/       # PXE 配置文件目录
│   ├── default         # 默认配置文件
│   └── 01-aa-bb-cc-dd-ee-ff  # 按 MAC 地址的配置
├── images/             # 系统镜像目录
│   ├── ubuntu-22.04/   # 按发行版/版本组织
│   │   ├── vmlinuz     # 内核
│   │   └── initrd.img  # 初始 RAM 磁盘
│   └── centos-9/
│       ├── vmlinuz
│       └── initrd.img
└── iso/                # ISO 镜像文件(可选)
    └── netboot.iso

为什么这么分?

  • pxelinux.cfg/ 目录放 PXE 的配置文件,PXE 客户端会根据自己的 MAC 地址或 IP 地址来匹配对应的配置文件。匹配不到就用 default。
  • images/ 目录按发行版和版本号组织,方便后期维护多个系统版本。我在一次项目中同时维护了 Ubuntu 20.04、22.04 和 CentOS 7、8,这种结构让我少掉了不少头发。
  • iso/ 目录是可选的,如果你需要通过网络启动 ISO 文件,可以放在这里。
注意: 文件名在 TFTP 协议中是大小写敏感的。Linux 内核文件名通常是 vmlinuz(全小写),但有些发行版可能用 vmlinuz-5.15.0。请确保你的配置文件和实际文件名完全一致。

3.4 权限设置

权限问题,是 TFTP 服务器配置中最容易出错的环节。我见过太多人花了一下午调试,最后发现只是文件权限没设对。

基本原则:TFTP 服务以 tftp 用户运行,所以 tftp 用户必须对 TFTP 根目录及其下的文件有读取权限。如果开启了上传功能,还需要写入权限。

设置权限的步骤:

  1. 修改目录所有者:
sudo chown -R tftp:tftp /srv/tftp
  1. 设置目录权限:
sudo find /srv/tftp -type d -exec chmod 755 {} \;
sudo find /srv/tftp -type f -exec chmod 644 {} \;

这里解释一下:目录需要 755(rwxr-xr-x),因为 tftp 用户需要进入目录(执行权限)。文件只需要 644(rw-r--r--),只读就够了。

  1. 如果允许上传,给上传目录加写权限:
sudo mkdir -p /srv/tftp/upload
sudo chmod 755 /srv/tftp/upload
sudo chown tftp:tftp /srv/tftp/upload

注意,上传目录的权限要设为 755 而不是 777。777 意味着任何人都可以写,这在生产环境中是安全隐患。

避坑指南: 我曾经遇到过一个情况,所有权限都设对了,但客户端就是下载失败。最后发现是 SELinux 在作祟。如果你用的是 RHEL/CentOS,记得检查 SELinux 上下文:
sudo semanage fcontext -a -t tftpdir_t "/srv/tftp(/.*)?"
sudo restorecon -Rv /srv/tftp
或者直接临时关闭 SELinux 测试(不推荐生产环境使用):
sudo setenforce 0

3.5 传输模式

TFTP 支持三种传输模式:netascii、octet 和 mail。不过在实际使用中,你基本只会用到 octet。

模式 说明 适用场景
netascii 文本模式,会做换行符转换 传输纯文本配置文件
octet 二进制模式,不做任何转换 传输内核、initrd、ISO 等二进制文件
mail 邮件模式,已废弃 不要用

为什么强调用 octet?因为 PXE 启动过程中传输的文件——pxelinux.0、vmlinuz、initrd.img——全都是二进制文件。如果用 netascii 模式,TFTP 服务器会在传输过程中把 \n 转换成 \r\n,这会导致二进制文件损坏。启动时内核加载到一半就崩溃了,你连错误日志都看不到。

在 tftpd-hpa 中,默认就是 octet 模式。你不需要额外配置。但如果你用命令行客户端测试,记得指定模式:

tftp 192.168.1.100
tftp> mode octet
tftp> get pxelinux.0
tftp> quit

或者用一行命令:

tftp 192.168.1.100 -m octet -c get pxelinux.0

3.6 核心流程一览

说了这么多,我们来画一张图,把 TFTP 服务器在整个 PXE 启动流程中的位置看清楚。

TFTP 服务器在 PXE 启动中的角色 PXE 客户端(裸机) DHCP 服务器 TFTP 服务器 ① 广播 DHCP 请求 ② 返回 IP + TFTP 地址 ③ 请求 pxelinux.0 ④ 传输引导文件 加载 pxelinux.0 请求配置文件 ⑤ 读取 pxelinux.cfg/ ⑥ 返回配置 下载内核并启动

从这张图可以看得很清楚:TFTP 服务器在整个流程中扮演的是文件仓库的角色。DHCP 告诉客户端「你的 TFTP 服务器在 192.168.1.100」,然后客户端就去那里下载引导文件、配置文件,最后下载内核和 initrd。整个过程不需要用户名密码,不需要复杂的协议协商,就是简单的「给我文件」→「拿去」。

嗯,这就是 TFTP 的魅力——简单到极致,但也正因为简单,所以可靠。

3.7 验证配置

配置完了,怎么验证?我一般会在本机用 tftp 命令测试一下:

# 安装客户端工具
sudo apt install tftp-hpa -y

# 测试下载
echo "get pxelinux.0" | tftp 127.0.0.1

# 检查文件是否下载成功
ls -la pxelinux.0

如果文件下载下来了,说明 TFTP 服务器工作正常。如果报错 Transfer timed out,多半是防火墙挡住了 69 端口:

sudo ufw allow 69/udp

如果报错 File not found,检查文件路径和权限。记住,TFTP 的路径是相对于 TFTP_DIRECTORY 的。比如你要下载 /srv/tftp/pxelinux.0,在 TFTP 客户端里只需要写 get pxelinux.0。

调试小技巧: 如果客户端是远程机器,可以在 TFTP 服务器上开启 tcpdump 抓包:
sudo tcpdump -i any port 69 -nn
这样你能看到客户端发来的请求和服务器返回的响应。如果看到 RRQ(读请求)但没有 DATA 包,说明文件权限或路径有问题。

好了,TFTP 服务器的配置就到这里。记住几个关键点:目录结构要清晰、权限要收紧、传输模式用 octet。把这些搞定了,你的 PXE 启动环境就稳了一半。