通过 Kerberos 实现完全无密码的 nfs

通过 Kerberos 实现完全无密码的 nfs

我有一个小网络,其中包括一个 NAS。我花了一些功夫在该 NAS 上配置了一个 Kerberos 服务器。Kerberos 服务器允许网络上的 Linux 主机创建安全的 NFS 挂载。在 KDC 上创建的服务密钥会分发给相应的主机,并且挂载会配置 Kerberos 安全性。NAS 上配置的策略会阻止不安全的挂载。

不方便的是,用户只有在主机上拥有来自 KDC 的有效票证时才可以访问挂载点上的文件。由于不方便,此要求具有限制性,尤其是通过限制以常规用户权限运行的自动任务对挂载点的访问。

在 NFS 的早期,远程卷上的文件会显示为本地文件,从启动开始,并在整个系统会话期间持续显示。安全和身份管理是 Kerberos 在 NFS 中的重要优势,但要求用户获得票证通常是不必要的。由于密钥分发和对主机的受控访问可防止对 NFS 挂载的不必要访问,因此我不需要用户票证。

理想情况下,我希望用户能够访问具有 Kerberos 安全性的挂载,而无需从 KDC 请求票证,甚至不需要在其上注册主体。任何用户都可以随时访问任何文件,前提是访问权限不受每个文件权限的限制。

通过现有工具,多大程度上可以接近这一目标场景?

答案1

简短的回答是,当前的 NFS Kerberos 身份验证机制 (RPCSEC_GSS) 不支持此功能。发出调用的主体是获得访问权限的人。因此,如果您不希望用户手动获取门票,那么你需要让主持人自动获取门票为了他们。

将来,较新的 RPCSEC_GSSv3 协议可能会有允许主机模仿任意用户的选项,但尚未完成或实施。


如果您想允许主机模拟任何 UID,那么您根本不需要 Kerberos - 切换回sec=sys“过去”使用的安全模式。在此模式下,主机实际上可以指定用户的符号标识符。(当然,权限检查仍然会发生。)

最后,允许主机通过 Kerberos 模拟任何用户(使用主机的 /etc/krb5.keytab 进行身份验证)与允许主机通过基本 UID 声明模拟任何用户(使用主机的 IPsec 或 WireGuard 私钥进行身份验证)之间没有功能区别——后者将为您提供比 GSSAPI 更高的性能。


在 Kerberos 中,当仅使用现有工具时(没有直接为 RPC 实现某种主机级身份验证),最接近的是带协议转换的约束委派(S4U2Self + S4U2Proxy),允许服务以用户的名义获取特定其他服务的票证。它通常用于 Active Directory 环境中,但也受到 MIT Kerberos KDC(和大概Heimdal KDCs – 感谢 Samba,代码就在那里,但我不知道如何在 Heimdal 上启用它)。

要在 MIT Kerberos KDC 中启用此功能,您需要使用 LDAP 后端;基于文件的 HDB 后端不支持存储附加字段。

  1. ok_to_auth_as_delegate在客户端的主机主体上设置主体标志(可以通过 kadmin 完成,也可以通过 ORing0x200000进入krbTicketFlagsLDAP 属性来完成)。

    kadmin.local modprinc +ok_to_auth_as_delegate host/foo.example.com
    
  2. 将客户端主体的krbAllowedToDelegateToLDAP 属性设置为可能为其创建虚假票证的 NFS 服务主体列表。(每个值一个服务。)

    ldapmodify <<EOF
    dn: krbPrincipalName=host/[email protected],cn=EXAMPLE.COM,ou=Kerberos,o=Example
    add: krbAllowedToDelegateTo
    krbAllowedToDelegateTo: nfs/fs1.example.com
    -
    EOF
    
  3. 以 root 身份测试 S4U 功能是否有效:

    # Acquire host credentials using system keytab
    host_cc=FILE:/tmp/krb5cc_host
    kinit -c $host_cc -k
    klist -c $host_cc
    
    # Acquire NFS tickets on behalf of the user using S4U2Proxy
    kvno -c $host_cc -I $user_name -P nfs/fs1.example.com
    klist -c $host_cc
    
    # Do the same, but put the tickets in that user's cache
    # so that rpc.gssd would be able to find them
    user_cc=FILE:/tmp/krb5cc_$(id -u $user)
    kvno -c $host_cc -I $user -P nfs/fs1.example.com --out-cache $user_cc
    chown $user: $user_cc
    
  4. 安装gss-代理在客户端上,并编辑其包含的内容nfs-client.conf以使用 S4U2Proxy 而不是单独的客户端密钥表:

    [service/nfs-client]
      mechs = krb5
      cred_store = keytab:/etc/krb5.keytab
      cred_store = ccache:FILE:/var/lib/gssproxy/clients/krb5cc_%U
      impersonate = yes
      allow_any_uid = yes
      trusted = yes
      euid = 0
    

    本示例基于https://github.com/gssapi/gssproxy/blob/main/docs/NFS.md#user-impersonation-via-constrained-delegation

  5. 配置客户端的rpc.gssdGSS_USE_PROXY=1守护进程通过向环境添加以下内容来使用 gss-proxy :

    # systemctl edit rpc-gssd
    
    [Service]
    Environment=GSS_USE_PROXY=1
    
    # systemctl restart rpc-gssd
    

如果 Kerberos 专门用于 NFS,并且每台主机只需要一组有限的用户,那么主机可以存储客户端密钥表(保存密码派生密钥)用于这些用户。这大致相当于存储用户的密码,因为密钥表允许

相关内容