强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Dnsmasq 服务搭建完全教程 / 第 05 章:TFTP 配置

第 05 章:TFTP 配置

5.1 TFTP 基础概念

5.1.1 什么是 TFTP

TFTP(Trivial File Transfer Protocol,简单文件传输协议)是一种轻量级文件传输协议,主要用于网络设备的引导和配置文件分发。

特性 说明
传输层 UDP 端口 69
认证
目录列表 不支持
文件写入 协议支持但 Dnsmasq 仅提供只读
块大小 默认 512 字节
最大文件 无限制(协议层面)
典型用途 PXE 引导、路由器固件升级、配置分发

5.1.2 TFTP 与 FTP/HTTP 对比

维度 TFTP FTP HTTP
端口 69/UDP 20-21/TCP 80/TCP
认证
加密 FTPS HTTPS
复杂度 极低 中等 中等
速度 慢(小文件)
防火墙友好
适用场景 网络引导 文件管理 Web 服务

5.2 Dnsmasq TFTP 基本配置

5.2.1 启用 TFTP 服务

# /etc/dnsmasq.d/20-tftp.conf

# 启用 TFTP
enable-tftp

# TFTP 根目录
tftp-root=/var/lib/tftpboot

# 安全设置:只允许访问根目录下的文件
tftp-secure

# 设置 TFTP 文件权限(创建时的 umask)
tftp-unique-root=ip   # 为每个客户端创建唯一文件名

5.2.2 创建 TFTP 目录

# 创建目录
sudo mkdir -p /var/lib/tftpboot/{pxelinux.cfg,images,grub}

# 设置权限
sudo chmod -R 755 /var/lib/tftpboot
sudo chown -R nobody:nogroup /var/lib/tftpboot

# 验证目录
ls -la /var/lib/tftpboot/

5.2.3 测试 TFTP 服务

# 安装 TFTP 客户端
sudo apt install tftp-hpa     # Debian/Ubuntu
sudo yum install tftp         # CentOS/RHEL

# 测试上传/下载
echo "test file" > /tmp/test.txt
tftp 192.168.1.1 -c put test.txt
tftp 192.168.1.1 -c get test.txt

# 或使用 curl 测试下载
curl tftp://192.168.1.1/test.txt

5.3 PXE 网络引导

5.3.1 PXE 引导流程

1. 客户端发送 DHCP Discover
2. Dnsmasq 回复 DHCP Offer(包含 IP + TFTP 服务器地址 + 启动文件名)
3. 客户端通过 TFTP 下载启动文件(pxelinux.0 / grubx64.efi)
4. 启动加载器读取配置文件
5. 加载内核(vmlinuz)和初始内存盘(initrd)
6. 启动操作系统安装/运行
┌──────────┐     DHCP/TFTP      ┌──────────┐
│  客户端   │←──────────────────→│ Dnsmasq  │
│ (PXE ROM)│                    │ DHCP+TFTP│
└────┬─────┘                    └──────────┘
     │
     │ 1. DHCP Discover
     │←── DHCP Offer (IP + TFTP地址 + 启动文件)
     │ 2. TFTP: 读取 pxelinux.0
     │ 3. TFTP: 读取 pxelinux.cfg/default
     │ 4. TFTP: 读取 vmlinuz + initrd
     │ 5. 引导 Linux

5.3.2 Syslinux/PXELINUX 引导配置

步骤 1:准备引导文件

# 安装 syslinux(提供 PXE 引导文件)
sudo apt install syslinux syslinux-common pxelinux

# 复制引导文件到 TFTP 目录
sudo cp /usr/lib/PXELINUX/pxelinux.0 /var/lib/tftpboot/
sudo cp /usr/lib/syslinux/modules/bios/{ldlinux.c32,libutil.c32,menu.c32,libcom32.c32} /var/lib/tftpboot/

# 验证文件
ls -la /var/lib/tftpboot/

步骤 2:创建 PXE 菜单配置

sudo mkdir -p /var/lib/tftpboot/pxelinux.cfg

sudo tee /var/lib/tftpboot/pxelinux.cfg/default <<'EOF'
DEFAULT menu.c32
MENU TITLE PXE Network Boot Menu
PROMPT 0
TIMEOUT 100

LABEL ubuntu2204
  MENU LABEL Install Ubuntu 22.04 LTS
  KERNEL images/ubuntu2204/vmlinuz
  INITRD images/ubuntu2204/initrd
  APPEND ip=dhcp url=http://192.168.1.1/ubuntu-22.04-live-server-amd64.iso autoinstall ds=nocloud-net

