无盘 Linux X 终端

作者:Chip Coldwell

X 终端并非新概念;NCD 等公司生产 X 终端已超过 15 年。然而,在 1990 年代后期,瘦客户端的概念逐渐过时,因为 PC 硬件的价格降得如此之低,以至于使用 X 终端不再具有明显的成本优势。关于瘦客户端与 PC 的总体拥有成本(包括硬件成本和管理支持)的激烈争论随之而来,而本文不会解决这场辩论。本文的目的仅仅是描述一种技术,该技术允许人们利用不断增长的废旧硬件(在 PC 技术进步的浪潮中遗留下来的)来构建 X 终端。

任何瘦客户端的基本特征是它应该几乎没有或没有持久存储。通常,专用 X 终端具有少量 NVRAM,用于存储配置选项,除此之外别无其他。实际上,通常甚至可以将这些选项放在存储在服务器上的配置文件中,并在终端启动时由终端下载。本文采用纯粹主义的观点,即 X 终端应该没有任何持久存储。

PXE 启动

PC 没有硬盘、软盘或 CD-ROM 驱动器,因此必须由其他设备提供引导加载程序和可引导映像。X 终端是其所处网络的产物,因此显而易见的选择是网络接口卡 (NIC)。因此,NIC 必须向 BIOS 标识自身为可引导设备。如果被选中,它必须能够从网络下载引导加载程序。这不是大多数普通 NIC 可以做到的。但是,Intel 发布了一个名为 PXE(预启动执行环境,发音为 pixie)的 NIC 引导 ROM 标准,并且该公司以及其他一些供应商在某些产品中也实现了该标准。许多带有内置以太网的新型主板都支持 PXE。

在准备本文时,我测试了五种不同的 NIC,所有这些 NIC 都声称支持 PXE:Intel PRO/100+ (PILA8460BNG1)、3Com 3C905CX-TX-M、D-Link DFE-550TX、Linksys LNE100TX 和 SMC 1255TX(Tulip 芯片组)。在这五种卡中,只有 3Com 卡开箱即用。我能够为 SMC 卡单独获得一个引导 ROM,之后它也能正常工作。其他三张卡都有明显的但空置的引导 ROM 插槽,这些插槽默认情况下未发货。买者自慎。

当 PXE NIC 被主板 BIOS 选为启动设备时,它会在 LAN 上广播 DHCP 请求,并在收到的响应中查找 PXE 扩展。如果它收到包含其中一些扩展的响应,则它会确认并接受该响应。特别是,它尊重服务器响应中的 next-server 和 filename 参数。这些参数指定 TFTP 服务器的 IP 地址以及包含客户端应下载并启动的引导加载程序的文件名。

DHCP 和 TFTP

Internet 软件联盟的版本 3.0 DHCP 服务器可以配置为通告 PXE 扩展,它是随许多 Linux 发行版(包括 Red Hat 8.0 和更高版本)一起提供的 DHCP 服务器。列表 1 是一个 DHCP 服务器配置文件 dhcpd.conf 的示例,当 DHCP 客户端将自身标识为 PXE NIC 时,该文件会生成带有 PXE 扩展的 DHCP 响应。使用此配置,客户端从位于 192.168.1.1 的 TFTP 服务器下载文件 pxelinux.0。表 1 列出了配置文件中设置的选项。

表 1. dhcpd.conf 中 PXE 特定代码的定义

代码含义
1引导文件服务器的多播 IP 地址。
2客户端应监视 MTFTP 响应的 UDP 端口。
3MTFTP 服务器正在使用的用于侦听 MTFTP 请求的 UDP 端口。
4客户端在尝试启动新的 MTFTP 传输之前必须侦听活动的时间(秒)。
5客户端在尝试重新启动 MTFTP 传输之前必须侦听的时间(秒)。

列表 1. 支持 PXE 客户端的 dhcpd.conf 文件示例

option space PXE;
option PXE.mtftp-ip
  code 1 = ip-address;
option PXE.mtftp-cport
  code 2 = unsigned integer 16;
option PXE.mtftp-sport
  code 3 = unsigned integer 16;
option PXE.mtftp-tmout
  code 4 = unsigned integer 8;
option PXE.mtftp-delay
  code 5 = unsigned integer 8;
option PXE.discovery-control
  code 6 = unsigned integer 8;
