我正在尝试设置 NFSv4 客户端,但找不到有用的文档。
nfsidmap(5) 的手册页(碰巧,我关心的是客户端的 CentOS)描述了一个特定的工具,该工具在 idmapd.conf(5) 中配置,并为request-key
来自内核的上行调用提供服务。很好。
RFC 7530描述了底层协议,我可以使用 查看其内容tcpdump
。众所周知,NFSv4 通过字符串user@domain
而不是数字 UID 进行 uid/gid 管理,因此需要一种机制,在客户端和服务器端,根据双方的需要将这些名称映射到数字(可以在将数字 ID 作为字符串来回传递的模式下运行 NFSv4,但这似乎是不推荐的模式)。很好。
我苦苦挣扎的是,找不到中间的东西,无法更详细地了解正在发生的事情;我找不到任何东西来填补协议和关于如何配置特定工具的简洁文档之间的空白。我正在尝试做某事轻微地(非常轻微)非标准 – 见下文 – 我被卡住了。
我发现:
- 解释为何发生上调(这是我正在寻找的东西,但它太狭窄了),并且关于‘我正在和哪个守护进程对话?’的问题我在哪里找到了这个链接。
- 一个问题nfs4_disable_idmapping 参数到底起什么作用?这是一个相当绝望的恳求,显然是为了回应我发现的各种单行“随机调整这个参数”的答案,这些答案往往暗示“这对我有用”而没有太多的见解。
- A“为什么我需要 idmapd?”问题,答案只不过是上面的字符串与数字的解释。
- 关于这种字符串到 uid 的映射是否明显好或者明显冗余似乎也存在分歧。
- ...以及有关 Unix/Linux.SE 的一些未解答的问题。
(我不断偶然发现有关 Oracle/Solaris 的相当不错的文档idmapd
,但不幸的是,这似乎是一个非常不同的实现。)
我具体想做的是配置一些 CentOS 客户端,以便将 FreeBSD 服务器挂载到 NFSv4 上,其中至关重要的是,这些客户端位于几个不同的 DNS 域中,这(这花了我一些时间)长的因此,这意味着我必须以不同于默认方式配置客户端/服务器“NFS 域”(即使 NFS 域与 DNS 域相同)。此设置适用于与服务器位于同一 DNS 域中的客户端,因此剩下的问题就是这个 NFS 域问题。
显然的答案是设置Domain
,/etc/idmapd.conf
重新启动nfs-idmapd
服务,然后……不行,mount -tnfs server:/filesystem /mnt
可以工作,但ls /mnt
会产生 IO 错误。我在日志中看到(idmapd 详细程度已适当调高)
nfsidmap[5659]: nss_getpwnam: name 'root@<dnsdomain>' domain '<nfsdomain>': resulting localname '(null)'
这意味着……什么?我缺少上下文文档,无法弄清楚这里到底出了什么问题。我也找不到任何能提供有用线索的诊断工具——我没有足够的上下文来完全解释 的输出。即使我找到了设置nfsidmap -l
组合,并且它做了我想要的事情,我仍然会感到非常不舒服,因为这里的魔法比我理解的还要多。idmapd.conf
nfs4_disable_idmapping
答案1
nfs4 idmapd 有两个方面 - 一是使用凭证来识别请求者;二是显示文件的所有者和所有者组。
让我们看看你的ls /mnt
例子或更好的ls -l /mnt
,通常ls是ls -l。首先,客户端发送带有一些凭据的 RPC 请求。在您的例子中,由于没有特殊的挂载选项,我可以假设,身份验证系統被使用。因此,在网络上,客户端将发送数字当地的uid 和 gids。取决于服务器上的用户 ID,可以是同一个用户,也可以是另一个用户。
现在,服务器收到了请求,并以包含文件属性(包括所有者和组信息)的目录列表进行响应。根据服务器实现,服务器将返回数字字符串或主体,例如“500”或“user@domain”。如果出现以下情况,Linux 服务器将返回主体字符串:
- 客户端已使用 sys=krb5/krb5i/krb5p 安装
- nfs4idmapd 由 nfs4d_disable_idmapping=0 内核选项强制执行。
在收到服务器的回复后,客户端有两种可能性:如果提供了字符串主体,则调用 nfs4idmap,或者使用(实际上显示)提供的数字 id。
如果一切同步,那么你应该会看到一致的结果
$ id
uid=501(kofemann) gid=501(kofemann)
$ touch file
$ ls -l file
-rw-r--r-- 1 kofemann kofemann 0 Jun 13 22:03 file
$
另一方面,如果服务器返回错误的主体,那么您将得到意外的结果,例如
$ id
uid=501(kofemann) gid=501(kofemann)
$ touch file
$ ls -l file
-rw-r--r-- 1 nobody nobody 0 Jun 13 22:08 file
$
为了保持 ID 映射一致,客户端和服务器要么都应使用数字字符串,要么都配置为使用相同的 nfs 域。请注意,nfs 域只是我们用户群的一个逻辑命名空间。据我所知,没有服务器或客户端可以同时支持多个域,但这只是实现限制。
当你考虑到 Kerberos 时,整个 ID 映射的想法都是有意义的。假设你有一个客户端主机,它独立于你的用户群,例如一台笔记本电脑,以及一台服务器,它有本地用户群或连接到 LDAP。笔记本电脑上的 uid 可以是 501,服务器上的 uid 可以是 1234。唯一的共享身份是你的 Kerberos 主体用户@DOMAIN客户端会本地映射到501,服务器映射到1234。