LABEL debian12
  MENU LABEL Install Debian 12
  KERNEL images/debian12/vmlinuz
  INITRD images/debian12/initrd
  APPEND priority=critical url=http://192.168.1.1/debian-preseed.cfg

LABEL centos9
  MENU LABEL Install CentOS Stream 9
  KERNEL images/centos9/vmlinuz
  INITRD images/centos9/initrd
  APPEND inst.repo=http://192.168.1.1/centos9/ inst.ks=http://192.168.1.1/centos9-ks.cfg

LABEL memtest
  MENU LABEL Memory Test (memtest86+)
  KERNEL images/memtest86+

LABEL local
  MENU LABEL Boot from local disk
  LOCALBOOT 0
EOF

步骤 3:下载安装文件

# Ubuntu 22.04
sudo mkdir -p /var/lib/tftpboot/images/ubuntu2204
cd /tmp
wget https://releases.ubuntu.com/22.04/ubuntu-22.04.4-live-server-amd64.iso
sudo mount -o loop ubuntu-22.04.4-live-server-amd64.iso /mnt
sudo cp /mnt/casper/vmlinuz /var/lib/tftpboot/images/ubuntu2204/
sudo cp /mnt/casper/initrd /var/lib/tftpboot/images/ubuntu2204/
sudo umount /mnt

# Debian 12
sudo mkdir -p /var/lib/tftpboot/images/debian12
cd /tmp
wget https://deb.debian.org/debian/dists/bookworm/main/installer-amd64/current/images/netboot/debian-installer/amd64/linux
wget https://deb.debian.org/debian/dists/bookworm/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz
sudo cp linux /var/lib/tftpboot/images/debian12/vmlinuz
sudo cp initrd.gz /var/lib/tftpboot/images/debian12/initrd

步骤 4:配置 Dnsmasq 支持 PXE

sudo tee /etc/dnsmasq.d/20-pxe.conf <<'EOF'
# DHCP 接口
interface=eth1
bind-interfaces

# DHCP 地址池
dhcp-range=192.168.1.100,192.168.1.200,255.255.255.0,12h

# 启用 TFTP
enable-tftp
tftp-root=/var/lib/tftpboot
tftp-secure

# BIOS PXE 引导
dhcp-boot=pxelinux.0,,192.168.1.1

# 权威 DHCP
dhcp-authoritative
log-dhcp
EOF

步骤 5:测试

# 重启 Dnsmasq
sudo systemctl restart dnsmasq

# 用 QEMU 测试 PXE 引动(无需物理机器)
sudo apt install qemu-system-x86
qemu-system-x86_64 -m 2048 -net nic -net user -boot n

5.3.3 UEFI 引导配置

现代计算机使用 UEFI 引导,需要不同的启动文件:

# 安装 GRUB EFI 引导文件
sudo apt install grub-efi-amd64-signed shim-signed

# 复制 EFI 引导文件
sudo cp /usr/lib/shim/shimx64.efi.signed.latest /var/lib/tftpboot/shimx64.efi
sudo cp /usr/lib/grub/x86_64-efi-signed/grubnetx64.efi.signed /var/lib/tftpboot/grubx64.efi

# 创建 GRUB 配置
sudo tee /var/lib/tftpboot/grub/grub.cfg <<'EOF'
set timeout=5
set default=0

menuentry "Install Ubuntu 22.04" {
  linux images/ubuntu2204/vmlinuz ip=dhcp url=http://192.168.1.1/ubuntu-22.04-live-server-amd64.iso autoinstall
  initrd images/ubuntu2204/initrd
}

menuentry "Install Debian 12" {
  linux images/debian12/vmlinuz priority=critical
  initrd images/debian12/initrd
}

menuentry "Boot from local disk" {
  exit
}
EOF

更新 Dnsmasq 配置,区分 BIOS 和 UEFI:

sudo tee /etc/dnsmasq.d/21-pxe-uefi.conf <<'EOF'
# 区分 BIOS 和 UEFI 客户端
dhcp-match=set:bios,option:client-arch,0
dhcp-match=set:efi32,option:client-arch,6
dhcp-match=set:efi64,option:client-arch,7
dhcp-match=set:efi64,option:client-arch,9
dhcp-match=set:efiarm,option:client-arch,11

