Configure a Kerberos Client on AlmaLinux 10

Once your realm has a KDC, the next job is pointing machines at it. A Kerberos client needs four things: an accurate clock, a /etc/krb5.conf that knows where the KDCs are, a host keytab so other systems can trust it, and (if you want logins to use Kerberos passwords) SSSD wired into PAM. With those in place, users can run kinit, get a ticket at login, and SSH between hosts without typing a password again.

This guide configures an AlmaLinux 10 client (10.2 at the time of writing, krb5 1.21) against the realm built in Set Up an MIT Kerberos KDC on AlmaLinux 10 and made highly available in Set Up a Kerberos Primary and Replica KDC on AlmaLinux 10. The same steps work on AlmaLinux 9.x, Rocky Linux, Oracle Linux and RHEL, with one difference noted in the SSSD section.

Lab layout used in this guide

  • Realm: EXAMPLE.COM
  • Primary KDC and admin server: kdc1.example.com at 192.168.1.10
  • Replica KDC: kdc2.example.com at 192.168.1.11
  • Kerberized SSH server from the keytab post: web1.example.com at 192.168.1.20
  • New client: client1.example.com at 192.168.1.30, AlmaLinux 10.2 minimal, SELinux enforcing
  • Admin principal admin/admin@EXAMPLE.COM and test user alice@EXAMPLE.COM

Replace these names with your own everywhere they appear.

Prerequisites

  • A working KDC. If you do not have one yet, follow Set Up an MIT Kerberos KDC on AlmaLinux 10 first.
  • Forward and reverse DNS for every host, or matching /etc/hosts entries. Kerberos service principals are tied to fully qualified hostnames.
  • Time synchronized with chrony on the client and the KDCs. By default Kerberos rejects requests when clocks differ by more than 5 minutes.
  • Root or sudo access on the client, and the admin/admin password.
  • Outbound access from the client to the KDCs on TCP and UDP port 88, TCP port 749 for kadmin and TCP and UDP port 464 for password changes. No inbound firewall changes are needed on the client except SSH, which AlmaLinux allows by default.

Step 1: Set the hostname and name resolution

sudo hostnamectl set-hostname client1.example.com
hostname -f

If you do not have DNS for the lab, add the hosts to /etc/hosts on the client:

192.168.1.10  kdc1.example.com    kdc1
192.168.1.11  kdc2.example.com    kdc2
192.168.1.20  web1.example.com    web1
192.168.1.30  client1.example.com client1

Add the client1 line to /etc/hosts on the KDCs and on web1 as well, so they can resolve the new client.

Step 2: Make sure time is synchronized

sudo dnf install -y chrony
sudo systemctl enable --now chronyd
chronyc tracking
timedatectl

timedatectl should report System clock synchronized: yes. If the offset in chronyc tracking is large, fix it before going further, because every later step depends on it.

Step 3: Install the client packages

sudo dnf install -y krb5-workstation sssd sssd-krb5 sssd-proxy sssd-tools openssh-clients

krb5-workstation provides kinit, klist, kvno, kpasswd and kadmin. The SSSD packages are only needed if you want Kerberos password logins (Step 7). If you only want users to run kinit and use SSH with tickets, krb5-workstation is enough.

Step 4: Configure /etc/krb5.conf

The simplest way to get a correct client configuration is to copy it from a KDC, since it already lists both KDCs:

sudo scp root@kdc1.example.com:/etc/krb5.conf /etc/krb5.conf
sudo restorecon -v /etc/krb5.conf

If you prefer to write it by hand, this is the full file. Keep the includedir line at the top: on AlmaLinux it pulls in the system crypto policy for Kerberos.

includedir /etc/krb5.conf.d/

[logging]
    default = FILE:/var/log/krb5libs.log

[libdefaults]
    default_realm = EXAMPLE.COM
    dns_lookup_realm = false
    dns_lookup_kdc = false
    ticket_lifetime = 24h
    renew_lifetime = 7d
    forwardable = true
    rdns = false
    pkinit_anchors = FILE:/etc/pki/tls/certs/ca-bundle.crt
    spake_preauth_groups = edwards25519
    dns_canonicalize_hostname = fallback
    qualify_shortname = ""
    default_ccache_name = KEYRING:persistent:%{uid}

[realms]
    EXAMPLE.COM = {
        kdc = kdc1.example.com
        kdc = kdc2.example.com
        admin_server = kdc1.example.com
        primary_kdc = kdc1.example.com
    }

[domain_realm]
    .example.com = EXAMPLE.COM
    example.com = EXAMPLE.COM

The client tries the kdc entries in order and fails over to kdc2 if kdc1 does not answer. primary_kdc tells the client to retry a failed password check against the primary, which matters right after a password change that has not propagated to the replica yet. admin_server must always point at the primary, because only it runs kadmind.

