NFSv4 client identifier

本文档翻译自Documentation/filesystems/nfs/client-identifier.rst,翻译时文件的最新提交是d56b699d76d1 Documentation: Fix typos,大部分借助于ChatGPT翻译,仅作为我个人的参考,如果你想查阅,建议看英文文档,因为我不确定我记录的中文翻译是否完整和正确。

1 NFSv4客户端标识符

本文档解释了NFSv4协议如何标识客户端实例,以便在系统重新启动期间维护文件打开和锁定状态。每个客户端都维护一个特殊的标识符和主体。这些可以由管理员、站点管理员提供的脚本或Linux发行版提供的工具进行设置。

如果客户端的NFSv4标识符和其主体选择不当,存在风险。

1.1 介绍

NFSv4协议使用“基于租约的文件锁定”。租约有助于NFSv4服务器提供文件锁定保证并管理其资源。

简而言之,NFSv4服务器为每个NFSv4客户端创建一个租约。服务器在该租约下收集每个客户端的文件打开和锁定状态。

客户端负责定期更新其租约。在租约保持有效的同时,持有该租约的服务器保证客户端创建的文件锁定仍然有效。

如果客户端停止更新其租约(例如,如果崩溃),NFSv4协议允许服务器在一定时间后移除客户端的打开和锁定状态。当客户端重新启动时,它向服务器指示与其先前租约关联的打开和锁定状态不再有效,可以立即销毁。

此外,每个NFSv4服务器管理一个持久的客户端租约列表。当服务器重新启动并且客户端尝试恢复其状态时,服务器使用此列表来区分在服务器重新启动之前保留状态的客户端和发送新的OPEN和LOCK请求的客户端。这使文件锁定可以安全地持续存在于服务器重新启动之间。

1.2 NFSv4客户端标识符

每个NFSv4客户端向NFSv4服务器呈现一个标识符,以便它们可以将客户端与其租约关联起来。每个客户端的标识符包括两个元素:

NFSv4.0规范将这两个项目称为“nfs_client_id4”。NFSv4.1规范将这两个项目称为“client_owner4”。

NFSv4服务器将此标识符与客户端在呈现时使用的主体和安全方式绑定。服务器使用此主体来授权由客户端发送的后续租约修改操作。实际上,此主体是标识符的第三个元素。

作为呈现给服务器的标识,一个良好的“co_ownerid”字符串具有以下几个重要属性:

1.3 保护NFSv4租约状态

NFSv4服务器使用上述的“client_owner4”来分配给每个客户端一个唯一的租约。在此方案下,存在客户端可能相互干扰的情况。这被称为“租约窃取”。

如果不同的客户端呈现相同的“co_ownerid”字符串并使用相同的主体(例如,AUTH_SYS和UID 0),服务器将无法判断这两个客户端是否相同。每个不同的客户端呈现不同的引导验证器,因此对服务器来说,就好像有一个客户端频繁重新引导。在这种情况下,任何一个客户端都无法维持打开或锁定状态。

如果不同的客户端呈现相同的“co_ownerid”字符串并使用不同的主体,服务器可能会允许第一个客户端正常操作,但拒绝具有相同“co_ownerid”字符串的后续客户端。

如果客户端的“co_ownerid”字符串或主体不稳定,则不能保证在服务器或客户端重新启动后可以恢复状态。如果客户端意外重新启动但向服务器呈现不同的“co_ownerid”字符串或主体,则服务器会孤立客户端先前的打开和锁定状态。这会阻止对锁定文件的访问,直到服务器删除孤立的状态。

如果服务器重新启动并且客户端向服务器呈现更改的“co_ownerid”字符串或主体,则服务器将不允许客户端重新获取其打开和锁定状态,并可能在此期间将这些锁定给其他客户端。这被称为“锁窃取”。

租约窃取和锁窃取增加了服务拒绝的潜在风险,甚至在极少数情况下可能导致数据损坏。

1.4 选择适当的客户端标识符

默认情况下,Linux NFSv4客户端实现使用以“Linux NFS”开头,后跟客户端的UTS节点名称(与AUTH_SYS凭据中的“机器名称”相同)构造其“co_ownerid”字符串。在小型部署中,此构造通常是足够的。然而,通常情况下,仅使用节点名称可能不足够唯一,并且可能会意外更改。存在问题的情况包括:

Linux提供了两种机制来向其“co_ownerid”字符串添加唯一性:

nfs.nfs4_unique_id

此模块参数可以通过内核命令行或加载“nfs”模块时设置任意的唯一标识字符串。

/sys/fs/nfs/net/nfs_client/identifier

此虚拟文件自Linux 5.3以来可用,仅在其所在的网络命名空间中可用,因此可以在主机名保持一致时提供对网络命名空间(容器)的区分。

请注意,此文件在命名空间创建时为空。如果容器系统可以访问某种每个容器身份,则可以使用该唯一标识符。例如,可以在引导时使用容器的内部标识符形成唯一标识符:

sha256sum /etc/machine-id | awk '{print $1}' \

> /sys/fs/nfs/net/nfs_client/identifier

1.5 安全注意事项

强烈鼓励对租约管理操作使用密码安全性。

如果未配置带有Kerberos的NFS,则Linux NFSv4客户端将使用AUTH_SYS和UID 0作为其客户端身份的主体部分。这种配置不仅不安全,还增加了租约和锁定窃取的风险。然而,在没有本地持久存储的客户端配置中,这可能是唯一的选择。“co_ownerid”字符串的唯一性和持久性在这种情况下至关重要。

当Linux NFS客户端上存在Kerberos keytab时,客户端会尝试在向服务器标识自己时使用该keytab中的主体之一。 "sec ="挂载选项不控制此行为。或者,具有Kerberos主体的单用户客户端可以在客户端的主机主体的位置使用该主体。

使用Kerberos进行此目的使客户端和服务器能够对所有“sec =”设置覆盖的操作使用相同的租约。此外,Linux NFS客户端使用Kerberos和完整性QOS的RPCSEC_GSS安全性类型,以防止对租约修改请求的传输修改。

1.6 附加说明

Linux NFSv4客户端在访问的每个NFSv4服务器上建立一个租约。然后,来自Linux NFSv4客户端的特定服务器的NFSv4挂载共享该租约。

一旦客户端建立了打开和锁定状态,NFSv4协议就使租约状态可以过渡到其他服务器,遵循已迁移的数据。这完全隐藏了正在运行的应用程序对数据迁移的感知。 Linux NFSv4客户端通过向遇到的所有服务器呈现相同的“client_owner4”来促进状态迁移。

2 参见