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 服务的关系:
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