Kerberos authentication for NFS¶
NFS defaults to AUTH_SYS, where the client declares its own UID/GID and the server trusts it unconditionally (F-1.1). RPCSEC_GSS with Kerberos replaces this self-asserted identity with cryptographically verified tickets issued by a trusted third party. It is the only authentication mechanism in the NFS ecosystem that actually authenticates users.
This page covers the three Kerberos service levels, how to deploy them on both server and client, and what Kerberos does and does not protect.
Why Kerberos matters¶
AUTH_SYS fails three fundamental requirements for NFS security:
| Requirement | AUTH_SYS | Kerberos (RPCSEC_GSS) |
|---|---|---|
| User identity verification | Client-asserted, no proof | KDC-issued ticket, cryptographically verified |
| Mutual authentication | None -- client trusts the IP | Server proves its identity via service principal |
| Per-RPC integrity | None -- any intermediary can modify calls | HMAC on every RPC message (krb5i, krb5p) |
| Wire encryption | None -- credentials, handles, file data in cleartext | Full payload encryption (krb5p) |
| UID spoofing resistance | Zero -- attacker claims any UID | Server maps Kerberos principal to local UID via idmapd |
AUTH_SYS cannot be fixed
No amount of firewall rules, export options, or network segmentation eliminates AUTH_SYS spoofing. Any machine that can reach the NFS port can claim any identity. The only real fix is replacing AUTH_SYS with Kerberos. See Why NFS Is Insecure for the full structural analysis.
The three service levels¶
RPCSEC_GSS with Kerberos offers three protection levels, configured per-export via the sec= option in /etc/exports. Each level builds on the previous one.
graph LR
A["krb5<br>Authentication only"] --> B["krb5i<br>+ Integrity"]
B --> C["krb5p<br>+ Privacy"]
style A fill:#1a1a2e,stroke:#0d6efd,color:#fff
style B fill:#1a1a2e,stroke:#ffc107,color:#fff
style C fill:#1a1a2e,stroke:#198754,color:#fff
| Level | Authentication | Integrity | Encryption | Performance | When to use |
|---|---|---|---|---|---|
krb5 |
Kerberos ticket verifies user identity | None -- RPC payloads can be modified in transit | None -- file data, handles, metadata in cleartext | Lowest overhead | Trusted network, identity spoofing is the only concern |
krb5i |
Kerberos ticket | HMAC on every RPC message detects tampering | None -- data readable by passive observer | Moderate overhead | Untrusted network segment, but data confidentiality not required |
krb5p |
Kerberos ticket | HMAC integrity | Full encryption of RPC payloads (AES) | Highest overhead (10-30% throughput reduction) | Any network where file contents are sensitive |
krb5 alone does not protect the wire
With sec=krb5 (authentication only), an attacker who can sniff the network still sees file data, directory listings, and file handles in plaintext. The handle is a bearer token (F-2.1). Capturing one from the wire gives the attacker direct access. Use krb5p unless you have a strong reason not to.
Recommendation
Use sec=krb5p everywhere. The performance overhead is measurable but acceptable for most workloads. If throughput is critical (large sequential I/O on a trusted network), krb5i is a reasonable compromise. Never deploy krb5 alone on an untrusted network.
Prerequisites¶
Before configuring NFS Kerberos, you need:
- A working Kerberos realm -- either MIT Kerberos or Heimdal KDC, with DNS forward and reverse records for all NFS servers and clients
- Time synchronization -- Kerberos tickets have a 5-minute clock skew tolerance by default; all machines must run NTP/chrony
- DNS -- Kerberos relies on DNS for principal name canonicalization; PTR records must resolve correctly for server hostnames
- Keytab on the NFS server -- the
nfs/service principal's key, exported from the KDC - krb5.conf on all machines -- realm configuration, KDC addresses, domain-to-realm mapping
Server setup¶
1. Create the NFS service principal¶
The NFS server needs a service principal in the form nfs/server.example.com@REALM. The hostname must match the server's fully-qualified DNS name exactly, including what reverse DNS returns.
2. Install the keytab on the NFS server¶
Transfer the keytab securely (scp, not NFS) and merge it into the system keytab:
# On the NFS server
scp kdc:/tmp/nfs-server.keytab /tmp/nfs-server.keytab
ktutil
# ktutil: read_kt /etc/krb5.keytab
# ktutil: read_kt /tmp/nfs-server.keytab
# ktutil: write_kt /etc/krb5.keytab
# ktutil: quit
rm /tmp/nfs-server.keytab
chmod 600 /etc/krb5.keytab
Verify the keytab contains the NFS principal:
klist -ke /etc/krb5.keytab | grep nfs/
# Should show: nfs/nfs-server.example.com@EXAMPLE.COM (aes256-cts-hmac-sha1-96)
3. Configure /etc/exports¶
Replace sec=sys with sec=krb5p on every export. Do not include AUTH_SYS as a fallback; mixed flavors enable downgrade attacks (F-1.7).
# /etc/exports
/srv/nfs/data 10.0.0.0/24(rw,sync,sec=krb5p,root_squash,no_subtree_check)
/srv/nfs/home 10.0.0.0/24(rw,sync,sec=krb5p,root_squash,no_subtree_check)
Never mix sec=sys and sec=krb5
An export configured as sec=krb5p:sys accepts AUTH_SYS connections. An attacker simply selects AUTH_SYS and bypasses Kerberos entirely. There is no negotiation that forces the stronger mechanism. See F-1.7.
Apply the changes:
4. Enable and start the GSS daemon¶
The NFS server needs a GSS-API helper daemon to handle Kerberos ticket validation. Modern Linux distributions use gssproxy; older systems use rpc.gssd on the server side via rpc.svcgssd.
# gssproxy is typically configured automatically when nfs-utils is installed
# Verify the NFS server section exists:
cat /etc/gssproxy/24-nfs-server.conf
# Should contain:
# [service/nfs-server]
# mechs = krb5
# cred_store = keytab:/etc/krb5.keytab
# trusted = yes
# kernel_nfsd = yes
# euid = 0
systemctl enable --now gssproxy
systemctl restart nfs-server
Verify the server is advertising Kerberos:
rpcinfo -p localhost | grep nfs
# Should show program 100003 on expected ports
# From a client, check MOUNT reports krb5 flavors:
showmount -e nfs-server.example.com
5. Configure idmapd¶
NFSv4 with Kerberos uses rpc.idmapd to map between Kerberos principals and local UIDs. Without it, files owned by Kerberos-authenticated users show up as nobody:nogroup.
# /etc/idmapd.conf
[General]
Verbosity = 0
Domain = example.com
[Mapping]
Nobody-User = nobody
Nobody-Group = nogroup
[Translation]
Method = nsswitch
The Domain must match on all clients and the server. Restart idmapd after changes:
Client setup¶
1. Install Kerberos client packages¶
2. Configure krb5.conf¶
# /etc/krb5.conf
[libdefaults]
default_realm = EXAMPLE.COM
dns_lookup_realm = false
dns_lookup_kdc = true
forwardable = true
rdns = true
[realms]
EXAMPLE.COM = {
kdc = kdc.example.com
admin_server = kdc.example.com
}
[domain_realm]
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COM
rdns = true
Kerberos canonicalizes the NFS server hostname via reverse DNS. If rdns = false or PTR records are wrong, the client requests a ticket for the wrong principal and authentication fails with Server not found in Kerberos database. This is the single most common Kerberos NFS failure.
3. Obtain a ticket¶
For interactive users, kinit obtains a ticket-granting ticket (TGT) from the KDC:
For unattended mounts (servers, CI), use a host keytab:
# Create a host principal on the KDC and export a keytab to the client
# Then configure gssproxy or rpc.gssd to use it
kinit -k -t /etc/krb5.keytab host/client.example.com@EXAMPLE.COM
4. Enable rpc.gssd on the client¶
The client needs rpc.gssd (or gssproxy) to present Kerberos tickets to the NFS server:
5. Mount with Kerberos¶
Or in /etc/fstab:
Verify the mount is using Kerberos:
What Kerberos protects¶
Kerberos (especially krb5p) eliminates the most common NFS attack vectors:
| Attack | Without Kerberos | With krb5p |
|---|---|---|
| F-1.1: UID/GID spoofing | Any client claims any UID | Server verifies Kerberos principal, ignores AUTH_SYS fields |
| F-1.2: root_squash bypass | Claim UID=1 instead of UID=0 | Principal-to-UID mapping is server-controlled |
| F-1.3: Auxiliary group injection | Client injects arbitrary GIDs | Server resolves groups from principal via nsswitch |
| F-1.5: Credential replay | Sniffed AUTH_SYS replayable forever | Kerberos tickets have timestamps and sequence numbers |
| F-3.1: Plaintext wire protocol | File data readable on wire | krb5p encrypts entire RPC payload |
| F-1.7: Flavor downgrade | N/A | Prevented only if AUTH_SYS is removed from sec= |
What Kerberos does NOT protect¶
Kerberos is not a complete NFS security solution
Kerberos solves authentication and wire protection. It does not solve the structural protocol flaws that exist independently of how the user is authenticated.
| Attack | Status with Kerberos | Why |
|---|---|---|
| F-2.1: Export escape | Still possible | File handles are bearer tokens. A Kerberos-authenticated user who obtains an escape handle can use it. The server validates the handle against the filesystem, not against what the user was supposed to access. |
| F-2.2: Handle guessing | Still possible | Handle validation checks inode existence, not who constructed the handle. Kerberos does not add handle signing. |
| F-2.12: LOOKUPP cross-export | Still possible | NFSv4 LOOKUPP traversal is an authorized operation -- Kerberos authenticates the user but does not restrict directory traversal. |
| F-4.1: no_root_squash | Depends on mapping | If the Kerberos principal maps to local UID 0, the user gets root. root_squash still matters. |
| F-5.1: Export enumeration | Still possible | MOUNT EXPORT is a separate protocol with no Kerberos enforcement. |
| F-1.8: AUTH_TOOWEAK oracle | Inherent | The AUTH_TOOWEAK error confirms the export exists and requires Kerberos -- an information leak by design. |
MOUNT protocol and the Kerberos gap
The MOUNT protocol (RFC 1813 Appendix I) does not participate in RPCSEC_GSS negotiation. Per RFC 2623 S2.3.2, MOUNT MNT succeeds with AUTH_SYS even on sec=krb5 exports, leaking the root file handle. This is by design -- the handle is needed to bootstrap the NFS session. Use NFSv4 (which has no MOUNT protocol) to close this gap. See F-1.8 for the full analysis.
Limitations and operational considerations¶
Performance overhead¶
krb5p encrypts and integrity-checks every RPC message. Expect 10-30% throughput reduction on large sequential I/O compared to AUTH_SYS. The overhead comes from AES encryption of the RPC payload, not from ticket validation (which is cached). Random I/O workloads see less impact because the per-operation latency is dominated by disk, not crypto.
KDC availability¶
The KDC is a single point of failure. If the KDC is unreachable, no new Kerberos tickets can be issued. Existing mounts continue to work until their tickets expire (typically 10 hours). Mitigations:
- Deploy at least two KDC replicas with DNS SRV records
- Use
forwardable = truein krb5.conf for ticket renewal without KDC contact - Configure
krenework5startfor long-running processes
Keytab management¶
Keytabs contain long-term keys and must be protected like passwords. If a keytab is compromised, the attacker can impersonate the NFS server until the principal's key is changed. Rotate keytab keys periodically and restrict file permissions to root:root 0600.
NFSv2 and Kerberos¶
NFSv2 does not support RPCSEC_GSS at the protocol level. Linux knfsd enforces sec=krb5 on v2 operations at the server side (rejecting AUTH_SYS calls), but the MOUNT v1 protocol leaks the handle without Kerberos authentication. See F-1.6. Disable NFSv2 entirely when deploying Kerberos.
NFSv4 delegations¶
NFSv4.0 delegation metadata (OPEN/CLOSE state, lock state, callback notifications) uses the same RPCSEC_GSS protection level as the export. With krb5p, delegation traffic is encrypted. However, the CB_COMPOUND callback channel from server to client may use a different security flavor depending on the implementation. Verify with packet captures if delegation security is critical.
Troubleshooting¶
Common errors and fixes¶
| Error | Cause | Fix |
|---|---|---|
Server not found in Kerberos database |
Hostname mismatch between DNS PTR and service principal | Verify host -t PTR <server-ip> matches the principal name exactly |
Clock skew too great |
Time difference > 5 minutes between client, server, and KDC | Sync all machines with NTP; check with date on each |
mount.nfs: access denied by server |
Missing or expired ticket, or sec=sys in export |
Run klist to check ticket validity; verify export uses sec=krb5p |
GSS-API error: No credentials were supplied |
rpc.gssd not running on client | systemctl start rpc-gssd or systemctl start gssproxy |
Key version number for principal not found |
Keytab has old key version after password change | Re-export keytab from KDC with kadmin ktadd |
mount.nfs: Operation not permitted |
Client not using privileged port with sec=sys fallback | Ensure mount uses -o sec=krb5p, not falling back to AUTH_SYS |
Diagnostic commands¶
# Check ticket status
klist -e
# Verify keytab contents
klist -ke /etc/krb5.keytab
# Test ticket acquisition for the NFS service
kvno nfs/nfs-server.example.com@EXAMPLE.COM
# Enable RPC debug logging (kernel)
rpcdebug -m rpc -s auth
rpcdebug -m nfsd -s proc
# Check gssproxy status
systemctl status gssproxy
journalctl -u gssproxy -n 50
# Verify NFS server is advertising Kerberos flavors
# (use nfswolf to probe)
nfswolf scan nfs-server.example.com
Verifying with nfswolf¶
nfswolf detects Kerberos configuration (and misconfiguration) automatically:
# Scan reports auth flavors per export
nfswolf scan nfs-server.example.com
# Look for: auth_flavors: [krb5p] -- means Kerberos-only (good)
# Look for: auth_flavors: [sys, krb5p] -- means mixed flavors (F-1.7, bad)
# Analyze flags mixed-flavor exports as F-1.7
nfswolf analyze nfs-server.example.com
# F-1.7 fires if AUTH_SYS coexists with any krb5 variant
# AUTH_TOOWEAK oracle confirms Kerberos enforcement
# F-1.8 fires when AUTH_SYS operations are rejected with AUTH_TOOWEAK
Related pages¶
- Why NFS is insecure -- the structural flaws Kerberos addresses
- NFS over TLS -- transport encryption (complements Kerberos, does not replace it)
- F-1.7: Flavor downgrade -- why mixed
sec=sys:krb5is dangerous - F-1.8: AUTH_TOOWEAK oracle -- information leak from Kerberos enforcement
- Export options reference --
sec=option syntax and behavior - Hardening checklist -- Kerberos in context of the full hardening path