# BIOS 引导
dhcp-boot=tag:bios,pxelinux.0,,192.168.1.1

# UEFI x86-64 引导
dhcp-boot=tag:efi64,grubx64.efi,,192.168.1.1

# UEFI ARM64 引导
dhcp-boot=tag:efiarm,grubaa64.efi,,192.168.1.1

# 启用 TFTP
enable-tftp
tftp-root=/var/lib/tftpboot
tftp-secure
EOF

5.4 网络操作系统安装

5.4.1 Ubuntu 自动化安装(Autoinstall)

# 创建 autoinstall 配置
sudo mkdir -p /var/www/html/autoinstall

sudo tee /var/www/html/autoinstall/user-data <<'EOF'
#cloud-config
autoinstall:
  version: 1
  locale: zh_CN.UTF-8
  keyboard:
    layout: cn
  network:
    version: 2
    ethernets:
      ens33:
        dhcp4: true
  identity:
    hostname: ubuntu-server
    username: admin
    password: "$6$rounds=4096$..."  # mkpasswd --method=sha-512
  ssh:
    install-server: true
  storage:
    layout:
      name: lvm
  packages:
    - vim
    - htop
    - net-tools
EOF

sudo touch /var/www/html/autoinstall/meta-data

更新 PXE 菜单:

LABEL ubuntu-auto
  MENU LABEL Auto Install Ubuntu 22.04
  KERNEL images/ubuntu2204/vmlinuz
  INITRD images/ubuntu2204/initrd
  APPEND ip=dhcp autoinstall ds=nocloud-net\;s=http://192.168.1.1/autoinstall/

5.4.2 Debian 预置安装(Preseed)

sudo tee /var/www/html/debian-preseed.cfg <<'EOF'
# 语言和地区
d-i debian-installer/locale string zh_CN.UTF-8
d-i keyboard-configuration/xkb-keymap select cn

# 网络
d-i netcfg/choose_interface select auto
d-i netcfg/get_hostname string debian-server

# 磁盘分区
d-i partman-auto/method string lvm
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-auto-lvm/guided_size string max

# 用户
d-i passwd/root-login boolean false
d-i passwd/user-fullname string Admin
d-i passwd/username string admin
d-i passwd/user-password-crypted password $6$rounds=4096$...

# 软件包
tasksel tasksel/first multiselect ssh-server
d-i pkgsel/include string vim htop net-tools

# GRUB
d-i grub-installer/only_debian boolean true
d-i grub-installer/bootdev string /dev/sda
EOF

5.4.3 CentOS Kickstart

sudo tee /var/www/html/centos9-ks.cfg <<'EOF'
# 安装选项
install
url --url="http://192.168.1.1/centos9/"
lang zh_CN.UTF-8
keyboard cn
network --bootproto=dhcp --device=eth0 --onboot=yes
rootpw --iscrypted $6$rounds=4096$...
firewall --disabled
selinux --permissive
timezone Asia/Shanghai --utc

# 磁盘分区
clearpart --all --initlabel
autopart --type=lvm

# 软件包
%packages
@core
vim-enhanced
htop
net-tools
%end

# 安装后脚本
%post
echo "Installation completed" > /root/install.log
%end

# 引导加载器
bootloader --location=mbr
EOF

5.5 无盘工作站

5.5.1 无盘工作站架构

┌────────────┐  PXE/TFTP/NFS  ┌────────────────┐
│ 无盘客户端  │←──────────────→│ Dnsmasq 服务器  │
│            │                │ DHCP + TFTP     │
└────────────┘                │ + NFS Root      │
                              └────────────────┘

5.5.2 配置 NFS 根文件系统

# 安装 NFS 服务器
sudo apt install nfs-kernel-server

# 创建根文件系统
sudo mkdir -p /export/diskless/rootfs
sudo debootstrap --arch=amd64 jammy /export/diskless/rootfs http://mirrors.aliyun.com/ubuntu

# 配置 NFS 导出
echo "/export/diskless/rootfs *(rw,no_root_squash,async,no_subtree_check)" | sudo tee -a /etc/exports
sudo exportfs -rv

# 配置无盘引导内核参数
# 在 PXE 菜单中添加:
LABEL diskless
  MENU LABEL Diskless Workstation
  KERNEL images/ubuntu2204/vmlinuz
  INITRD images/ubuntu2204/initrd
  APPEND root=/dev/nfs nfsroot=192.168.1.1:/export/diskless/rootfs ip=dhcp rw

