TCFS:透明加密文件系统
当前的网络技术使得通过网络共享资源变得廉价而方便。通常,计算机网络由一台直接访问资源(文件系统、打印机、CPU 时间)的服务器组成。然后,服务器允许多个客户端访问该资源。文件系统是一种典型的可以通过网络共享的资源,而 Sun 公司的 NFS 是最广泛使用的文件系统共享协议。NFS 的一个重要特性是对使用它的应用程序完全透明。应用程序无需知道它访问的是本地文件系统上的文件还是通过网络共享的文件系统上的文件。
NFS 是 Sun 公司多年前设计的,但它没有解决在这种情况下出现的安全问题。NFS 结构简单,并假设了一种强信任模型:即用户信任远程文件系统服务器和网络上的数据安全。这带来了一些风险。服务器上的数据对服务器超级用户是可用的;此外,网络上的用户可能会通过更改其 IP 地址或用户 ID 来冒充其他身份,从而允许在数据在网络上传输时被读取。因此,有必要通过保护存储在远程服务器上和网络传输过程中的数据来解决安全问题。
TCFS(透明加密文件系统)是在意大利萨莱诺大学信息与应用系开发的,目前可用于 Linux。您可以将 TCFS 视为扩展的 NFS。它的作用类似于 NFS,但允许用户使用加密来保护其文件。
TCFS 需要运行 Linux 和 EXT2 文件系统的 NFS 服务器。它必须与 2.0.x 内核一起使用,因为它基于 Olaf Kirch 的 NFS 模块。TCFS 可以用作内核模块(并使用 insmod 实用程序插入)或编译到内核中。当您启动 TCFS 模块或启动时(如果 TCFS 是静态链接的),您会发现四个 tcfsiod 守护进程正在运行。
TCFS 在 VFS(虚拟文件系统交换)层下作为一个层工作,使其对应用程序完全透明。安全性通过 DES(数据加密标准)算法来保证。密钥保存在一个特殊的数据库 (/etc/tcfspasswd) 中,该数据库存储使用用户登录密码加密的密钥。为了最大限度地提高安全性,最好将受信任实体的数量保持在最低限度。TCFS 用户只需要信任内核和访问数据的客户端机器的超级用户。我们强调,这种最低程度的信任是必要的,因为您无法保护您的数据免受内核和超级用户的侵害。两者都可以随时访问内存。我们的信任模型非常适合 TCFS 的典型使用场景:工作站网络磁盘空间有限,每个工作站几乎只供有限数量的用户使用(您甚至可以将每个用户视为其自身工作站的超级用户),以及一个远程文件服务器与所有工作站共享文件。
在设计 TCFS 时,我们有兴趣以尽可能低的成本为用户提供强大的安全机制。安全机制必须保证安全文件不可读
对于合法所有者以外的任何用户,
通过窃听用户和远程文件系统服务器之间的通信线路,
通过文件系统服务器的超级用户。
我们还保护敏感的元数据——对于每个文件;不仅内容被加密,文件名也被加密。我们使用链接块密码中的 DES 隐藏内部文件数据依赖关系。
在 TCFS 中,安全性以透明的方式发挥作用。安全文件的访问方式与本地文件相同——用户只需在开始工作之前向 TCFS 验证身份。一个特殊的标志,看起来像 EXT2 扩展属性,标记加密文件,使其与未加密文件区分开来。因此,TCFS 能够将安全文件和不安全文件都存储在同一文件系统上,具体取决于是否设置了此标志。
我们特别关注使 TCFS 对文件服务器完全透明。透明性允许服务器上的超级用户执行所有管理职责,因为我们不更改文件系统本身的数据结构。对于启用安全标志的目录,需要进行特殊处理。安全目录中的文件以加密文件名存储,新文件继承安全标志,因此它们也是安全的。由于 TCFS 在 VFS(虚拟文件系统)层中充当文件系统,因此可以使用标准系统调用来访问 TCFS 上的文件。open() 或 create() 系统调用不需要特殊标志。因此,所有应用程序都可以使用新功能而无需重新编译。
为了解释 TCFS 的机制,我们将首先回顾 NFS 的工作原理。NFS 是一个简单的分布式文件系统,它允许文件系统服务器将其文件系统 导出 到多个客户端。在客户端上运行的应用程序通过常用的系统调用访问远程文件系统。客户端内核检查请求的数据是在本地文件系统上还是在 NFS 文件系统上。在后一种情况下,内核向服务器发出请求;例如,如果应用程序需要从远程文件系统上的文件中读取一个块,客户端操作系统会向服务器发出读取请求。服务器在收到读取请求后,从其本地文件系统中读取数据并将其发送到客户端,然后客户端将数据传递给应用程序。重要的是要记住,NFS 提供了一种最基本的用户身份验证形式。服务器从客户端接收请求数据的用户的 uid,并检查该用户是否被允许访问包含数据的文件。因此,用户可以在客户端上更改其 uid(例如,客户端机器的超级用户可以使用命令 su 成为任何用户)或修改 NFS 客户端,以便在请求中提供不同的 uid。
当使用 TCFS 时,文件可以以加密形式存储在服务器文件系统上,每个用户使用不同的加密密钥。加密密钥由用户通过 tcfslogin 实用程序提供给 TCFS 客户端。(TCFS 实用程序的详细描述见下文。)从服务器读取数据块是按照 NFS 协议实现的,但有一个重要的例外:一旦请求的块被 TCFS 客户端接收,它会在传递给应用程序之前被解密。同样,应用程序写入的数据块在使用用户的密钥加密后才会被传递到 TCFS 服务器。在读取或写入操作期间,用户的加密密钥永远不会离开 TCFS 客户端,并且数据在服务器和客户端之间仅以加密形式传输。此外,这种方法解决了与用户身份验证相关的问题。虽然用户仍然可以冒充文件的合法所有者,但他只会收到加密数据。
像设置 NFS 服务器一样设置您的 TCFS 服务器——通过导出您希望与客户端共享的文件系统。通常,这是通过编辑 /etc/exports 文件并重启 NFS 守护进程 (rpc.mountd, rpc.nfsd) 来完成的。
从 TCFS 包中检索 xattrd。它可以在 TCFS 发行版的 linux/fs/tcfs/contrib/xattrd 目录中找到。将 xattrd 复制到守护进程目录,通常是 /usr/sbin,并将其添加到您的 rc 文件中。对于 Slackware 发行版,编辑 /etc/rc.d/rc.inet2 文件,使其看起来像 列表 1. rc.inet2 文件。
对于 Red Hat 或任何其他使用 System V init 脚本模型的发行版,在 rc 目录(Red Hat 4 中为 /etc/rc.d/init.d)中创建一个文件,用于启动和停止 xattrd 守护进程,并在 rc\#.d 目录中创建符号链接以启动它。在 Red Hat 中,您可以使用 tksysv 脚本执行此操作。有关构建 xattrd rc 脚本的示例,请参阅 列表 2. 用于构建 xattrd 脚本的文件。
现在,重启系统或以 root 身份运行 xattrd 以准备服务器以支持 TCFS。请注意,xattrd 在启动时读取 /etc/exports,因此如果您更改 /etc/exports,则必须重启 xattrd。xattrd 为 NFS 服务器添加了功能,并非旨在取代它;因此,可以将同一服务器同时用作 TCFS 服务器和 NFS 服务器。
在客户端上安装 TCFS 有些复杂,因为大部分工作由客户端执行——必须重建内核以支持 TCFS。
TCFS 发行版提供了一个 tar 文件,需要在 /usr/src 目录中解压缩。我们假设内核源代码位于 /usr/src/linux 目录中(这是大多数 Linux 发行版的标准)。按照以下步骤安装 TCFS
解压 TCFS 以创建目录 /usr/src/linux/fs/tcfs,其中包含 TCFS 及其相关实用程序的代码。
将 /usr/src/linux/fs/tcfs/patches 中找到的 tcfs.diff 补丁应用于内核。通过将目录更改为 /usr/src,然后键入 patch < linux/fs/tcfs/patches/tcfs.diff 来执行此操作。
重新编译内核。在 FileSystem 部分,系统会询问您有关 TCFS 的信息。可以将 tcfs 安装为模块或内置模块。在这两种情况下,都需要按照通常的步骤重新编译内核。
安装实用程序。安装了支持 TCFS 的内核后,将目录更改为 /usr/src/linux/fs/tcfs/contrib/binaries,您将在其中找到 TCFS 实用程序的二进制文件,然后键入 make<\!s>install。也可以编译位于 /usr/src/linux/fs/tcfs/contrib/src 中的 TCFS 实用程序的源代码。
启用 TCFS 的使用。客户端的超级用户必须使用 tcfsgenkey 实用程序为每个用户生成密钥。这需要用户的密码,因此必须在用户的帮助下完成。tcfsgenkey 实用程序构建一个数据库 (/etc/tcfspasswd),其中存储用于加密文件的密钥。这些密钥使用用户的登录密码作为密钥进行加密保存。在 TCFS 的未来版本中,我们计划提供对智能卡的支持,从而无需将密钥(即使是以加密形式)保存在客户端上。
TCFS 实用程序。TCFS 提供的 mount 命令能够处理 TCFS 挂载操作。我们建议您使用我们的 mount 版本来代替标准的 mount 命令,因为 TCFS 需要标准 mount 未提供的一些信息。要使用 TCFS 挂载文件系统,请键入
mount -t tcfs server:/remotepath /localpath
TCFS 还提供了 passwd 命令,用于更新加密密钥数据库。它的作用类似于标准的 passwd 命令,但在更改密码后也会更新 tcfspasswd 文件。使用旧的 passwd 命令更改密码将导致从 /etc/tcfspasswd 中提取错误的加密密钥,从而导致数据完全丢失。
登录后,每个用户都必须执行 tcfslogin。tcfslogin 实用程序请求用户的登录密码以解密加密密钥,并将密码密钥推送到内核模块中。要删除密钥,用户必须执行 tcfslogout 实用程序,这需要挂载 TCFS 文件系统才能工作。在未来的版本中,我们计划包含对 PAM(可插拔身份验证模块)的支持,从而无需两次输入登录密码。
lsattr 和 chattr 命令的作用与在 EXT2 中相同。TCFS 版本支持一个新标志 X,用于启用文件加密。您可以通过键入以下命令来更改文件的状态(加密或解密)
chattr $ <+|-> $X
假设您有一个名为 foo 的服务器和一个名为 bar 的客户端,并且假设您从服务器 foo 将名为 /exports 的目录树导出到客户端 bar。为了实现这一点,foo 必须在 /etc/exports 中包含以下行
/exports bar(rw,insecure)
现在,以 root 身份登录到 bar,并通过键入以下命令 mount /exports
mount -t tcfs foo:/exports /mnt/tcfs此命令使远程文件系统 /exports@foo 通过 TCFS 层挂载到本地文件系统 /mnt/tcfs@localhost 上。
现在,假设您的登录名是 usdm1,并且您拥有一个名为 /mnt/tcfs/usdm1 的目录。以 usdm1 身份登录到 bar 并执行 tcfslogin;这样做使您能够在目录 /mnt/tcfs/usdml 中使用加密。如果未发出 tcfslogin,则在尝试访问设置了 X 标志的文件时,将发出权限拒绝错误。
为了评估通过网络发送的数据加密引入的开销,我们进行了一系列测试。我们在以下框架中运行了测试
在 Linux 2.0.23 内核上运行 TCFS 的客户端机器是 Cyrix x686 166MHz 处理器
作为 NFS+xattrd 文件服务器运行的服务器机器是一台配备 2GB 快速 SCSI 磁盘的 Intel Pentium 133MHz 处理器。
由于加密/解密是一项 CPU 密集型任务,因此拥有快速客户端来执行加密可以获得更好的性能。TCFS 使用标准的 VFS 缓存——不需要特殊的缓存。
在 表 1 和 表 2 中显示的实时值是使用 time 命令获得的,读取操作设置了以下选项
time dd bs=xxx if=file of=/dev/null count=n
以及写入操作
time dd bs=xxx if=/dev/zero of=file count=n
表格显示以下结果
TCFS 写入操作的总体性能接近 NFS 性能加上 DES 开销。在写入操作中,由于缺少缓存系统,我们受到影响,因为数据直接写入服务器文件系统。
TCFS 读取操作的性能似乎隐藏了部分 DES 时间,因为 VFS 缓存减少了服务器 I/O。
由于处理扩展属性,TCFS 为未加密文件的 I/O 支付了一些额外的成本。在 NFS 中,需要多次 getattr 调用来更新 inode 缓存。在 TCFS 中,我们需要 getattr 和 geteattr 来更新 inode 缓存。这导致 TCFS I/O 中出现一些额外的开销。
使用其他密码将导致不同的性能。我们计划使用 IDEA、RC5 和其他密码作为 TCFS 的可选模块。
Ermelindo Mauriello (ermmaui@globenet.it) 于 1972 年 12 月 10 日出生于意大利阿韦利诺。他是意大利萨莱诺大学 “Renato M. Capocelli” 信息与应用系的计算机科学专业的学生。自 1995 年以来,他一直致力于 TCFS 项目。