Linux NFS 服务器实现的 setclientid 是如何工作的?

Linux NFS 服务器实现的 setclientid 是如何工作的?

是否有人足够了解 NFS 协议(版本 4)或其 Linux NFS 服务器实现,能够解释 setclientid 如何协商身份验证?

背景:

我有一台 CentOS 7 服务器,它运行带有 Kerberos 身份验证的 NFS4 服务器,Kerberos 集成由 PowerBroker Identity Services Open 提供。此服务器正在生产中,每天都在使用。我一直在尝试创建一个相同的服务器,但似乎做不到。大约六个月前,我在旧服务器上配置了所有内容,我认为我已经很好地记录了我所做的一切 - 但它似乎不再起作用了。除此之外,我还尝试尽可能简化设置,但它就是不起作用。在任何情况下,我都无法使用 Kerberos 挂载任何导出。我不确定这是为什么,但在花了很长时间进行故障排除后,我相信我已经确定了问题发生的位置。

观察到的 setclientid 行为:

下面是我尝试安装的测试系统上的 syslog 中的两个片段(名称和 IP 已替换),它运行 Ubuntu 16.04 桌面(ubuntu-1604x、192.168.1.30)。

两台服务器都运行 CentOS 7,并且看起来完全相同(我曾尝试在服务器 B 上使用不同版本的软件,但没有成功)

服务器A(192.168.1.125):

Nov  8 19:36:04 ubuntu-1604x kernel: [316817.783379] NFS call  setclientid auth=RPCSEC_GSS, 'Linux NFSv4.0 192.168.1.30/192.168.1.125 tcp'
Nov  8 19:36:04 ubuntu-1604x kernel: [316817.854777] NFS reply setclientid: 0
Nov  8 19:36:04 ubuntu-1604x kernel: [316817.854781] NFS call  setclientid_confirm auth=RPCSEC_GSS, (client ID 11cfcd5b138b872c)
Nov  8 19:36:04 ubuntu-1604x kernel: [316817.855413] NFS reply setclientid_confirm: 0

服务器B(192.168.1.250):

Nov  8 19:34:59 ubuntu-1604x kernel: [316752.414152] NFS call  setclientid auth=RPCSEC_GSS, 'Linux NFSv4.0 192.168.1.30/192.168.1.250 tcp'
Nov  8 19:34:59 ubuntu-1604x kernel: [316752.455212] NFS reply setclientid: -13
Nov  8 19:34:59 ubuntu-1604x kernel: [316752.455217] NFS call  setclientid auth=RPCSEC_GSS, 'Linux NFSv4.0 192.168.1.30/192.168.1.250 tcp'
Nov  8 19:34:59 ubuntu-1604x kernel: [316752.490325] NFS reply setclientid: -13
Nov  8 19:34:59 ubuntu-1604x kernel: [316752.490358] NFS call  setclientid auth=UNIX, 'Linux NFSv4.0 192.168.1.30/192.168.1.250 tcp
Nov  8 19:34:59 ubuntu-1604x kernel: [316752.490768] NFS reply setclientid: 0
Nov  8 19:34:59 ubuntu-1604x kernel: [316752.490772] NFS call  setclientid_confirm auth=UNIX, (client ID 1580e45bf5783af5)
Nov  8 19:34:59 ubuntu-1604x kernel: [316752.491354] NFS reply setclientid_confirm: 0

问题:

下面的那个导致“权限被拒绝”错误,这对我来说完全合理,因为导出仅允许 Kerberos 身份验证,但我无法理解 -13 回复和切换到不同的身份验证机制。有人能给我解释一下吗?

编辑:经过 7 次更新和看似已修复的错误后,问题仍然与上述相同。

我查过的资料来源:

除了我在互联网上找到的各种帖子之外,我还研究了 RFC 7530、7531 和 7931。我还没有详细阅读整个文档,但我仔细阅读了 RFC 7530 中有关“setclientid”和“setclientid_confirm”的部分多次,但我就是无法理解上述内容——我认为我的理解是有缺陷的。

更新

我认为 -13 是一个 RPC 错误。查看源代码nfs4proc我了解到输出中的 -13 来自 rpc_run_task。查看 rpc_run_task,我了解到它运行 rpc_execute - 我不知道具体执行了什么,但大概实现遵循 RFC 5531,它恰好有 14 种不同的身份验证错误,其中第 13 个是“用户没有凭据”,我在测试过程中多次看到 rpc.gssd 输出此错误。

更新 2

我从 rpc.gssd 看到的错误是:

ERROR: No credentials found for connection to server nfsserver.example.org

回想起来,我只在一台主机上测试时见过它,我从未确认过它是否可以连接到另一台服务器。我在任何地方都找不到它的记录,但我在其他地方看到很多对另一个 RPC 错误 13 的引用:RPC 错误 13(RPC 因超时而中止)鉴于我可以正常挂载另一台服务器,这可能是我遇到的错误吗?