5.5.3 为无盘客户端配置独立 hosts

# 为每个无盘客户端分配固定 IP 和主机名
sudo tee /etc/dnsmasq.d/22-diskless.conf <<'EOF'
dhcp-host=00:0c:29:aa:bb:01,192.168.1.201,diskless-01,infinite
dhcp-host=00:0c:29:aa:bb:02,192.168.1.202,diskless-02,infinite
dhcp-host=00:0c:29:aa:bb:03,192.168.1.203,diskless-03,infinite
EOF

5.6 固件升级

5.6.1 路由器固件升级

# 部分嵌入式设备支持通过 TFTP 恢复/升级固件

# 将固件放入 TFTP 根目录
sudo cp firmware.bin /var/lib/tftpboot/

# 设备通常在启动时尝试从 TFTP 下载固定名称的文件
# 例如 OpenWrt 路由器会查找:
# - tp_recovery.bin (TP-Link)
# - openwrt.bin

5.7 TFTP 安全配置

# /etc/dnsmasq.d/23-tftp-security.conf

# 限制 TFTP 只读访问
tftp-secure

# 限制 TFTP 只在特定接口可用
# (通过 bind-interfaces 和 interface 控制)

# 为不同客户端提供不同的文件
tftp-unique-root=mac   # 基于 MAC 地址
# tftp-unique-root=ip  # 基于 IP 地址

# 使用 tftp-lowercase 兼容大小写不敏感的客户端
tftp-lowercase

# 限制最大文件大小(Dnsmasq 2.85+)
# tftp-max=50M

警告:TFTP 不提供认证和加密,不应用于传输敏感文件。在生产环境中,TFTP 应仅在内网使用,并通过防火墙限制访问。

5.8 TFTP 性能调优

5.8.1 提高传输速度

# Dnsmasq 的 TFTP 实现较简单,不支持 blocksize 扩展
# 对于大型文件,建议使用 HTTP 替代 TFTP

# 方案 1:混合方案 - 小文件用 TFTP,大文件用 HTTP
# PXE 引导文件(pxelinux.0, vmlinuz, initrd)通过 TFTP
# 安装镜像通过 HTTP

# 方案 2:使用 atftpd 替代 Dnsmasq 的 TFTP
# sudo apt install atftpd
# 支持更大的 blocksize,传输速度更快

5.8.2 HTTP 引导替代方案

UEFI HTTP Boot 是 TFTP 的现代替代方案:

# 配置 Dnsmasq 为 UEFI 客户端提供 HTTP 引导
dhcp-match=set:httpclient,option:client-arch,9
dhcp-boot=tag:httpclient,http://192.168.1.1/grub/grubx64.efi,,192.168.1.1

# 在 HTTP 服务器上托管引导文件
# nginx 或 apache 的文档根目录指向 /var/lib/tftpboot/

5.9 完整 TFTP + PXE 配置示例

# /etc/dnsmasq.d/20-pxe-full.conf

# === DHCP 基础 ===
interface=eth1
bind-interfaces
dhcp-range=192.168.1.100,192.168.1.200,255.255.255.0,12h
dhcp-option=option:router,192.168.1.1
dhcp-option=option:dns-server,192.168.1.1
dhcp-authoritative

# === TFTP 配置 ===
enable-tftp
tftp-root=/var/lib/tftpboot
tftp-secure

# === PXE 引导 - BIOS ===
dhcp-match=set:bios,option:client-arch,0
dhcp-boot=tag:bios,pxelinux.0,,192.168.1.1

# === PXE 引导 - UEFI 64位 ===
dhcp-match=set:efi64,option:client-arch,7
dhcp-match=set:efi64,option:client-arch,9
dhcp-boot=tag:efi64,grubx64.efi,,192.168.1.1

# === 日志 ===
log-dhcp
log-queries
log-facility=/var/log/dnsmasq/dnsmasq.log

5.10 小结

功能 关键配置项 说明
启用 TFTP enable-tftp 激活 TFTP 服务
根目录 tftp-root= TFTP 文件存放路径
BIOS 引导 dhcp-boot=pxelinux.0 PXELINUX 引导
UEFI 引导 dhcp-boot=grubx64.efi GRUB EFI 引导
安全 tftp-secure 限制根目录访问
多引导 dhcp-match + dhcp-boot 区分 BIOS/UEFI

5.11 扩展阅读