If you published the DNS SRV records described in the KDC post, you can set dns_lookup_kdc = true instead and drop the kdc lines, which saves editing every client when a KDC changes.

Step 5: Test kinit as a user

kinit alice
klist
kdestroy

klist should show a krbtgt/EXAMPLE.COM@EXAMPLE.COM ticket with the 24-hour lifetime set in the configuration. If it does, the client can reach a KDC and the realm configuration is correct.

Step 6: Create the host principal and keytab

A host keytab lets the client act as an SSH server for Kerberos logins and lets SSSD verify that tickets really came from your KDC. Run these on the client; kadmin asks for the admin/admin password:

sudo kadmin -p admin/admin -q "addprinc -randkey host/client1.example.com"
sudo kadmin -p admin/admin -q "ktadd host/client1.example.com"

sudo klist -ke /etc/krb5.keytab
sudo chmod 600 /etc/krb5.keytab
sudo restorecon -v /etc/krb5.keytab

Confirm the keytab works by getting a ticket with it instead of a password:

sudo kinit -k host/client1.example.com
sudo klist
sudo kdestroy

Remember that ktadd randomizes the key each time it runs. See Create and Manage Kerberos Keytabs on AlmaLinux 10 for extracting keytabs on the KDC, rotation and the other details.

Step 7: Use Kerberos passwords for logins with SSSD

This step makes a normal password login (console, SSH or su) check the password against the KDC and leave the user with a ticket, so they never have to run kinit by hand. Here user accounts stay local in /etc/passwd and only the password lives in Kerberos. If you have a directory such as LDAP, FreeIPA or Active Directory, use its SSSD provider instead; Join CentOS/RedHat to Active Directory Domain covers the Active Directory case.

AlmaLinux 10 removed the old SSSD files provider and now uses the local authselect profile by default. The supported way to combine local accounts with Kerberos authentication is the SSSD proxy identity provider with the krb5 authentication provider. That is why sssd-proxy was installed in Step 3.

Create the local account without a local password, so the only password that works is the Kerberos one:

sudo useradd alice
sudo passwd -S alice

passwd -S should report the password as locked or not set. Next create /etc/sssd/sssd.conf:

[sssd]
services = nss, pam
domains = EXAMPLE.COM

[domain/EXAMPLE.COM]
id_provider = proxy
proxy_lib_name = files
auth_provider = krb5
chpass_provider = krb5
krb5_realm = EXAMPLE.COM
krb5_server = kdc1.example.com, kdc2.example.com
krb5_kpasswd = kdc1.example.com
krb5_validate = true
krb5_renewable_lifetime = 7d
krb5_renew_interval = 1h
cache_credentials = true
krb5_store_password_if_offline = true

krb5_server lists both KDCs for failover, and krb5_kpasswd sends password changes to the primary. krb5_validate = true makes SSSD check each new ticket against the host keytab from Step 6, which stops an attacker from logging in with a fake KDC. The last two lines let users log in with their cached password when no KDC is reachable.

SSSD refuses to start unless the file is owned by root with mode 600. Set that, switch the system to the sssd authselect profile and start the service:

sudo chown root:root /etc/sssd/sssd.conf
sudo chmod 600 /etc/sssd/sssd.conf
sudo restorecon -v /etc/sssd/sssd.conf

sudo authselect select sssd
sudo authselect current
sudo systemctl enable --now sssd

The sssd profile puts pam_sss into the PAM stack and sss into /etc/nsswitch.conf. Check that passwd and group list sss:

grep -E '^(passwd|group|shadow):' /etc/nsswitch.conf

On AlmaLinux 9 you can still use this exact configuration. The older id_provider = files setting also works there, but it is deprecated and will not survive an upgrade to 10.

Step 8: Enable Kerberos (GSSAPI) logins for SSH

AlmaLinux already enables GSSAPI authentication in the default OpenSSH configuration (in /etc/ssh/sshd_config.d/50-redhat.conf and /etc/ssh/ssh_config.d/50-redhat.conf). Confirm it on the client:

sudo sshd -T | grep -i gssapi
ssh -G web1.example.com | grep -i gssapi

You want gssapiauthentication yes in both outputs. If not, create /etc/ssh/sshd_config.d/60-kerberos.conf:

GSSAPIAuthentication yes
GSSAPICleanupCredentials yes
sudo sshd -t && sudo systemctl reload sshd

Every SSH server that should accept tickets needs its own host/ principal in /etc/krb5.keytab, and the user needs a local account with the same name as the principal. MIT Kerberos maps alice@EXAMPLE.COM to the local user alice because EXAMPLE.COM is the default realm. To let a different principal into an account, list it in that account’s ~/.k5login file, one principal per line. Once a .k5login exists, only the principals in it are allowed.