更新 3

我在两台服务器上对 rpc.gssd 进程运行了 strace,并进行了另一次挂载尝试。服务器 A 没有输出任何内容,大概是因为我之前连接过。服务器 B 输出以下内容:

strace: Process 843 attached
epoll_wait(4, [{EPOLLIN, {u32=8, u64=8}}], 32, -1) = 1
read(8, "\r\0\0\0\0\2\0\0\0\0\0\0\20\0\0\0info\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 80
inotify_rm_watch(8, 13)                 = -1 EINVAL (Invalid argument)
inotify_add_watch(8, "nfsd4_cb/clnt3", IN_CREATE|IN_DELETE) = 14
openat(7, "nfsd4_cb/clnt3", O_RDONLY)   = 3
openat(3, "gssd", O_RDWR|O_NONBLOCK)    = -1 ENOENT (No such file or directory)
openat(3, "krb5", O_RDWR|O_NONBLOCK)    = -1 ENOENT (No such file or directory)
close(3)                                = 0
read(8, 0x7ffd2945e280, 4096)           = -1 EAGAIN (Resource temporarily unavailable)
epoll_wait(4,

我在 /var/lib/nfs/rpc_pipefs 中找到了提到的文件夹 (nfsd4_cb),两台服务器上的内容并不相同。工作服务器有一长串文件夹,它们似乎代表之前已连接/当前正在连接的客户端 - 可能是所有已分配的客户端 ID。也许这是一个未解决的问题。

我确实在 /var/lib/nfs/rpc_pipefs 中看到了 gssd 目录,因此“没有这样的文件或目录”消息令人困惑。编辑:我猜它可能在不同的文件夹中查找,我不知道 openat 的第一个参数是什么意思,而且它是不同的。有人明白这一点吗?

更新 4

我从测试中捕获了网络流量并检查了 setclientid 数据包。发送到服务器 A 的凭据如下:RPCSEC_GSS但发送到服务器 B 的凭证却是这样的 '身份验证'。在日志文件中,似乎进行了 3 次 setclientid 调用,并且服务器做出了回复,但只发送了一个 - 因此“拒绝”一定发生在客户端本地。

我使用完全相同的 mount 命令,但主机名已被替换。

更新 5

在启用所有 RPC 调试输出的情况下,我查看了日志文件,并找到了我认为是 SETCLIENTID 启动的 RPC 任务的输出(如果我的理解正确的话,那就是。请参阅'更新')。

因此,通过比较正常挂载和失败挂载的输出,我相信我已经找到了这个 RPC 出错的地方,但是我不明白到底发生了什么。

工作支架的片段:

Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150180] NFS call  setclientid auth=RPCSEC_GSS, 'Linux NFSv4.0 192.168.1.30/192.168.1.125 tcp'
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150181] RPC:       new task initialized, procpid 12556
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150182] RPC:       allocated task ffff880034f92500
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150183] RPC:  2251 __rpc_execute flags=0x5280
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150184] RPC:  2251 call_start nfs4 proc SETCLIENTID (sync)
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150185] RPC:  2251 call_reserve (status 0)
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150186] RPC:  2251 reserved req ffff880211697600 xid 29a970ab
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150187] RPC:       wake_up_first(ffff880130755190 "xprt_sending")
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150187] RPC:  2251 call_reserveresult (status 0)
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150188] RPC:  2251 call_refresh (status 0)
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150190] RPC:       gss_create_cred for uid 0, flavor 390004
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150191] RPC:       gss_create_upcall for uid 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150196] RPC:       __gss_find_upcall found nothing
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171925] RPC:       __gss_find_upcall found msg ffff8800db521000
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171938] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171939] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171944] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171944] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171950] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171951] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171954] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171954] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171957] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171958] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171961] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171962] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171964] RPC:       gss_import_sec_context_kerberos: returning 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171965] RPC:       gss_fill_context Success. gc_expiry 4438759401 now 4431124651 timeout 30539 acceptor
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171968] RPC:       gss_pipe_downcall returning 80
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171985] RPC:       gss_create_upcall for uid 0 result 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171987] RPC:  2251 refreshing RPCSEC_GSS cred ffff8802121513c0

