3. TFTP服务器搭建:从原理到排障
TFTP这玩意儿,说白了就是简化版的FTP。它走UDP 69端口,没有认证,没有目录列表,功能单一到极致——就干一件事:读文件或写文件。但恰恰是这种“傻”,让它成了网络启动场景里的标配。想想看,PXE客户端在内存里刚拉起网卡驱动,哪来的精力去处理复杂的TCP握手和用户认证?
我在早期做无盘工作站项目时,就被TFTP的“简单”坑过好几次。嗯,今天咱们把这层窗户纸捅破,从原理到实战,再到那些让人抓狂的报错,一次性讲透。
3.1 TFTP协议原理:为什么它这么快?
TFTP(Trivial File Transfer Protocol)基于UDP,数据包固定512字节(最后一块不足512字节表示传输结束)。它的核心机制是停等协议——发一个数据块,等一个ACK,再发下一块。
关键特性一览:
- 传输模式:octet(二进制)或netascii(文本)
- 端口:UDP 69(监听),数据传输使用临时端口(1024以上)
- 无认证、无加密、无目录浏览
- 最大文件大小:32MB(理论值,实际受块号16位限制)
你可能会问:“停等协议效率多低啊?”没错,在局域网里这根本不是问题。PXE启动时传输的通常是内核镜像(vmlinuz)和initrd,加起来也就几十MB,毫秒级就传完了。我见过有人非要在TFTP上跑几百MB的ISO文件,结果超时重传搞到崩溃——那是用错了工具。
3.2 安装与配置tftpd-hpa
Linux下TFTP服务器有好几个流派:tftp-hpa、atftpd、dnsmasq(内置TFTP)。我个人习惯用tftpd-hpa,它是H. Peter Anvin维护的版本,跟PXE生态配合最默契。
3.2.1 安装
# Debian/Ubuntu
sudo apt update
sudo apt install tftpd-hpa tftp-hpa
# CentOS/RHEL 7/8
sudo yum install tftp-server tftp
# 或
sudo dnf install tftp-server tftp
# 启动并设置开机自启
sudo systemctl enable --now tftpd-hpa
小提示:tftp-hpa是客户端工具,tftpd-hpa是服务端。两个都装上,方便本地自测。
3.2.2 配置文件
主配置文件在 /etc/default/tftpd-hpa(Debian系)或 /etc/xinetd.d/tftp(RedHat系)。我直接给你看最常用的配置模板:
# /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp" # 文件根目录
TFTP_ADDRESS="0.0.0.0:69" # 监听所有IP的69端口
TFTP_OPTIONS="--secure --create" # 安全模式 + 允许上传
参数说明:
| 参数 | 含义 | 我的建议 |
|---|---|---|
--secure |
限制访问根目录,不能跳出 | 必须开启,否则有安全风险 |
--create |
允许客户端上传新文件 | 按需开启,PXE启动一般不需要 |
--timeout |
超时秒数(默认5秒) | 局域网保持默认即可 |
--blocksize |
数据块大小(默认512) | 调大能提速,但部分客户端不兼容 |
3.2.3 准备文件目录
sudo mkdir -p /srv/tftp
sudo chown -R tftp:tftp /srv/tftp
# 放一个测试文件
echo "Hello TFTP" | sudo tee /srv/tftp/test.txt
权限坑:目录权限必须是 tftp 用户可读。我曾经图省事用 chmod 777,结果被安全审计抓了个正着。正确做法是 chown tftp:tftp /srv/tftp,目录设 755,文件设 644。
3.3 文件传输测试
配置完别急着往PXE环境里怼,先在本地验证。我习惯用三步测试法:
3.3.1 本地回环测试
# 从服务器本机下载
tftp 127.0.0.1
tftp> get test.txt
tftp> quit
# 检查文件
cat test.txt
# 输出: Hello TFTP
3.3.2 跨主机测试
# 在另一台机器上执行
tftp 192.168.1.100
tftp> get test.txt
tftp> verbose # 开启详细输出,看传输过程
tftp> get test.txt
# 输出类似: received 12 bytes in 0.0 seconds
3.3.3 上传测试(如果开启了--create)
tftp 192.168.1.100
tftp> put localfile.txt
tftp> quit
测试清单:
- 本地回环通了吗?→ 验证服务端基本功能
- 跨主机通了吗?→ 验证网络和防火墙
- 上传/下载权限对吗?→ 验证文件系统权限
3.4 常见错误排查
这部分是重头戏。我这些年踩过的坑,全给你列出来。
3.4.1 超时(Timeout)
现象:Transfer timed out.
原因分析:
- 防火墙拦截了UDP 69端口
- 客户端和服务端不在同一广播域(跨网段没配DHCP中继)
- 服务器负载过高,丢包严重
排查步骤:
# 1. 检查服务端监听
sudo netstat -tulpn | grep :69
# 应该看到: udp 0.0.0.0:69
# 2. 检查防火墙
sudo iptables -L -n | grep 69
# 或
sudo ufw status
# 3. 抓包确认
sudo tcpdump -i eth0 port 69 -nn
# 看有没有RRQ包到达服务器
我曾经遇到过一个奇葩案例:客户说TFTP间歇性超时,查了三天发现是交换机的STP(生成树协议)在作怪——端口在转发和阻塞状态间切换,导致UDP包丢失。最后在接入端口配了 portfast 解决。
3.4.2 权限拒绝(Permission denied)
现象:Error code 2: Access violation
原因:
- 文件或目录属主不是tftp用户
- 文件权限不足(比如600)
- SELinux/AppArmor拦截
快速修复:
# 检查SELinux
getenforce
# 如果是Enforcing,临时放行
sudo setenforce 0
# 确认问题后,永久规则:
sudo semanage fcontext -a -t tftpdir_t "/srv/tftp(/.*)?"
sudo restorecon -Rv /srv/tftp
# 检查AppArmor(Ubuntu)
sudo aa-status | grep tftp
# 如果拦截,编辑 /etc/apparmor.d/usr.sbin.tftpd 添加路径
3.4.3 防火墙规则
很多新手只开了TCP端口,忘了TFTP走的是UDP。我建议你这样配:
# iptables
sudo iptables -A INPUT -p udp --dport 69 -j ACCEPT
# firewalld(CentOS 7+)
sudo firewall-cmd --add-service=tftp --permanent
sudo firewall-cmd --reload
# ufw(Ubuntu)
sudo ufw allow 69/udp
注意:TFTP的数据传输使用临时端口(1024-65535),如果防火墙规则太严,只放行69端口是不够的。客户端发RRQ到69,服务器会用临时端口回传数据。所以要么放行所有UDP高端口(不推荐),要么用状态防火墙自动放行回程流量。iptables的 state 模块可以搞定:-m state --state ESTABLISHED,RELATED -j ACCEPT。
3.4.4 文件未找到(File not found)
现象:Error code 1: File not found
排查:
- 检查文件名大小写(TFTP区分大小写)
- 检查文件是否在TFTP根目录下
- 检查路径是否包含软链接(TFTP默认不跟随软链接)
# 确认文件存在
ls -la /srv/tftp/test.txt
# 确认tftp用户可读
sudo -u tftp cat /srv/tftp/test.txt
3.5 生产环境配置建议
最后,分享几条我自己的生产环境铁律:
| 场景 | 配置 | 理由 |
|---|---|---|
| PXE启动 | 只读模式,关闭--create | 防止客户端上传恶意文件 |
| 多网段 | DHCP option 66指定TFTP服务器IP | 避免广播域限制 |
| 高并发 | 使用atftpd替代tftpd-hpa | atftpd支持多线程,并发性能更好 |
| 日志审计 | 开启rsyslog记录tftp日志 | 排查问题时能回溯 |