Forwarding the ticket to the remote host is off by default. Turn it on only for hosts you trust, for example in ~/.ssh/config:

Host *.example.com
    GSSAPIAuthentication yes
    GSSAPIDelegateCredentials yes

Verify the client

Name lookups and SSSD status

getent passwd alice
id alice
sudo sssctl user-checks alice

getent and id should return the local account, and sssctl user-checks should show that SSSD can look up alice and that PAM account checks pass.

Log in with the Kerberos password

From another machine, or from the client itself, log in as alice with password authentication and check that a ticket was created:

ssh -o PreferredAuthentications=keyboard-interactive,password alice@client1.example.com
klist

klist should show a krbtgt/EXAMPLE.COM ticket for alice@EXAMPLE.COM with a KEYRING:persistent cache, without you having run kinit.

SSH with a ticket instead of a password

With that ticket still active, SSH to web1, which already has a host keytab and needs a local alice account (sudo useradd alice):

ssh -v alice@web1.example.com hostname 2>&1 | grep -i 'authenticated'
klist

The verbose output should include Authenticated to web1.example.com using "gssapi-with-mic", and klist on the client now also lists a host/web1.example.com@EXAMPLE.COM service ticket. Always connect with the fully qualified hostname so the client requests the right service principal.

Change a password

kpasswd

kpasswd talks to kadmind on the primary through port 464. Users who log in through SSSD can also use the normal passwd command, which SSSD forwards to Kerberos because of chpass_provider = krb5.

Failover

Stop krb5kdc on kdc1 for a moment and run kinit alice on the client again. It should still succeed, served by kdc2. Start krb5kdc on kdc1 again afterwards.

Troubleshooting

For any kinit problem, start by running it with tracing turned on. The trace shows which KDCs the client tried, which encryption types it used and the exact error:

KRB5_TRACE=/dev/stderr kinit alice

kinit: Cannot find KDC for realm “EXAMPLE.COM” while getting initial credentials

The client does not know where the KDC is. Check the [realms] section of /etc/krb5.conf, that the realm name is uppercase and matches exactly, and that the KDC hostnames resolve. If you use dns_lookup_kdc = true, confirm the SRV records with dig _kerberos._udp.example.com SRV.

kinit: Cannot contact any KDC for realm ‘EXAMPLE.COM’ while getting initial credentials

The client found the KDC but cannot reach it. Test port 88 with nc -vz kdc1.example.com 88, and check that kerberos is allowed in firewalld on the KDCs (sudo firewall-cmd --list-services).

Clock skew too great

The client and KDC clocks differ by more than the allowed skew. Fix chrony on both sides (chronyc sources -v) rather than raising clockskew.

SSH still asks for a password

Run ssh -vvv and look for the GSSAPI lines. Common causes are a missing host/ principal in the server’s keytab (sudo klist -k on the server), connecting by IP address or short name instead of the FQDN, no valid ticket on the client (klist), a missing local account on the server, or a ~/.k5login on the server that does not list the principal. On the server, sudo journalctl -u sshd usually names the reason.

SSSD will not start, or the password login fails

Check sudo journalctl -u sssd and sudo sssctl config-check. Wrong permissions on sssd.conf and typos in option names are the usual causes. If authentication fails only with krb5_validate = true, the host keytab is missing or out of date, so re-run Step 6. For more detail, set debug_level = 6 in the domain section, restart SSSD and read /var/log/sssd/krb5_child.log and /var/log/sssd/sssd_EXAMPLE.COM.log.

klist shows no ticket after logging in

Make sure authselect current reports the sssd profile and that the login went through password authentication, not an SSH key. A login with an SSH public key never sends a password, so there is nothing to get a ticket with. Also check which cache is in use: if sssd-kcm is installed, its file in /etc/krb5.conf.d/ switches the default cache to KCM:, which is fine but changes what klist prints.

Next steps

Your AlmaLinux clients now get tickets at login and use them for passwordless SSH. Repeat Steps 1 to 8 on each new machine, or put them in an Ansible role or kickstart file. From here you can Kerberize other services on the same hosts, such as NFS with sec=krb5p or Apache with an HTTP/ keytab as shown in Create and Manage Kerberos Keytabs on AlmaLinux 10. If you have many users, move their accounts into LDAP or FreeIPA so SSSD can look them up centrally instead of creating local accounts on every host.

References: MIT Kerberos: krb5.conf, MIT Kerberos: Installing and configuring UNIX client machines, SSSD: Files provider removal and Red Hat: Configuring authentication and authorization in RHEL 10.

Leave a Reply

Your email address will not be published. Required fields are marked *