option PXE.discovery-mcast-addr
  code 7 = ip-address;

subnet 192.168.1.0 netmask 255.255.255.0 {

  class "pxeclients" {
    match if substring (option
      vendor-class-identifier, 0, 9) = "PXEClient";
    option vendor-class-identifier "PXEClient";
    vendor-option-space PXE;

    # At least one of the vendor-specific PXE
    # options must be set in order for the client
    # boot ROMs to realize that this is a PXE-
    # compliant server. We set the MCAST IP address
    # to 0.0.0.0 to tell the boot ROM that we can't
    # provide multicast TFTP.

    option PXE.mtftp-ip 0.0.0.0;

    # This is the name of the file the boot ROMs
    # should download.
    filename "pxelinux.0";
    # This is the name of the server they should
    # get it from.
    next-server 192.168.1.1;
  }

  pool {
    max-lease-time 86400;
    default-lease-time 86400;
    range 192.168.1.2 192.168.1.254;

   # If you include this, you must provide host
   # entries for every client, optionally associating
   # ethernet MAC addresses with IP addresses.

   # deny unknown clients;
  }
}

显然,必须将 192.168.1.1 的服务器配置为提供 TFTP 服务。它还必须有一个名为 pxelinux.0 的引导加载程序映像,TFTP 服务器进程会在其中查找它(通常在 /tftpboot 目录中)。TFTP 服务器进程通常由超级服务器 inetd 或 xinetd 之一管理,因此启用它意味着要修改它们的配置文件之一(分别为 /etc/inetd.conf 或 /etc/xinetd.conf)。

文件 pxelinux.0 是来自 H. Peter Anvin 的 SYSLINUX 项目的引导加载程序。与通用引导加载程序(如 LILO 或 GRUB)不同,PXELINUX 了解 PXE 协议,并且具有必要的网络功能,可以通过使用 TFTP 下载内核和压缩的 RAM 磁盘来在此处接管引导过程。但是,PXELINUX 需要增强的 TFTP 服务器,该服务器应了解 TSIZE 选项 (RFC 2349)。幸运的是,H. Peter Anvin 还提供了一个修改后的标准 BSD TFTP 守护程序版本,名为 tftp-hpa,它确实支持此选项。最简单的方法是将标准 TFTP 守护程序(通常位于 /usr/sbin/in.tftpd)替换为 tftp-hpa。

PXELINUX

PXELINUX 知道 PXE 引导 ROM 将来自 DHCP 服务器响应的网络参数存放在内存中的位置,并且可以使用这些参数启动另一个 TFTP 会话,以从服务器下载其配置文件。在 TFTP 服务器配置如上所述的情况下,客户端上运行的引导加载程序首先尝试在 /tftpboot/pxelinux.cfg/ethermac 中查找其配置文件,其中 ethermac 表示客户端的以太网硬件地址,采用小写十六进制,八位字节之间用连字符分隔,例如 fe-ed-de-ad-be-ef。如果失败,引导加载程序将尝试 /tftpboot/pxelinux.cfg/iphex,其中 iphex 是客户端的 IP 地址,采用大写十六进制。例如,如果客户端的 IP 地址为 192.168.0.12,则 PXELINUX 将尝试下载文件 /tftpboot/pxelinux.cfg/C0A8000C。如果该文件不存在,则从名称中删除最低有效半字节,然后重复该过程。因此,在上面的示例中,在找不到 C0A8000C 之后,PXELINUX 将尝试 C0A8000,然后 C0A800,依此类推。这使得为整个子网使用单个配置文件成为可能,前提是子网边界与半字节对齐。

列表 2 显示了 PXELINUX 配置文件的内容。第一行给出了一个文件的名称,该文件包含要下载的压缩内核映像 - 所有路径都相对于服务器上的 /tftpboot。第二行列出了应传递给内核的参数,指定根文件系统应为 64MB RAM 磁盘,应以读/写方式挂载。最后一行导致 PXELINUX 生成一个附加的内核参数,其中包含ip=client-ip:server-ip:gateway-ip:netmask并使用 PXE 引导 ROM 从 DHCP 服务器的响应中获得的值。如果内核是在启用了 IP 网络内核级自动配置的情况下构建的,这将非常有用。如果是这样,当内核启动时,它会使用这些参数来配置网络接口,从而无需在启动脚本中使用 ifconfig 或 ifup 来执行此操作。

