Introduction to Kerberos (part 1)
Bear Giles | April 17, 2016Old protocols never die.
Kerberos is a three party protocol that provides strong mutual authentication between clients and servers. It is designed for academic and enterprise organizations where there is a single source of truth regarding identify, authentication and authorization. Think universities with faculty, students, and staff, or businesses with employees with different responsibilities. Changes must be propagated immediately – it is not acceptable for there to be a lag such as we see with X.509 digital certificates using periodically updated CRL lists. (It is possible, but expensive, to use OCSP to verify a certificate on each use.)
Strong mutual authentication is when both parties to a transaction have high confidence in the identity of the other party. A good example is when you log onto your bank’s website. The bank authenticates the user with username, password, and second factor like the user accepting the “personal image”. The user authenticates the bank by checking the HTTPS icon in the corner and the recognized “personal image”. Many of us consider the latter somewhat broken since the system will accept a certificate from ANY certificate authority preloaded into the browser. I have nothing against the Moldovian postal service but I don’t want to have to trust it in order to check my bank balance. I have nothing against it but I have no reason to trust it either. With Kerberos there’s a personal relationship – it is our employer, our university, etc., so there’s a much higher level of trust.
Kerberos came out of the Athena project at MIT in the 1980s and was “embraced and extended” by the Borg, I mean by Microsoft, in Windows 2000 as the basis of Active Directory. The “client” was traditionally a person but it is increasingly software as well.
There are three open source Kerberos implementations widely available to Linux users: MIT, Heimdal, and Shishi. MIT Kerberos 5 is the reference implementation and somewhat more tuned to enterprise users, Heimdal is an implementation made outside of the US, and I know nothing about Shishi. The fact that Heimdal was developed outside of the US was important while the US banned export under ITAR regulations (since it includes strong encryption) and may become important again and we refight the crypto wars.
I will be discussing MIT Kerberos since I’m a little more familiar with it.
The Three-Headed Hellhound
Kerberos is named after the three-headed dog that guards the gate of Hell. This reflects the three parties in a Kerberos session:
The Client
The client may be a person (student, employee) or enterprise software. The client does not log into a remote system. Instead the client logs into a local agent and that agent performs all necessary negotiation with the KDC and servers. In the protocol this is the “ticket granting ticket (TGT)”.
As mentioned earlier the client may also be enterprise software.
The Server
The server can be any software requiring authentication. Traditional servers include telnet (ktelnet) allowing remote access to a shell and NFS (allowing remote access to a filesystem). In the enterprise environment we often see kerberized web services.
The Key Distribution Center (KDC)
The key distribution center (KDC) is the trusted third party. In early implementations the KDC was literally responsible for generating symmetric keys to be used by the client and server, hence the name. I don’t know if that’s still true. The client and server are free to renegotiate their session keys at any time.
All of this occurs within a Kerberos realm. This is an arbitrary string but by convention is the domain name in all caps, e.g., INVARIANTPROPERTIES.COM. This ensures that realms will be unique (modulo bad players). Users within a realm are identified by principals. An individual may have more than one principal but no principal should be used by more than one individual. Principals have the format username@REALM or username/role@REALM, e.g., bgiles/admin@INVARIANTPROPERTIES.COM. Servers have a similar format: servicename/fqdn@REALM.
KDC installation on Debian and Ubuntu
Today we will discuss the installation and configuration of an MIT Kerberos5 KDC on an AWS EC2 instance. MIT can use either an internal database or LDAP for its backing store. The latter will be a better choice if you already use an LDAP database for user management.
I will only discuss the former in this blog entry but might revisit the latter in the future.
Hardware Requirements
The primary hardware requirement for a KDC is security. A compromised KDC will put the entire enterprise at risk. It should be physically secured and run no other services. In production we want at least two servers (one primary and at least one secondary) and they should be in physically separate locations.
It is extremely important that the clocks are synchronized across the all systems within a realm. Historically tickets would be valid for 5 to 15 minutes but with NTP running on all systems this window can be reduced to seconds. Note: this is the window when a ticket can be used for authentication and has no bearing on how long the user can use the service.
A KDC has modest computational requirements. I believe we can start with a micro instance and only upgrade if the need arises. This means the financial cost is extremely modest even if we use multiple KDCs.
We need to open three ports in our firewall. Ports 88 and 750 are required by Kerberos, port 22 for SSH is only required for initial installation and can can be blocked at the AWS Security Group level unless explicitly needed. Subsequent access can eat its own dog food with ktelnet (kerberized telnet), krsh (kerberized rsh), or SSH with Kerberos extensions.
The KDC admin server must also open port 749. Access to this port should be limited.
Debian/Ubuntu Packages
We need to install two packages: krb5-kdc and krb5-admin-server. If you are using LDAP you will want to install krb5-ldap as well. Finally we want to install krb5-doc for documentation.
- $ sudo apt-get install krb5-kdc krb5-admin-server krb5-doc
$ sudo apt-get install krb5-kdc krb5-admin-server krb5-doc
During installation we will be asked three things:
- Name of our realm – this is traditionally our domain name in all-caps.
- KDC servers – this system
- KDC admin servers – this system
If you wish you can leave the servers blank at this time and fix the /etc/krb5.conf file below.
Database Initialization
We initialize the internal database with a call to krb5_util. We need to provide our realm name.
- $ sudo /usr/sbin/kdb5_util create -r INVARIANTPROPERTIES.COM -s
$ sudo /usr/sbin/kdb5_util create -r INVARIANTPROPERTIES.COM -s
This will take a minute or so to complete.
Defining user rights
We define our users’ rights via an ACL file – /etc/krb5kdc/kadm5.acl. See the man pages for details. One thing to keep in mind is that the user will remain logged in for 7 days by default. Roles with more authority should require reauthentication more frequently.
/etc/krb5dkc/kadm5.acl
- */admin@INVARIANTPROPERTIES.COM x * -maxlife 4h
- */root@INVARIANTPROPERTIES.COM ci *1@INVARIANTPROPERTIE.COM
- */root@INVARIANTPROPERTIES.COM l *
*/admin@INVARIANTPROPERTIES.COM x * -maxlife 4h */root@INVARIANTPROPERTIES.COM ci *1@INVARIANTPROPERTIE.COM */root@INVARIANTPROPERTIES.COM l *
See the man page for kadm5.acl for a description of these entries. The gist is that any principal with ‘admin’ has full administrative rights but must reauthenticate every 4 hours. The superuser on any system can list and update user credentials.
Creating our first administrative user(s)
We must bootstrap our administrative users on the KDC itself. Subsequent user management can be handled remotely. Note that we do NOT need the master password for this – this is why it is critical that access to the KDC be limited.
This shows how to add a user with both regular and administrative rights.
- $ sudo kadmin.local
- kadmin.local: add_principal bgiles
- Enter password for principal "bgiles@INVARIANTPROPERTIES.COM": *******
- Re-enter password for principal "bgiles@INVARIANTPROPERTIES.COM": *******
- kadmin.local: add_principal bgiles/admin
- Enter password for principal "bgiles/admin@INVARIANTPROPERTIES.COM": *******
- Re-nter password for principal "bgiles/admin@INVARIANTPROPERTIES.COM": *******
- kadmin.local: quit.
$ sudo kadmin.local kadmin.local: add_principal bgiles Enter password for principal "bgiles@INVARIANTPROPERTIES.COM": ******* Re-enter password for principal "bgiles@INVARIANTPROPERTIES.COM": ******* kadmin.local: add_principal bgiles/admin Enter password for principal "bgiles/admin@INVARIANTPROPERTIES.COM": ******* Re-nter password for principal "bgiles/admin@INVARIANTPROPERTIES.COM": ******* kadmin.local: quit.
Registering our servers
If you did not specify the KDC server and KDC admin servers when we installed the packages you can fix this now. Edit the appropriate entry in the /etc/krb5.conf file:
- ,,,
- [realms]
- INVARIANTPROPERTIES.COM = {
- kdc = kdc1.invariantproperties.com:88
- kdc = kdc2.invariantproperties.com:88
- admin_server = kdc1.invariantproperties.com
- default_domain = invariantproperties.com
- }
- ...
- [domain_realm]
- .invariantproperties.com = INVARIANTPROPERTIES.COM
- invariantproperties.com = INVARIANTPROPERTIES.COM
- ...
,,, [realms] INVARIANTPROPERTIES.COM = { kdc = kdc1.invariantproperties.com:88 kdc = kdc2.invariantproperties.com:88 admin_server = kdc1.invariantproperties.com default_domain = invariantproperties.com } ... [domain_realm] .invariantproperties.com = INVARIANTPROPERTIES.COM invariantproperties.com = INVARIANTPROPERTIES.COM ...
This snippet demonstrates how to specify multiple KDC servers. I have not discussed how to perform database replication among multiple KDC servers. This is one task where an LDAP backing store would make much more convenient.
Preparing the Client
We are now ready to set up the client systems so the user can log into Kerberos (that is, get a ticket-granting-ticket (TGT)). I am not going to discuss setting up and accessing kerberized services at this time.
Debian/Ubuntu Packages
We need to install one package: krb5-user. We may also want to install krb5-doc for the rare user who reads the documentation before calling the help desk.
- $ sudo apt-get install krb5-user krb5-doc
$ sudo apt-get install krb5-user krb5-doc
You will be asked to specify the Kerberos realm, KDC and KDC admin servers.
Logging in and out
The user can now log into the system using kinit. This command has many options – see the man page for details.
- $ kinit
- Password for bgiles@INVARIANTPROPERTIES.COM: ******
- $ kinit bgiles/admin
- Password for bgiles/admin@INVARIANTPROPERTIES.COM ******
$ kinit Password for bgiles@INVARIANTPROPERTIES.COM: ****** $ kinit bgiles/admin Password for bgiles/admin@INVARIANTPROPERTIES.COM ******
We can determine our current credentials with klist
- $ klist
- Ticket cache: FILE:/tmp/krb5cc_1000
- Default principal: bgiles/admin@INVARIANTPROPERTIES.COM
- Valid starting Expires Service principal
- 04/17/2016 09:40:51 04/17/2016 19:40:51 krbtgt/INVARIANTPROPERTIES.COM@INVARIANTPROPERTIES.COM
- renew until 04/18/2016 09:40:46
$ klist Ticket cache: FILE:/tmp/krb5cc_1000 Default principal: bgiles/admin@INVARIANTPROPERTIES.COM Valid starting Expires Service principal 04/17/2016 09:40:51 04/17/2016 19:40:51 krbtgt/INVARIANTPROPERTIES.COM@INVARIANTPROPERTIES.COM renew until 04/18/2016 09:40:46
(note that the credentials expire at 10 hours, not 4 hours. I need to look into that…)
Finally we can log out with kdestroy
- $ kdestroy
- $ klist
- klist: Credentials cache file '/tmp/krb5cc_1000' not found
$ kdestroy $ klist klist: Credentials cache file '/tmp/krb5cc_1000' not found
You can change your password with kpasswd and change your active principal with kswitch.
Remote administration
Administrators can run kadmin remotely. It is no longer necessary for them to physically log into the KDC and run kadmin.local. They will be prompted to reenter their credentials since this is a sensitive operation.
Keytab files
Finally it can be inconvenient to re-enter your password every time you access a remote service. Keytab files allow you to store a Kerberos principal and encryption key for us in place of a password. You must regenerate the keytab files every time you change your Kerberos password.
Keytabs are maintained with the ktutil command.
For more information see What is a keytab, and how do I use one? from Indiana University.
Next Time
Next time I will discuss setting up kerberized services.
Finally A Cautionary Tale
I almost forgot something important – a server should never ask for a user’s Kerberos credentials. The user always performs local authentication and everything else is negotiated behind the scenes. I mention this because Apache had (and still has?) a Kerberos authentication module that worked by prompting the user for his Kerberos credentials and then logging into the system as that that user on the server in order to obatain resources from other systems. This is entirely contrary to the design goals of Kerberos and it is a huge red flag when it happens – it is possible to get “transferable” tickets that can be used by a server on your behalf.