NFS v4 ????????? Kerberos ?????????????????????
NFS v4 (Network File System version 4) ???????????? protocol ?????????????????? share files ???????????? network ????????????????????????????????? v3 ??????????????????????????? ?????????????????? stateful operations, compound procedures (????????????????????? operations ?????? 1 request), mandatory locking, ACLs ?????????????????????????????????????????? built-in security ???????????? RPCSEC_GSS ??????????????????????????? Kerberos authentication
Kerberos ???????????? authentication protocol ?????????????????? tickets ????????? passwords ??????????????????????????? KDC (Key Distribution Center) ?????????????????????????????? Authentication Server (AS) ????????? TGT (Ticket Granting Ticket) ????????? Ticket Granting Server (TGS) ????????? service tickets ??????????????????????????????????????? services ???????????????
NFS v4 + Kerberos ?????? 3 security levels krb5 authentication only ????????????????????????????????????????????? data ????????? encrypt, krb5i integrity checking ?????????????????????????????? data ?????????????????? tamper, krb5p privacy/encryption ???????????? authenticate ????????? encrypt data ??????????????????????????????????????? ??????????????? SSL/TLS certificates ?????????????????? encrypt management traffic ??????????????????????????????????????????????????????????????????
????????????????????? Kerberos KDC ????????? NFS Server
Setup Kerberos KDC ?????????????????? NFS authentication
# === Kerberos KDC Installation ===
# Environment:
# KDC Server: kdc.example.com (192.168.1.10)
# NFS Server: nfs.example.com (192.168.1.20)
# NFS Client: client.example.com (192.168.1.30)
# Realm: EXAMPLE.COM
# 1. Install KDC on kdc.example.com
dnf install -y krb5-server krb5-libs krb5-workstation
# 2. Configure /etc/krb5.conf (all machines)
cat > /etc/krb5.conf << 'EOF'
[libdefaults]
default_realm = EXAMPLE.COM
dns_lookup_realm = false
dns_lookup_kdc = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
default_ccache_name = KEYRING:persistent:%{uid}
[realms]
EXAMPLE.COM = {
kdc = kdc.example.com
admin_server = kdc.example.com
default_domain = example.com
}
[domain_realm]
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COM
EOF
# 3. Configure KDC
cat > /var/kerberos/krb5kdc/kdc.conf << 'EOF'
[kdcdefaults]
kdc_ports = 88
kdc_tcp_ports = 88
[realms]
EXAMPLE.COM = {
acl_file = /var/kerberos/krb5kdc/kadm5.acl
dict_file = /usr/share/dict/words
admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
supported_enctypes = aes256-cts:normal aes128-cts:normal
max_life = 24h
max_renewable_life = 7d
}
EOF
# 4. Create Kerberos Database
kdb5_util create -s -r EXAMPLE.COM
# Enter master password
# 5. Create Admin Principal
kadmin.local -q "addprinc admin/admin@EXAMPLE.COM"
# 6. Set ACL
echo "*/admin@EXAMPLE.COM *" > /var/kerberos/krb5kdc/kadm5.acl
# 7. Start Services
systemctl enable --now krb5kdc kadmin
# 8. Create NFS Service Principals
kadmin.local << 'KADMIN'
addprinc -randkey nfs/nfs.example.com@EXAMPLE.COM
addprinc -randkey nfs/client.example.com@EXAMPLE.COM
addprinc -randkey host/nfs.example.com@EXAMPLE.COM
addprinc -randkey host/client.example.com@EXAMPLE.COM
KADMIN
# 9. Export Keytabs
kadmin.local -q "ktadd -k /tmp/nfs-server.keytab nfs/nfs.example.com host/nfs.example.com"
kadmin.local -q "ktadd -k /tmp/nfs-client.keytab nfs/client.example.com host/client.example.com"
# Copy keytabs to respective machines
scp /tmp/nfs-server.keytab nfs.example.com:/etc/krb5.keytab
scp /tmp/nfs-client.keytab client.example.com:/etc/krb5.keytab
echo "Kerberos KDC configured"
Configure NFS v4 ????????? Kerberos Authentication
????????????????????? NFS Server ????????? Client ????????? Kerberos
# === NFS v4 + Kerberos Setup ===
# === On NFS Server (nfs.example.com) ===
# 1. Install NFS
dnf install -y nfs-utils krb5-workstation
# 2. Configure idmapd
cat > /etc/idmapd.conf << 'EOF'
[General]
Verbosity = 0
Domain = example.com
[Mapping]
Nobody-User = nfsnobody
Nobody-Group = nfsnobody
[Translation]
Method = nsswitch
EOF
# 3. Configure NFS exports with Kerberos
cat > /etc/exports << 'EOF'
# Syntax: path client(options)
# krb5 = authentication only
/exports/public *(sec=krb5,rw,sync,no_subtree_check)
# krb5i = authentication + integrity
/exports/shared *(sec=krb5i,rw,sync,no_subtree_check,root_squash)
# krb5p = authentication + integrity + encryption (most secure)
/exports/secure *(sec=krb5p,rw,sync,no_subtree_check,root_squash)
# Multiple security levels (client chooses)
/exports/flexible *(sec=krb5p:krb5i:krb5,rw,sync,no_subtree_check)
EOF
# 4. Create export directories
mkdir -p /exports/{public,shared,secure,flexible}
chmod 755 /exports/*
# 5. Configure gssproxy for NFS
cat > /etc/gssproxy/24-nfs-server.conf << 'EOF'
[service/nfs-server]
mechs = krb5
cred_store = keytab:/etc/krb5.keytab
cred_store = ccache:FILE:/var/lib/gssproxy/clients/krb5cc_%U
trusted = yes
kernel_nfsd = yes
euid = 0
EOF
# 6. Enable and Start Services
systemctl enable --now gssproxy
systemctl enable --now nfs-server
systemctl enable --now rpcbind
# Apply exports
exportfs -rav
# 7. Firewall
firewall-cmd --permanent --add-service=nfs
firewall-cmd --permanent --add-service=mountd
firewall-cmd --permanent --add-service=rpc-bind
firewall-cmd --reload
# === On NFS Client (client.example.com) ===
# 1. Install
dnf install -y nfs-utils krb5-workstation
# 2. Copy krb5.conf and idmapd.conf (same as server)
# 3. Mount with Kerberos
mkdir -p /mnt/{public,shared,secure}
# Mount with krb5p (encrypted)
mount -t nfs4 -o sec=krb5p nfs.example.com:/exports/secure /mnt/secure
# Mount with krb5i (integrity)
mount -t nfs4 -o sec=krb5i nfs.example.com:/exports/shared /mnt/shared
# 4. Persistent mount via fstab
cat >> /etc/fstab << 'EOF'
nfs.example.com:/exports/secure /mnt/secure nfs4 sec=krb5p,rw,_netdev 0 0
nfs.example.com:/exports/shared /mnt/shared nfs4 sec=krb5i,rw,_netdev 0 0
EOF
echo "NFS v4 + Kerberos configured"
SSL/TLS Certificate ?????????????????? NFS
?????????????????????????????????????????? TLS certificates
#!/usr/bin/env python3
# tls_management.py ??? TLS Certificate Management for NFS
import json
import logging
import subprocess
from datetime import datetime, timedelta
from typing import Dict, List
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("tls")
class TLSCertManager:
def __init__(self, ca_dir="/etc/pki/nfs-tls"):
self.ca_dir = ca_dir
def generate_ca(self):
"""Generate internal CA for NFS TLS"""
commands = [
# Create CA private key
f"openssl genrsa -out {self.ca_dir}/ca.key 4096",
# Create CA certificate (10 years)
f"openssl req -x509 -new -nodes -key {self.ca_dir}/ca.key "
f"-sha256 -days 3650 -out {self.ca_dir}/ca.crt "
f"-subj '/C=TH/ST=Bangkok/O=MyOrg/CN=NFS Internal CA'",
]
return {"steps": commands, "output_files": ["ca.key", "ca.crt"]}
def generate_server_cert(self, hostname, ip):
"""Generate server certificate signed by CA"""
san_config = f"""
[req]
distinguished_name = req_dn
req_extensions = v3_req
[req_dn]
CN = {hostname}
[v3_req]
subjectAltName = DNS:{hostname}, IP:{ip}
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
"""
commands = [
# Server private key
f"openssl genrsa -out {self.ca_dir}/{hostname}.key 2048",
# Certificate Signing Request
f"openssl req -new -key {self.ca_dir}/{hostname}.key "
f"-out {self.ca_dir}/{hostname}.csr "
f"-subj '/C=TH/ST=Bangkok/O=MyOrg/CN={hostname}' "
f"-config san.cnf",
# Sign with CA (2 years)
f"openssl x509 -req -in {self.ca_dir}/{hostname}.csr "
f"-CA {self.ca_dir}/ca.crt -CAkey {self.ca_dir}/ca.key "
f"-CAcreateserial -out {self.ca_dir}/{hostname}.crt "
f"-days 730 -sha256 -extensions v3_req -extfile san.cnf",
]
return {
"hostname": hostname,
"san_config": san_config,
"commands": commands,
"output_files": [f"{hostname}.key", f"{hostname}.crt"],
}
def check_cert_expiry(self, cert_path):
"""Check certificate expiry date"""
try:
result = subprocess.run(
["openssl", "x509", "-in", cert_path, "-enddate", "-noout"],
capture_output=True, text=True
)
if result.returncode == 0:
expiry_str = result.stdout.strip().replace("notAfter=", "")
return {"cert": cert_path, "expires": expiry_str, "status": "valid"}
except Exception as e:
return {"cert": cert_path, "error": str(e)}
return {"cert": cert_path, "status": "unknown"}
def nfs_tls_config(self):
"""NFS over TLS configuration (nfs-utils 2.6.4+)"""
return {
"server_config": {
"file": "/etc/nfs.conf",
"settings": {
"[nfsd]": {
"tls": "yes",
"tls-certfile": f"{self.ca_dir}/nfs-server.crt",
"tls-keyfile": f"{self.ca_dir}/nfs-server.key",
"tls-cafile": f"{self.ca_dir}/ca.crt",
},
},
},
"client_config": {
"mount_options": "xprtsec=tls",
"example": "mount -t nfs4 -o sec=krb5p, xprtsec=tls nfs.example.com:/exports/secure /mnt/secure",
},
}
mgr = TLSCertManager()
ca = mgr.generate_ca()
print("CA Generation:")
for cmd in ca["steps"]:
print(f" {cmd}")
server = mgr.generate_server_cert("nfs.example.com", "192.168.1.20")
print(f"\nServer Cert for: {server['hostname']}")
tls = mgr.nfs_tls_config()
print(f"\nMount with TLS: {tls['client_config']['example']}")
Client Configuration ????????? Automount
????????????????????? NFS client ????????? automount
# === NFS Client Automount with Kerberos ===
# 1. Install autofs
dnf install -y autofs nfs-utils krb5-workstation
# 2. Configure autofs master map
cat > /etc/auto.master << 'EOF'
# Mount point Map file Options
/nfs /etc/auto.nfs --timeout=300
/home /etc/auto.home --timeout=600
EOF
# 3. Configure NFS automount map
cat > /etc/auto.nfs << 'EOF'
# Key Options Location
secure -fstype=nfs4,sec=krb5p,rw nfs.example.com:/exports/secure
shared -fstype=nfs4,sec=krb5i,rw nfs.example.com:/exports/shared
public -fstype=nfs4,sec=krb5,rw nfs.example.com:/exports/public
EOF
# 4. Home directory automount (for centralized home dirs)
cat > /etc/auto.home << 'EOF'
# Wildcard: mount /home/ from NFS
* -fstype=nfs4, sec=krb5p, rw nfs.example.com:/exports/home/&
EOF
# 5. Start autofs
systemctl enable --now autofs
# 6. Test
ls /nfs/secure # Should trigger automount
ls /home/testuser # Should mount user's home
# 7. Kerberos Ticket for User
kinit testuser@EXAMPLE.COM
# Enter password
# Verify ticket
klist
# Shows TGT and NFS service ticket
# 8. Configure sssd for automatic ticket
cat > /etc/sssd/sssd.conf << 'EOF'
[sssd]
domains = EXAMPLE.COM
services = nss, pam
config_file_version = 2
[domain/EXAMPLE.COM]
id_provider = ldap
auth_provider = krb5
krb5_server = kdc.example.com
krb5_realm = EXAMPLE.COM
krb5_store_password_if_offline = true
krb5_renewable_lifetime = 7d
krb5_renew_interval = 3600
ldap_uri = ldaps://ldap.example.com
cache_credentials = true
EOF
chmod 600 /etc/sssd/sssd.conf
systemctl enable --now sssd
# 9. Performance Tuning
cat >> /etc/nfs.conf << 'EOF'
[nfsd]
threads = 16
[mountd]
threads = 4
[gssd]
use-memcache = yes
preferred-realm = EXAMPLE.COM
EOF
# NFS mount options for performance
# rsize=1048576,wsize=1048576 ??? max read/write size
# noatime ??? don't update access time
# nocto ??? disable close-to-open consistency (careful!)
echo "Client automount configured"
Troubleshooting ????????? Monitoring
Debug NFS Kerberos issues
#!/usr/bin/env python3
# nfs_monitor.py ??? NFS Kerberos Monitoring
import json
import logging
import subprocess
from typing import Dict
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("monitor")
class NFSKerberosMonitor:
def __init__(self):
self.checks = []
def troubleshooting_guide(self):
return {
"common_issues": {
"mount_fails_sec_krb5": {
"symptom": "mount.nfs4: access denied by server",
"causes": [
"Keytab missing or wrong principal",
"Clock skew > 5 minutes between KDC and NFS server",
"DNS not resolving correctly (reverse DNS important)",
"gssproxy not running",
],
"debug_commands": [
"klist -ke /etc/krb5.keytab",
"kinit -k nfs/nfs.example.com@EXAMPLE.COM",
"rpcdebug -m nfs -s all",
"journalctl -u gssproxy -f",
"ntpstat",
],
},
"permission_denied": {
"symptom": "Permission denied after mount",
"causes": [
"UID/GID mapping mismatch (idmapd)",
"root_squash blocking root access",
"Kerberos principal not mapped to local user",
],
"debug_commands": [
"nfsidmap -l",
"id username",
"cat /proc/net/rpc/auth.unix.gid/content",
],
},
"slow_performance": {
"symptom": "NFS operations very slow",
"causes": [
"krb5p encryption overhead",
"Small rsize/wsize",
"Too few NFS threads",
"Network latency",
],
"debug_commands": [
"nfsstat -c",
"nfsiostat 1",
"mountstats /mnt/secure",
],
},
},
}
def health_checks(self):
return {
"kerberos": [
{"check": "KDC reachable", "command": "kinit -k host/$(hostname)@EXAMPLE.COM"},
{"check": "Keytab valid", "command": "klist -ke /etc/krb5.keytab"},
{"check": "Clock sync", "command": "chronyc tracking | grep 'System time'"},
{"check": "DNS forward", "command": "host nfs.example.com"},
{"check": "DNS reverse", "command": "host 192.168.1.20"},
],
"nfs": [
{"check": "NFS server running", "command": "systemctl is-active nfs-server"},
{"check": "Exports active", "command": "exportfs -v"},
{"check": "RPC services", "command": "rpcinfo -p localhost"},
{"check": "gssproxy running", "command": "systemctl is-active gssproxy"},
{"check": "NFS mounts", "command": "mount -t nfs4"},
],
"tls": [
{"check": "Cert valid", "command": "openssl x509 -in /etc/pki/nfs-tls/nfs-server.crt -checkend 2592000"},
{"check": "Cert chain", "command": "openssl verify -CAfile ca.crt nfs-server.crt"},
],
}
monitor = NFSKerberosMonitor()
guide = monitor.troubleshooting_guide()
for issue, info in guide["common_issues"].items():
print(f"\n{issue}: {info['symptom']}")
for cause in info["causes"]:
print(f" - {cause}")
checks = monitor.health_checks()
total = sum(len(v) for v in checks.values())
print(f"\nHealth checks: {total} checks defined")
FAQ ??????????????????????????????????????????
Q: krb5 ????????? krb5i ????????? krb5p ?????????????????????????????????????????? ??????????????????????????????????
A: krb5 authentication only ?????????????????????????????????????????????????????? ????????? data ????????????????????? plaintext ???????????? network ???????????????????????? network ????????????????????? (isolated VLAN) krb5i ??????????????? integrity check ????????? packet ?????? checksum ????????????????????? data ?????????????????????????????????????????????????????? ????????? data ????????? plaintext overhead ????????????????????? (~2-5%) krb5p ??????????????? encryption ????????? packet ????????? encrypt ????????????????????????????????? tampering ????????? eavesdropping ??????????????????????????????????????? overhead ????????????????????? (~10-20% ????????????????????? CPU) ?????????????????? production ??????????????? krb5p ?????????????????? sensitive data, krb5i ?????????????????? general use, krb5 ??????????????? trusted network
Q: NFS v4 ????????????????????? Kerberos ??????????
A: ??????????????????????????? NFS v4 ?????????????????? sec=sys (AUTH_SYS) ?????????????????? v3 ????????? UID/GID mapping ??????????????? encryption ????????? Kerberos recommended ??????????????????????????? production ??????????????? AUTH_SYS ????????????????????? security UID/GID spoofing ???????????? ???????????????????????????????????? UID ???????????????????????????????????? ??????????????? encryption data ????????? plaintext ??????????????? integrity check data ?????????????????? tamper Kerberos ????????????????????????????????????????????? ???????????????????????????????????????????????? KDC, encrypt data (krb5p), integrity check (krb5i) ????????????????????? setup ????????????????????????????????? ?????????????????? KDC infrastructure
Q: Clock sync ??????????????????????????????????????????????????? Kerberos?
A: ???????????????????????? Kerberos ?????? default clock skew tolerance 5 ???????????? ????????? clock ????????????????????? KDC, server ????????? client ????????????????????????????????? 5 ???????????? authentication ?????? fail ??????????????? ????????? error KRB5KRB_AP_ERR_SKEW ????????????????????? NTP (chrony ???????????? ntpd) sync ?????????????????????????????????????????? ??????????????? ????????? NTP server ?????????????????????????????????????????????????????? ???????????? chrony maxpoll 6 (64 ??????????????????) ?????????????????? accuracy ?????? monitor clock offset ???????????? Prometheus node_exporter (node_timex_offset_seconds) alert ??????????????? offset ???????????? 2 ????????????
Q: NFS over TLS (xprtsec=tls) ????????????????????? ????????????????????? krb5p ??????????????????????
A: NFS over TLS ??????????????????????????????????????????????????? Linux kernel 6.x ????????? nfs-utils 2.6.4+ ????????? TLS encrypt transport layer ????????????????????? (?????????????????? HTTPS) ????????????????????? krb5p ?????????????????? krb5p encrypt ??????????????? RPC payload ????????? Kerberos crypto (AES) NFS/TLS encrypt ??????????????? transport ????????? TLS 1.3 crypto ???????????????????????? NFS/TLS ????????????????????? Kerberos infrastructure ????????? certificate-based auth ???????????????????????? performance ?????????????????? krb5p ??????????????? TLS hardware acceleration ?????????????????????????????? Kerberos ????????? (sec=krb5+xprtsec=tls) ????????????????????? ?????????????????????????????????????????????????????? ???????????? kernel ????????? nfs-utils version ????????????
