4. 校验技术概述

TFTP 这玩意儿,说实话,我用了好多年。简单、轻量,在局域网里跑 PXE 启动确实够用。但一旦你开始部署大镜像——比如超过 4GB 的 Windows ISO 或者定制 Linux 发行版——TFTP 的短板就暴露无遗了。它基于 UDP,没有拥塞控制,传输大文件时丢包率飙升,速度慢得让人抓狂。

我在一个数据中心项目里遇到过,用 TFTP 传一个 6GB 的 wim 文件,客户端反复超时重试,整个部署流程拖了将近 40 分钟。后来换成 HTTP,同样的网络环境,8 分钟搞定。所以这一章,我们就来聊聊怎么用 Nginx 或 Apache 替代 TFTP,把 PXE 引导升级到 HTTP/HTTPS 模式。

为什么非换不可?

说白了,TFTP 的设计初衷就不是为了传大文件。它只有 512 字节的固定块大小,没有窗口滑动,没有加密。而 HTTP 有 TCP 的拥塞控制、有 Keep-Alive、有断点续传,还能上 TLS 加密。你想想看,在跨网段部署或者公网部署场景下,TFTP 几乎不可用。

特性 TFTP HTTP/HTTPS
传输协议 UDP (端口 69) TCP (端口 80/443)
大文件支持 差(块大小 512B) 优秀(支持分块传输)
加密 无 TLS (HTTPS)
拥塞控制 无 有(TCP 自带)
典型场景 局域网小文件 跨网段/公网大镜像

Nginx 配置:轻量又高效

我个人习惯用 Nginx 来做 HTTP 引导服务器。配置简单,性能好,内存占用低。下面是一个典型的配置片段,专门为 PXE 文件服务优化过。

server {
    listen 80;
    server_name pxe.example.com;

    root /var/lib/pxe;
    autoindex on;
    autoindex_exact_size off;
    autoindex_localtime on;

    # 大文件传输优化
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    client_max_body_size 0;

    # 针对 ISO/WIM 等大文件禁用压缩
    location ~* \.(iso|wim|img|squashfs)$ {
        gzip off;
        sendfile_max_chunk 1m;
        output_buffers 32 512k;
    }

    # 日志格式优化
    access_log /var/log/nginx/pxe_access.log;
    error_log /var/log/nginx/pxe_error.log;
}

这里有几个关键点。sendfile 必须开,它让内核直接搬运文件,省掉用户态拷贝。tcp_nopush 和 tcp_nodelay 配合使用,能减少小包数量,提升吞吐量。对于 ISO 这类大文件,我建议关掉 gzip 压缩——压缩大文件反而浪费 CPU,而且压缩后的数据流在 PXE 客户端可能解压失败。我曾经踩过这个坑,一个 8GB 的 ISO 开了 gzip,客户端加载到一半直接崩溃。

小技巧: 如果客户端数量多,可以增加 worker_processes 和 worker_connections。我一般设成 worker_processes auto; 然后 worker_connections 1024; 足够应对几百台并发部署。

Apache 配置:稳定但稍重

如果你团队里 Apache 用得熟,用它也行。配置上比 Nginx 啰嗦一点,但功能一样。下面是一个参考配置。

<VirtualHost *:80>
    DocumentRoot /var/www/pxe
    ServerName pxe.example.com

    <Directory /var/www/pxe>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>

    # 大文件优化
    EnableSendfile On
    EnableMMAP On
    KeepAlive On
    MaxKeepAliveRequests 100
    KeepAliveTimeout 5

    # 禁用大文件压缩
    SetEnvIfNoCase Request_URI \.(iso|wim|img|squashfs)$ no-gzip dont-vary

    # 日志
    CustomLog /var/log/apache2/pxe_access.log combined
    ErrorLog /var/log/apache2/pxe_error.log
</VirtualHost>

注意 Apache 的 EnableSendfile 和 EnableMMAP 默认可能是 Off,记得手动打开。MMAP 能把文件映射到内存,对大文件读取有加速效果。但如果你内存紧张,建议关掉 MMAP,否则频繁换页反而拖慢速度。

grub.cfg 配置:从 HTTP 启动

服务器配好了,客户端怎么知道去 HTTP 拿文件?关键在 grub.cfg。传统 PXE 用 tftp 协议前缀,现在改成 http 或 https 就行。下面是一个实际可用的例子。

set net_default_server=192.168.1.100
set net_default_prefix=http://192.168.1.100/pxe

menuentry "Ubuntu 22.04 LTS HTTP Install" {
    linux ${net_default_prefix}/vmlinuz root=/dev/nfs netboot=nfs nfsroot=${net_default_server}:/srv/nfs ip=dhcp
    initrd ${net_default_prefix}/initrd.img
}