来自非工作安装的片段:

Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738317] NFS call  setclientid auth=RPCSEC_GSS, 'Linux NFSv4.0 192.168.1.30/192.168.1.250 tcp'
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738318] RPC:       new task initialized, procpid 12672
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738319] RPC:       allocated task ffff880158862200
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738320] RPC:  2280 __rpc_execute flags=0x5280
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738322] RPC:  2280 call_start nfs4 proc SETCLIENTID (sync)
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738323] RPC:  2280 call_reserve (status 0)
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738324] RPC:  2280 reserved req ffff8801b5ef2800 xid ab6b57ae
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738325] RPC:       wake_up_first(ffff880130751990 "xprt_sending")
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738326] RPC:  2280 call_reserveresult (status 0)
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738327] RPC:  2280 call_refresh (status 0)
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738328] RPC:       gss_create_cred for uid 0, flavor 390004
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738330] RPC:       gss_create_upcall for uid 0
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738332] RPC:       __gss_find_upcall found nothing
Nov 11 10:59:42 ubuntu-1604x kernel: [545029.835573] RPC:       __gss_find_upcall found msg ffff8801b5ef3400
Nov 11 10:59:42 ubuntu-1604x kernel: [545029.835576] RPC:       gss_fill_context returns error 13
Nov 11 10:59:42 ubuntu-1604x kernel: [545029.835580] RPC:       gss_pipe_downcall returning 16
Nov 11 10:59:42 ubuntu-1604x kernel: [545029.835593] RPC:       gss_create_upcall for uid 0 result -13
Nov 11 10:59:42 ubuntu-1604x kernel: [545029.835597] RPC:  2280 call_refreshresult (status -13)
Nov 11 10:59:42 ubuntu-1604x kernel: [545029.835598] RPC:  2280 call_refreshresult: refresh creds failed with error -13

-13 错误肯定是这个,而且很可能是RPCSEC_GSS_CREDPROBLEM = 13, /* 没有用户凭证 */在 RFC 5531 中引用。__gss_find_upcall 找到消息与正常工作的有所不同,但我不确定这意味着什么。使用正常工作的挂载,会明确记录凭据稍后会进行验证,因此不可能是凭据未通过验证,而一定是凭据未找到。

Nov 11 10:57:48 ubuntu-1604x kernel: [544916.172735] RPC:  2251 validating RPCSEC_GSS cred ffff8802121513c0

使用的 mount 命令完全相同,除了主机名之外。主机名如何影响“凭据”的搜索?它在哪里查找?有人知道发生了什么吗?

更新 6

在 setclientid NFS 调用之前,有一些流量到 KDC 服务器。'请求TGS' 请求已发送,服务器回复 'KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN'。我对此不太了解,无法弄清楚到底向 KDC 发送了什么,并且流量是加密的。两个服务器都有相同的 SPN(其中包含自己的主机名)。有没有人对此了解得足够多,可以帮助确定我的 mount 命令的主机名如何影响请求TGS发送了什么?我没有权限访问 KDC,因此无法在那里排除故障。

更新 7

上述错误是由错误的反向 DNS 记录引起的。修复该问题后,KDC 现在会在收到请求TGS。但观察到的行为是相同的,挂载失败,日志中的 NFS setclientid 输出完全相同,RPC 输出看起来相同。收到的票证似乎有问题 - 有人知道如何调试吗?

更新 8

这张票似乎是正确的。我使用 Wireshark 捕获流量,并再次将正常工作的流量与不正常工作的流量进行比较。我注意到,在 setclientid 调用之前,正在进行“NULL”调用。

第一个服务器没有凭据,第二个服务器似乎有正确的凭据。两个服务器都收到了对第一个没有凭据的 NULL 调用的回复,但只有工作服务器收到了对第二个服务器的回复,另一个服务器尝试了 4 次,都没有回复。

我看到的这些 NULL 调用是什么?我该如何调试没有回复的情况?目标端口是端口 2049,其他到 2049 的流量确实会得到回复。

服务器上 rpc.gssd 的 Strace 仍然给出与 Update 3 中相同的结果。

此外,我使用 lsof 来确认 rpc.gssd 的工作目录:

rpc.gssd    892                 root  cwd       DIR               0,39         0      12726 /var/lib/nfs/rpc_pipefs

以下是对该文件夹执行 ls -la 的结果:

total 0
dr-xr-xr-x. 11 root root   0 Nov 14 14:33 .
drwxr-xr-x.  6 root root 179 Nov 14 15:17 ..
dr-xr-xr-x.  2 root root   0 Nov 14 14:33 cache
dr-xr-xr-x.  3 root root   0 Nov 14 14:33 gssd
dr-xr-xr-x.  2 root root   0 Nov 14 14:33 lockd
dr-xr-xr-x.  2 root root   0 Nov 14 14:33 mount
dr-xr-xr-x.  2 root root   0 Nov 14 14:33 nfs
dr-xr-xr-x.  2 root root   0 Nov 14 14:33 nfsd
dr-xr-xr-x.  2 root root   0 Nov 14 22:31 nfsd4_cb
dr-xr-xr-x.  2 root root   0 Nov 14 14:33 portmap
dr-xr-xr-x.  2 root root   0 Nov 14 14:33 statd

有gssd文件夹,为什么会出现ENOENT错误?

openat(3, "gssd", O_RDWR|O_NONBLOCK)    = -1 ENOENT (No such file or directory)
openat(3, "krb5", O_RDWR|O_NONBLOCK)    = -1 ENOENT (No such file or directory)

编辑:首次安装时,上述情况也会发生在工作服务器上。

相关内容