列表 2. PXELINUX 配置文件指定要下载的压缩内核映像。

DEFAULT vmlinuz
APPEND initrd=ramdisk.gz ramdisk=65536 root=/dev/ram rw
IPAPPEND 1
构建内核

为了使用 IP 参数的内核级自动配置,网络设备驱动程序必须在启动早期就可用,甚至在挂载根文件系统之前。因此,它不能是可加载模块。由于大多数发行版附带的内核广泛使用可加载模块,因此实际上这意味着有必要为 X 终端构建自定义内核。此外,自定义内核应支持 RAM 磁盘和初始 RAM 磁盘。IP 网络内核级自动配置也很方便。没有必要包含任何获取 IP 地址的动态方法(可以选择 DHCP、BOOTP 和 RARP),但是,由于 PXELINUX 配置文件中包含的 IPAPPEND 行确保内核接收到正确的 IP 参数。最后,设备文件系统支持以及启动时自动挂载的 devfs 大大简化了 RAM 磁盘根文件系统中的 /dev 目录。

RAM 磁盘根文件系统

如果不是因为 Richard Gooch 的设备文件系统和 Erik Anderson 的 BusyBox 组合二进制文件的出现,那么构建和填充根文件系统将是设置无盘 Linux 盒最复杂的部分。设备文件系统自动管理 /dev 目录,根据内核中加载的设备需要创建设备入口点。这意味着两件事:目录中没有不必要的条目,RAM 磁盘根文件系统的构建者不必花费数小时使用 mknod 尝试创建所有需要的设备入口点。BusyBox 组合二进制文件是一个可执行文件,它根据其调用方式更改其个性。通常的方法是从 /bin/ls、/bin/cat、/bin/ps、/sbin/mount 等创建指向 /bin/busybox 的符号链接,以创建一个极简主义的 UNIX 系统。不需要额外的库或二进制文件;BusyBox 将它们整合到一个文件中。

考虑此设置的一种方法是,设备文件系统负责 /dev;BusyBox 负责 /bin 和 /sbin;内核负责 /proc;只读 NFS 挂载负责 /usr;/tmp 可以为空。因此,您需要担心的只是 /etc。实际上,/etc 可以非常简约,仅包含 /etc/fstab、/etc/inittab 和 /etc/init.d/rcS,后者是 BusyBox 作为 init 运行时使用的单个启动脚本。

BusyBox 是为嵌入式 Linux 世界编写的,通常会构建为静态可执行文件。但是,XFree86 服务器本身依赖于许多通常在 /lib 中找到的共享库。我们将要 NFS 挂载 /usr,因此我们不必担心在 /usr/lib 中找到的共享库,但我们确实必须提供 XFree86 希望在 /lib 中找到的共享库。因此,我们不妨利用通过将 BusyBox 配置为动态可执行文件而实现的节省空间。运行以下命令可以发现 /lib 中运行 XFree86 所需的最小库ldd /usr/X11R6/bin/XFree86。它们是 glibc (libc.so 和 libm.so)、PAM (libpam.so 和 libpam_misc.so) 以及动态加载器本身 (libdl.so 和 ld-linux.so)。

配置 XFree86

XFree86 可执行文件通常在 /usr/X11R6/bin 中找到,它是 /usr 的子目录。那么我们不需要在 RAM 磁盘中提供 X 服务器,而是可以从 NFS 挂载中获取它。虽然模块化 XFree86 服务器本身自大约 4.0 版本以来就不是特定于硬件的,但其配置文件肯定是。如果您管理着具有不同视频硬件的多个 X 终端,则不可能对所有终端使用相同的 XF86Config 文件。因此,我们不希望将其保存在 RAM 磁盘根文件系统中,它通常会在 /etc/X11/XF86Config 中找到。相反,我们可以使用存储在 NFS /usr 目录中的每个终端的配置文件。最终,BusyBox init 进程被配置为连续重生一个 shell 脚本,其中包含单行

/usr/X11R6/bin/XFree86 \
-xf86config /usr/X11R6/configs/iphex -query \
server

