4、TFTP服务器搭建:tftp-hpa vs atftpd,传输性能调优与安全加固
TFTP这玩意儿,说白了就是网络启动里的“送水工”。它不花哨,但没它不行。PXE启动时,BIOS/UEFI从DHCP拿到IP和引导文件位置后,全靠TFTP把vmlinuz、initrd.img这些“粮食”搬进内存。
我这些年经手过的网络启动项目,少说也有几十个了。TFTP这块踩过的坑,够写一本小册子。今天咱们就把tftp-hpa和atftpd这两个主流服务器掰开揉碎,讲讲怎么搭、怎么调、怎么防、怎么修。
核心结论先放这儿:小规模环境(<50台并发)用tftp-hpa,省心;大规模批量部署(>200台)上atftpd,性能优势明显。别问为什么,问就是血泪教训。
4.1 两个主流TFTP服务器的选型对比
先说说tftp-hpa。这是H. Peter Anvin写的,就是那个搞SYSLINUX的大神。它走的是单线程、select模型,每次只能处理一个请求。你想想看,如果50台机器同时PXE启动,它就得排队一个个喂。但好处是——稳,非常稳。我在一个教育城域网里跑了三年,没重启过一次。
atftpd呢,是Jean-Pierre Lefebvre的作品。它用多线程+自适应窗口,能同时伺候几百个客户端。我记得有一次给一家代工厂做批量部署,300台机器同时开机,atftpd扛住了,tftp-hpa直接超时一片。
| 对比维度 | tftp-hpa | atftpd |
|---|---|---|
| 并发模型 | 单线程 select | 多线程 自适应 |
| 默认块大小 | 512字节(RFC标准) | 自动协商(最大1468) |
| 配置复杂度 | 低,一个配置文件搞定 | 中,参数较多 |
| chroot支持 | 内置,-s参数 | 内置,--chroot |
| 日志能力 | syslog,较简略 | 详细,支持debug级别 |
| 适用场景 | 小规模、嵌入式、单机 | 批量部署、大规模集群 |
我的建议:如果你刚开始搭PXE环境,先用tftp-hpa上手。等遇到性能瓶颈了,再换atftpd不迟。别一上来就上atftpd,参数调不好反而更慢。
4.2 安装与基础配置
4.2.1 tftp-hpa 安装配置
在Debian/Ubuntu上,一条命令搞定:
apt install tftp-hpa tftpd-hpa
配置文件在 /etc/default/tftpd-hpa。我个人习惯这样配:
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure --create --verbose -s -c -p -U 077 -u tftp"
这里解释几个关键参数:
--secure:chroot到TFTP目录,这是安全底线-c:允许上传文件(如果你需要客户端回传日志的话)-p:不检查端口范围,提高兼容性-U 077:上传文件的umask,防止权限过大
注意:千万不要在生产环境去掉 --secure 参数。我曾经见过有人为了省事直接暴露根目录,结果被扫到TFTP漏洞,整个/boot被人扒走了。
4.2.2 atftpd 安装配置
apt install atftpd
atftpd的配置在 /etc/default/atftpd:
OPTIONS="--daemon --port 69 --tftpd-timeout 300 --retry-timeout 5 \
--maxthread 100 --verbose=5 --logfile /var/log/atftpd.log \
--chroot /srv/tftp"
这里 --maxthread 100 是关键——控制最大并发线程数。我建议根据你的机器内存来调,每线程大约消耗2-3MB内存。
4.3 传输性能调优
TFTP默认的512字节块大小,是1970年代在ARPANET上定的。放到今天千兆网络里,简直是在用吸管喝奶茶。调优的核心就两个参数:块大小(blksize)和窗口大小(windowsize)。
4.3.1 块大小调优
TFTP的RRQ包可以协商blksize。客户端在请求时带上blksize 1468选项,服务器同意后,每个数据包就能塞1468字节。1468这个数字怎么来的?以太网MTU 1500 - IP头20 - UDP头8 - TFTP头4 = 1468。刚刚好。
在tftp-hpa中,客户端这样指定:
tftp -m binary -c get -b 1468 server_ip /pxelinux.0 /tmp/pxelinux.0
atftpd默认会自动协商,但你可以强制指定:
OPTIONS="$OPTIONS --blksize 1468"
我做过对比测试:512字节块大小,传输10MB文件耗时约12秒;调到1468后,直接降到4秒。3倍提升,立竿见影。
4.3.2 窗口大小调优
这是TFTP的“黑科技”。传统TFTP是停等协议——发一个包,等ACK,再发下一个。窗口大小(windowsize)允许连续发多个包再等ACK,大幅减少往返延迟的影响。
atftpd支持这个扩展,tftp-hpa不支持(至少原生不支持)。配置方法:
OPTIONS="$OPTIONS --windowsize 8"
窗口大小设多少合适?我一般建议8-16。设太大(比如64),一旦丢包重传代价很高。设太小,又发挥不出优势。
| 窗口大小 | 10MB传输时间(千兆网络) | 丢包重传影响 |
|---|---|---|
| 1(传统模式) | ~12秒 | 低 |
| 4 | ~5秒 | 中 |
| 8 | ~3秒 | 中高 |
| 16 | ~2.5秒 | 高 |
性能调优黄金法则:先调blksize到1468,再调windowsize到8。如果网络环境干净(交换机无丢包),可以试试16。别贪心,稳定比速度重要。
4.4 安全加固
TFTP本身没有认证、没有加密。说白了,谁都能连上来下载文件。所以安全加固不是可选项,是必选项。
4.4.1 chroot 隔离
chroot是TFTP安全的第一道防线。它把TFTP进程的根目录锁定在指定目录,就算被攻破,攻击者也看不到/etc/passwd。
tftp-hpa用 -s 参数:
TFTP_OPTIONS="--secure -s /srv/tftp"
atftpd用 --chroot:
OPTIONS="--chroot /srv/tftp"
注意:chroot后,TFTP目录里必须包含所有客户端需要的文件,包括引导加载器、内核、initrd等。我曾经犯过一个低级错误——chroot后忘了把pxelinux.0拷进去,结果所有客户端报"File not found",排查了半小时才反应过来。
4.4.2 访问控制
光chroot还不够,你还要限制谁能连、能连什么。
方法一:iptables限制源IP
iptables -A INPUT -p udp --dport 69 -s 192.168.100.0/24 -j ACCEPT
iptables -A INPUT -p udp --dport 69 -j DROP
方法二:atftpd内置访问控制
OPTIONS="$OPTIONS --allow-ip 192.168.100.0/24 --deny-ip 0.0.0.0/0"
方法三:文件级权限控制
TFTP目录权限设为755,所有文件644。不要让TFTP用户有写权限,除非你明确需要上传功能。
chown -R root:tftp /srv/tftp
chmod -R 755 /srv/tftp
find /srv/tftp -type f -exec chmod 644 {} \;
安全底线清单:
- 必须chroot,不要妥协
- 必须限制源IP,至少限制到内网段
- TFTP目录不要放敏感文件
- 定期检查日志,关注异常请求
- 如果不需要上传,去掉 -c 参数
4.5 常见故障排查
这部分是我花时间最多的。TFTP出问题,症状往往就两个:Timeout 和 File not found。但背后的原因五花八门。
4.5.1 Timeout 超时
客户端报 TFTP timeout,通常原因有这几个:
- 防火墙拦了UDP 69端口——这是最常见的。检查iptables、云平台安全组、物理防火墙规则。
- TFTP服务没启动——检查进程:
ps aux | grep tftp - 端口被占用——
netstat -anp | grep :69,看看是不是有其他服务占了69端口 - 网络路径MTU问题——如果blksize设了1468但中间设备MTU小于1500,大包会被分片或丢弃。降回512试试看。
- 并发太高导致服务端丢包——tftp-hpa单线程处理不过来,换atftpd或加--maxthread
排查命令三板斧:
# 1. 测试连通性
tftp 192.168.100.10 -c get testfile
# 2. 抓包看交互
tcpdump -i eth0 port 69 -vv
# 3. 看服务端日志
tail -f /var/log/syslog | grep tftp
4.5.2 File Not Found
这个错误更气人——明明文件就在那里,客户端就是找不到。原因通常是:
- 路径问题:chroot后,客户端请求
/pxelinux.0,但文件实际在/srv/tftp/pxelinux.0。注意chroot后的路径是相对于chroot目录的。 - 文件名大小写:TFTP协议区分大小写。
PXELINUX.0和pxelinux.0是两个文件。我见过有人把文件拷成大写,客户端请求小写,死活找不到。 - 权限问题:TFTP用户对文件没有读权限。
chmod 644解决。 - SELinux/AppArmor:这些安全模块会拦截TFTP的读操作。检查审计日志:
ausearch -m avc -ts recent
我的排查习惯:先在TFTP服务器本地用 tftp localhost -c get filename 测试。本地能通,就是网络或防火墙问题;本地不通,就是配置或权限问题。这个二分法能省一半时间。
4.5.3 一个真实案例
去年帮一家公司排查PXE启动故障。症状是:100台机器同时开机,前20台正常,后面的全部timeout。我一看,他们用的tftp-hpa,单线程。100个请求排队,每个传输要3-4秒,前20台占掉60-80秒,后面的客户端早就超时放弃了。
解决方案:换成atftpd,设 --maxthread 50 --blksize 1468 --windowsize 8。重启后,100台机器同时启动,全部在30秒内完成。客户当场竖大拇指。
嗯,这就是选对工具、调好参数的价值。