4、TFTP服务器搭建:TFTP协议简介、安装tftp-server、配置tftp根目录、防火墙放行

TFTP 这玩意儿,说白了就是个简化版的 FTP。我刚开始接触网络启动时,总觉得它太简陋了——没有认证、没有目录列表,连端口都是固定的 UDP 69。但后来在项目中吃过亏才明白,简单恰恰是它的优势。PXE 启动过程中,BIOS/UEFI 那点可怜的代码根本跑不动复杂的 FTP 协议,TFTP 这种“傻瓜式”传输反而最可靠。

4.1 TFTP协议简介

TFTP(Trivial File Transfer Protocol)基于 UDP 传输,端口号 69。它只支持读、写、确认三个基本操作。你想想看,一个连用户密码都不校验的协议,能指望它多安全?所以它只适合在内网用,千万别暴露到公网去。

特性 TFTP FTP
传输层协议 UDP(端口69) TCP(端口21/20)
认证机制 无 用户名/密码
目录浏览 不支持 支持
传输效率 低(停等协议) 高(流式传输)
适用场景 PXE启动、嵌入式 文件共享、上传下载

TFTP 的传输模式是“停等协议”——发一个数据包,等一个确认,再发下一个。效率确实不高,但胜在实现简单。我记得有一次调试 PXE 启动,客户端总是卡在“Downloading NBP...”这一步,最后发现是 TFTP 的 block size 默认 512 字节,传输大文件时超时重传太频繁。后来我把 block size 调到 1468 字节,问题就解决了。

核心要点:TFTP 只做一件事——从服务器读取文件或向服务器写入文件。没有花哨的功能,但足够稳定。

4.2 安装tftp-server

在 CentOS/RHEL 7/8 上,我习惯用 tftp-server 配合 xinetd 来管理。当然,你也可以用 systemd 直接启动,但 xinetd 的方式更灵活——有请求时才启动服务,节省资源。

# 安装 tftp-server 和 xinetd
yum install -y tftp-server xinetd

# 或者用 dnf(RHEL 8+)
dnf install -y tftp-server xinetd

安装完成后,检查一下 xinetd 的配置:

# 查看 tftp 的 xinetd 配置文件
cat /etc/xinetd.d/tftp

默认配置长这样:

service tftp
{
    socket_type     = dgram
    protocol        = udp
    wait            = yes
    user            = root
    server          = /usr/sbin/in.tftpd
    server_args     = -s /var/lib/tftpboot
    disable         = no
    per_source      = 11
    cps             = 100 2
    flags           = IPv4
}

这里有个坑——disable = no 必须设置,否则 xinetd 不会启动 tftp 服务。我曾经在客户现场排查了半天,最后发现是安装后忘记改这个参数了。

4.3 配置tftp根目录

TFTP 的根目录默认是 /var/lib/tftpboot。我个人习惯把它改到 /data/tftpboot,方便和别的服务共用存储。但不管放哪,权限一定要给对。

# 创建 TFTP 根目录
mkdir -p /var/lib/tftpboot

# 设置权限(重要!)
chmod 755 /var/lib/tftpboot
chown nobody:nobody /var/lib/tftpboot

为什么用 nobody 用户?因为 tftp 服务默认以 nobody 身份运行,如果目录权限是 root,客户端读文件时会报“Permission denied”。

避坑指南:我曾经把 TFTP 根目录权限设成了 777,结果被安全扫描工具报了个高危漏洞——任何人都能往里面写文件。正确的做法是:根目录 755,里面的文件 644,子目录 755。

接下来,把 PXE 启动需要的文件放进去。比如一个简单的测试文件:

# 创建一个测试文件
echo "Hello from TFTP server" > /var/lib/tftpboot/test.txt

# 设置正确的权限
chmod 644 /var/lib/tftpboot/test.txt
chown nobody:nobody /var/lib/tftpboot/test.txt

启动服务并验证:

# 启动 xinetd
systemctl start xinetd
systemctl enable xinetd

# 检查 tftp 是否在监听
netstat -tuln | grep :69

如果看到 udp 0 0 0.0.0.0:69 0.0.0.0:*,说明服务已经跑起来了。

4.4 防火墙放行

TFTP 用的是 UDP 69 端口,防火墙必须放行。但这里有个细节——TFTP 的数据传输会使用随机高位端口(通常是 1024-65535),所以光放行 69 端口是不够的。

我推荐的做法是:

# 放行 TFTP 服务(firewalld)
firewall-cmd --add-service=tftp --permanent
firewall-cmd --reload

# 或者手动放行端口
firewall-cmd --add-port=69/udp --permanent
firewall-cmd --add-port=1024-65535/udp --permanent
firewall-cmd --reload

如果你用的是 iptables:

# iptables 规则
iptables -A INPUT -p udp --dport 69 -j ACCEPT
iptables -A INPUT -p udp --sport 1024:65535 -j ACCEPT

小技巧:如果你只想在调试时临时放行,可以用 firewall-cmd --add-service=tftp(不加 --permanent),重启防火墙后规则就没了。这样既方便测试,又不会留下安全隐患。

验证防火墙规则是否生效:

# 查看 firewalld 规则
firewall-cmd --list-all

# 或者用 telnet 测试(虽然 TFTP 是 UDP,但可以检查端口是否可达)
telnet 192.168.1.100 69

嗯,这里要注意——telnet 只能测试 TCP 端口,UDP 端口得用 nc 或 tftp 客户端来测。

4.5 整体架构图

下面这张图展示了 TFTP 服务器在整个 PXE 启动流程中的位置,以及它和 DHCP、HTTP 服务的关系:

TFTP服务器在PXE启动中的角色 TFTP服务器在PXE启动中的角色 PXE客户端 DHCP服务器 TFTP服务器 HTTP服务器 ① 广播请求IP ② 返回IP+TFTP地址 ③ 请求引导文件 ④ 传输pxelinux.0 ⑤ 请求内核/镜像 ⑥ 传输vmlinuz+initrd 说明: 1. TFTP只负责传输小文件(引导加载器、配置文件) 2. 大文件(内核、根文件系统)建议用HTTP/HTTPS 3. TFTP基于UDP 69端口,防火墙需放行 4. 根目录权限必须为755,文件权限644

4.6 验证与测试

服务搭好了,怎么确认它能用?我一般用 tftp 客户端来测:

# 安装 tftp 客户端
yum install -y tftp

# 测试连接
tftp 192.168.1.100
tftp> get test.txt
tftp> quit

# 查看下载的文件
cat test.txt

如果看到 Hello from TFTP server,说明一切正常。如果卡住了,多半是防火墙没放行,或者根目录权限不对。

排错思路:

  • 检查 xinetd 是否运行:systemctl status xinetd
  • 检查端口监听:netstat -tuln | grep 69
  • 检查防火墙:firewall-cmd --list-all
  • 检查 SELinux:getenforce(如果 enforcing,需要放行 tftp 相关策略)

嗯,说到 SELinux,我记得有一次在 RHEL 7 上搭 TFTP,所有配置都对,但客户端就是连不上。最后发现是 SELinux 在作怪——tftp_home_t 上下文没设置。解决办法很简单:

# 设置 SELinux 上下文
semanage fcontext -a -t tftpdir_t "/var/lib/tftpboot(/.*)?"
restorecon -Rv /var/lib/tftpboot

如果你不想折腾 SELinux,直接关掉也行(不推荐生产环境):

setenforce 0