其中 iphex 是客户端的 IP 地址,采用十六进制(借用自 PXELINUX 的命名约定),server 是服务器的 IP 地址,采用点分十进制。通过一些巧妙的 awk-on-/proc/cmdline 技巧,我们可以完全避免将任何主机名或 IP 地址硬编码到 RAM 磁盘映像中。

可以通过在终端上运行以下命令来创建基本的 XFree86 配置文件XFree86 -configure。一般来说,这可以正确识别视频硬件,并且生成的配置文件会加载适当的 XFree86 模块。但是,值得一提的是,默认的指针设备 /dev/mouse 通常在使用设备文件系统的系统上不存在。例如,PS/2 鼠标在 /dev/misc/psaux 中找到。

服务器端配置

使 X 终端成为 X 终端而不是带有图形显示的 Linux 盒子的部分是-query server上面 XFree86 命令行的一部分。这会导致终端上的 XFree86 服务器运行 XDMCP(X 显示管理器控制协议)会话,以尝试让服务器管理其显示。但是,并非每个服务器都会同意这样做。

首先,也是最明显的,服务器必须侦听传入的 XDMCP 连接。XDMCP 通常在 UDP 端口 177 上,并且大多数显示管理器(xdm、gdm、kdm)都可以配置为侦听 XDMCP 请求。虽然大多数发行版都配置为在启动时运行显示管理器,但出于安全考虑,大多数发行版都不侦听传入的 XDMCP 请求。例如,经典的 X 显示管理器 xdm 通常随行一起分发

DisplayManager.requestPort: 0

在其配置文件(通常为 /etc/X11/xdm/xdm-config)中。必须注释掉此行,xdm 才能接受 XDMCP 请求。此外,可以使用配置文件 /etc/X11/xdm/Xaccess(不要与 /etc/X11/xdm/Xservers 混淆,后者在很大程度上是历史遗留物)将 xdm 限制为每个主机或每个子网的连接。例如,要将 xdm 限制为 192.168.1.0/24 子网中的终端,请在 /etc/X11/xdm/Xaccess 的末尾添加一行,其中仅包含 192.168.1.0/24。

此外,如果服务器还通过 X 字体服务器进程 xfs 向终端提供字体,则会很方便。再次强调,虽然大多数发行版都运行字体服务器进程,但通常配置为不侦听传入的请求。例如,xfs 的配置文件 /etc/X11/fs/config 通常包含行no-listen = tcp。如果注释掉此行,则终端的 XF86Config 文件(存储在服务器上的 /usr/X11R6/configs/iphex 中)的 Files 部分可以仅包含一个 FontPath 而不是通常的六个,如列表 3 所示(其中假定服务器 IP 为 192.168.1.1)。

列表 3. 终端 XF86Config 片段

Section "Files"
        RgbPath      "/usr/X11R6/lib/X11/rgb"
        ModulePath   "/usr/X11R6/lib/modules"
        FontPath     "tcp/192.168.1.1:7100"
EndSection

最后,必须将服务器配置为将 /usr 文件系统以只读方式 NFS 导出到终端,因为终端从这里获取 XFree86 服务器。

关于安全性的一些说明

运行 X 终端时,应牢记一些安全注意事项。首先,应该很明显,对 xdm 和 xfs 配置所做的更改正在撤消为提高服务器安全性而完成的操作。此外,本文中描述的设置不加密任何流量。终端上的每个击键都通过未加密的网络传输。运行 X 终端的唯一合理安全的方式是将它们全部放在仅供 X 终端使用的专用 LAN 上,并且该 LAN 不路由到 Internet。终端和服务器上的一个接口应该是终端 LAN 上唯一的接口。

套件可用

由于印刷媒体的空间限制,本文从较高层面介绍了如何配置 Linux 盒子以无盘启动并成为 X 终端,而没有详细介绍精确的实现。鼓励感兴趣的读者从作者的网站下载 X 终端套件;它包括 shell 脚本、Makefile 和 README,以指导您完成有时很复杂的过程。此外,本文中描述的软件来自互联网上的众多资源,所有这些资源都提供了有关其特定软件包的更详细信息。请参阅在线资源以获取指针。

本文的资源: www.linuxjournal.com/article/7924

Chip Coldwell (coldwell@physics.harvard.edu) 是哈佛大学物理系的系统管理员。当他不摆弄各种计算机时,他通常会骑自行车或享受未婚妻 Cindy 的陪伴。

加载 Disqus 评论