menuentry "Custom ISO via HTTP" {
    linux ${net_default_prefix}/memdisk iso
    initrd ${net_default_prefix}/custom.iso
}

这里有个坑。grub 的 http 模块默认只支持 HTTP 1.0,不支持分块传输编码。如果你的 Nginx 开了 chunked transfer encoding,grub 会直接报错。解决办法是在 Nginx 里强制关闭分块传输,或者用 proxy_buffering 把响应缓冲起来。我建议直接关掉分块:

location /pxe/ {
    proxy_set_header Connection "";
    proxy_http_version 1.0;
    proxy_buffering off;
    chunked_transfer_encoding off;
}
注意: grub 的 http 模块不支持 HTTPS。如果你要用 HTTPS,得用 iPXE 或者 UEFI HTTP Boot。UEFI 固件自带的 HTTP 客户端通常支持 HTTPS,但需要导入 CA 证书。这个我们后面章节会细讲。

大文件传输优化:别让网络成为瓶颈

大文件传输优化,说白了就是三件事:减少握手、增大窗口、避免重传。我总结了一个清单,你可以照着检查。

  • TCP 缓冲区调大: 在 sysctl.conf 里设置 net.core.rmem_max=16777216 和 net.core.wmem_max=16777216,然后重启网络服务。
  • 启用 TCP 快速打开: net.ipv4.tcp_fastopen=3,减少三次握手的延迟。
  • 关闭 Nagle 算法: 对于大文件传输,Nagle 算法反而有害。Nginx 里 tcp_nodelay on 就是干这个的。
  • 使用 HTTP 范围请求: 如果客户端支持(比如 iPXE),可以分片下载,实现类似多线程加速的效果。
  • CDN 或缓存代理: 跨地域部署时,用 Varnish 或 Squid 做缓存,避免回源带宽打满。

我记得有一次给一个教育城域网做批量部署,200 台教室电脑同时从一台服务器拉镜像。一开始没做优化,千兆网卡被打满,丢包率飙升到 15%。后来加了缓存代理,又调大了 TCP 缓冲区,并发量直接翻了三倍。

HTTPS 引导:安全但要注意性能

HTTPS 引导的好处很明显:防篡改、防中间人。但代价是 TLS 握手开销。对于 PXE 启动来说,每次连接都要做证书验证,如果镜像文件被拆成很多小片,握手次数会非常多。

我的建议是:只在关键环节用 HTTPS。比如 grub.cfg 本身用 HTTPS 拉取,确保引导配置不被篡改;但内核和 initrd 可以用 HTTP,因为它们的校验和已经在 grub.cfg 里用 hash 验证过了。这样既保证了安全,又避免了性能损失。

核心思路: 分层安全。配置层用 HTTPS 保证完整性,数据层用 HTTP 保证传输效率,最后用校验和兜底。

整体架构图

下面这张图展示了从 DHCP 到 HTTP 引导的完整流程。你可以看到,TFTP 只负责传一个很小的引导文件(比如 undionly.kpxe 或 bootx64.efi),剩下的所有大文件都走 HTTP。

HTTP/HTTPS PXE 引导架构 HTTP/HTTPS PXE 引导架构 DHCP 服务器 分配 IP + 引导文件 TFTP 服务器 仅传引导加载器 HTTP/HTTPS 服务器 Nginx / Apache PXE 客户端 UEFI / BIOS 镜像存储 ISO / WIM / squashfs DHCP Offer (引导文件路径) 请求引导加载器 (undionly.kpxe) HTTP 请求内核/镜像 读取文件 关键优化点 1. sendfile 开启 2. TCP 缓冲区调大 3. 关闭分块传输

从图上你能看到,TFTP 的角色被压缩到最小——只传一个几百 KB 的引导加载器。剩下的内核、initrd、根文件系统全部走 HTTP。这样既保留了 PXE 的兼容性,又享受了 HTTP 的高效传输。

避坑指南

最后分享几个我踩过的坑,希望能帮你少走弯路。

  • 防火墙别忘了放行 80 端口: 听起来简单,但我真见过有人配了半天 Nginx,结果 iptables 把 80 端口 DROP 了。记得检查 iptables -L -n。
  • grub 的 http 模块版本问题: 老版本 grub 的 http 实现有 bug,传输大文件会断。建议用 grub 2.06 以上版本。
  • UEFI 安全启动: 如果开了 Secure Boot,HTTP 引导的加载器必须签名。要么用 shim 链式加载,要么在 BIOS 里关掉 Secure Boot。生产环境建议用 shim。
  • 并发数估算: 一个千兆网口,理论最大吞吐 125MB/s。如果每个客户端下载速度 10MB/s,最多支持 12 台并发。超过这个数,要么加网卡绑定,要么上 CDN。