0

I have a small network that includes a NAS. on which I provisioned, with some effort, a Kerberos server. The Kerberos server allows Linux hosts on the network to create secure NFS mounts. Service keys created on the KDC are distributed to appropriate hosts, and mounts are configured with Kerberos security. Insecure mounts are blocked by the policy configured on the NAS.

Inconveniently, users may access files on the mounts only if they have active tickets on the host from the KDC. This requirement is restrictive, due to inconvenience, and even more so by limiting access to the mounts by automated tasks running with regular user permissions.

In the early days of NFS, files on a remote volume would appear as local, beginning at boot, and continuously for the entire system session. Security and identity management are important benefits of Kerberos in NFS, but requiring users to be granted tickets is often unnecessary. Since the key distribution and the controlled access to the hosts prevents unwanted access to the NFS mounts, I have no need of user tickets.

Ideally, I would like users to access mounts that have Kerberos security without requesting a ticket from the KDC, or even needing a principal registered on it. Any user would have access at all times to any file, provided access would not be restricted by per-file permissions.

How close to this target scenario is possible through existing tools?

9
  • In that case, do you actually gain any benefits by using Kerberos instead of, say, IPsec? (You do lose performance compared to IPsec.) Are you using Kerberos authentication for any other services or is it literally just NFS? Commented Dec 9, 2021 at 13:33
  • 1
    @user1686: IPsec knows nothing about the file permissions on the volume. It would be no help to my scenario.
    – brainchild
    Commented Dec 9, 2021 at 13:35
  • But NFS still does – by including the user's UID in every RPC request. That's literally how things worked "in the early days of NFS" before Kerberos: the client said "user 1003 is performing this operation", the server trusted that claim and applied permission checks accordingly. Commented Dec 9, 2021 at 13:36
  • The objective is to check permissions against the active user on the host with the mount. A ticket from the KDC is not necessary. The symbolic identifier of the user is sufficient.
    – brainchild
    Commented Dec 9, 2021 at 13:46
  • Exactly, and that's what you get with the UID-based sec=sys, without needing Kerberos in any way. Commented Dec 9, 2021 at 13:47

1 Answer 1

1

The short answer is that the current NFS Kerberos authentication mechanism (RPCSEC_GSS) does not support this. The principal that's making the call is the one who gets access. So if you don't want users to manually get tickets, then you'll need to have the host automatically get tickets for them.

In the future, the newer RPCSEC_GSSv3 protocol might have options for allowing hosts to impersonate arbitrary users, but it hasn't yet been finished nor implemented.


If you want to allow hosts to impersonate any UID, then you don't need Kerberos at all – switch back to the sec=sys security mode that was used "in the old days". In this mode, the host literally gets to specify a symbolic identifier of the user. (Permission checks still happen, of course.)

In the end, there is no functional difference between allowing a host to impersonate any user via Kerberos (authenticated using the host's /etc/krb5.keytab), versus allowing a host to impersonate any user via basic UID claim (authenticated using the host's IPsec or WireGuard private key or) – and the latter will give you much higher performance than GSSAPI can achieve.


Within Kerberos, when using existing tools only (without outright implementing some kind of host-level authentication for RPC), the closest thing you have is constrained delegation with protocol transition (S4U2Self + S4U2Proxy), where a service is allowed to get tickets to specific other services in the name of a user. It is commonly used in Active Directory environments but is also supported by MIT Kerberos KDCs (and probably Heimdal KDCs – the code is there, thanks to Samba, but I do not know how to enable it on Heimdal).

To enable this in a MIT Kerberos KDC you will need to use the LDAP backend; the file-based HDB backend doesn't support storing the additional fields.

  1. Set the ok_to_auth_as_delegate principal flag on the client's host principal (can be done through kadmin, or by ORing 0x200000 into the krbTicketFlags LDAP attribute).

    kadmin.local modprinc +ok_to_auth_as_delegate host/foo.example.com
    
  2. Set the client principal's krbAllowedToDelegateTo LDAP attribute to a list of NFS service principals that it may create the fake tickets for. (One service per value.)

    ldapmodify <<EOF
    dn: krbPrincipalName=host/[email protected],cn=EXAMPLE.COM,ou=Kerberos,o=Example
    add: krbAllowedToDelegateTo
    krbAllowedToDelegateTo: nfs/fs1.example.com
    -
    EOF
    
  3. Test whether S4U features work, as root:

    # 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. Install gss-proxy on the client, and edit its included nfs-client.conf to use S4U2Proxy instead of individual client keytabs:

    [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
    

    This example is based on https://github.com/gssapi/gssproxy/blob/main/docs/NFS.md#user-impersonation-via-constrained-delegation.

  5. Configure the client's rpc.gssd daemon to use gss-proxy by adding GSS_USE_PROXY=1 to the environment:

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

If Kerberos is used exclusively for NFS, and if each host only needs a limited set of users, then the host can store client keytabs (which hold the password-derived keys) for those users. This is roughly equivalent to storing the users' passwords, as the keytab allows

13
  • So the KDC will issue tickets even without user credentials, but requesting tickets (through kinit) is still necessary?
    – brainchild
    Commented Dec 9, 2021 at 14:22
  • Yes, S4U2Proxy allows the host (or some other service) to get user tickets without any user credentials – for an approved set of destination services. It is pretty much meant for this situation. But in the end NFS's RPCSEC_GSS needs a user ticket, therefore something has to get a user ticket for the client's rpc.gssd (it doesn't know how to do S4U2Proxy on its own), although it might not necessarily be kinit – it seems the gss-proxy daemon has support for this as well. Commented Dec 9, 2021 at 14:33
  • (This does have the advantage that it generalizes to SMB/CIFS or any other protocols you might want to provide, instead of being an inherently NFS-specific trick.) Commented Dec 9, 2021 at 14:35
  • It would be great if the ticket request could be triggered simply by the user accessing the files, as detected by gssd.
    – brainchild
    Commented Dec 9, 2021 at 14:37
  • The PAM script has the problem of depending on manual login. Automation is not possible in the general case.
    – brainchild
    Commented Dec 9, 2021 at 14:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .