Simple usage of Kerberos for SSH authentication on FreeBSD

17 Feb 2020 - tsp
Last update 17 Feb 2020
Reading time 9 mins

This article should provide a short introduction on how to setup Kerberos based authentication inside on owns network. Kerberos is one of the most used single sign on solutions used today (it’s also used behind the surface for Windows Domains) an provides authentication over insecure networks like the Internet - of course that means it’s also suited for authentication inside a corporate or home network. Basically it provides authentication using tickets - users authenticate against the ticket authentication server (using kinit or - most of the time - embedded in one own’s login procedure). This authentication might happen (as in this tutorial) using passwords but it may also happen using certificates or other mechanisms. After the user has authenticated itself against the KDC an ticket granting ticket is issued and stored at the users maching. This can be listed using klist. For every service that a user wants to access the client (transparently) asks the ticket granting service for an ticket to access the given service - using the ticket granting ticket for one owns authentication. The ticket granting service then issues an session ticket which is then used to authenticate against the service itself.

Note that authentication is not done crossing domain (administrative) boundaries. All services that one authenticates have to be situated inside the same domain as the user. Kerberos identifies domains using strings similar to domains known from the DNS system - but keep in mind that they basically live in a different namespace (although they are normally overlapping and some autodiscovery methods to detect the KDC are using that identity).

Kerberos provides single sign on when one has kerberized all key services. Most services used today support this including:

For web applications there are some different methods to kerberize intranet applications (like SPNEGO). They do work - but there are some formal problems since they violate the strict rules defined by the HTTP specification when it comes to the Authorization header. One should note that one cannot easily mix Kerberos and other authentication mechanisms on a webpage.

Single sign on in this context means that the user is only required to authenticate one, the Kerberos service is then providing authentication information to the services in a transparent way.

Most of the time Kerberos authentication is accompanied by an metadata distribution system like LDAP to provide properties to name services like providing Unix user IDs, group memberships, mailadresses, home directories, locations of mail directories, properties for XACML policy information points, etc. This will not be handeled in this blog post.

Requirements

Key distribution center setup

Basically all tools required to setup a KDC are part of the base system. One can simply enable the kdc (the key distribution center) as well as the kerberos administration system which provides a way to add users, set passwords, etc. (kadmind) inside one’s /etc/rc.conf

kdc_enable="YES"
kadmind_enable="YES"

Then one should configure one’s /etc/krb5.conf. Basically this would not be required but it makes live somewhat easier:

[libdefaults]
    default_realm = EXAMPLE.COM
    dns_lookup_kdc = yes
    dns_lookup_realm = yes

One should also add some records into the DNS zone:

_kerberos._udp      IN SRV   10 0 88     kerberoskdc
_kerberos._tcp      IN SRV   10 0 88     kerberoskdc
_kpasswd._udp       IN SRV   10 0 464    kerberoskdc
_kerberos-adm._tcp  IN SRV   10 0 749    kerberoskdc
_kerberos-iv._udp   IN SRV   10 0 88     kerberoskdc

In this case the hostname of the KDC an administrative server is assumed to be kerberoskdc.

Now one should initialize the Kerberos database. This is done using the kstash database. The password one supplies is used to encrypt the database. One should use a rather long (64 or more) characters random password. There is no need to remember that password besides for having to enter (or pasting) it two times since it’s stored on the KDC machine to allow automatic booting an access to the database.

root@kdc# kstash
Master key: **********
Verifying password - Master key: **********

Now one can connect to the local KDC and initialize the database for the given realm:

root@kdc# kadmin -l
kadmin> init EXAMPLE.COM
Realm max ticket life [unlimited]:

After that one can start to add initial users:

kadmin> add testuser
Max ticket life [unlimited]:
Max renewable life [unlimited]:
Attributes []:
Password: ********
Verifying password - Password: ********

Now one can start the services

root@kdc# /etc/rc.d/kdc start
root@kdc# /etc/rc.d/kadmind start

and test the service by requesting a ticket:

kdc$ kinit testuser

If that was successful one can list all tickets present in ones credential cache:

kdc$ klist
Credentials cache: FILE:/tmp/krb5cc_1001
        Principal: testuser@EXAMPLE.COM

  Issued                Expires               Principal
Feb 17 01:45:33 2020  Feb 17 11:45:33 2020  krbtgt/EXAMPLE.COM@EXAMPLE.COM

To remove all tickets from the local cache on uses kdestroy:

kdc$ kdestroy

Adding an server / host

One should add a /etc/krb5.conf to provide an default realm and enable DNS lookup for realm and KDC:

[libdefaults]
   default_realm = EXAMPLE.COM
   dns_lookup_kdc = yes
   dns_lookup_realm = yes

After that one should create an host principal and export the given key into the hosts keytab. One can do this from the root user:

root@newhost# kinit [User that has permissions]
root@newhost # kadmin
kadmin> add --random-key host/hostname.example.com
kadmin> ext_keytab host/hostname.example.com
kadmin> exit
root@newhost # kdestroy

Of course one can also do any step except the ext_keytab command on any other host on the network that one’s trusting. Note that the supplied hostname.example.com hostname should be the canonicalized hostname. This is the hostname that one get’s when one first resolves the hostname that one’s connecting to using DNS and then re-resolving the IP address using the reverse DNS zone. This has the effect of giving an host that’s aliased using multiple CNAME records an unique name.

If one - for example - has the following records in DNS:

$ORIGIN example.com.

hostA    IN A      10.0.0.1
aliasA   IN CNAME  hostA
aliasB   IN CNAME  hostB

and the reverse DNS zone entry

$ORIGIN in-addr.arpa.
1.0.0.10 IN PTR    hostA.example.com.

one might access the same host using either hostA.example.com or one of aliasA.example.com and aliasB.example.com. When one accesses the host using aliasA.example.com the DNS system resolves that name to 10.0.0.1. The reverse DNS lookup yields the PTR record to hostA.example.com. This is what’s used to build the host principal name host/hostA.example.com@EXAMPLE.COM.

SSHD configuration

Now one can configure sshd to allow authentication using Kerberos. This is done inside /etc/ssh/sshd_config. To allow login using Kerberos using the internal authentication mechanism of sshd (not using PAM) one can enable GSSAPI authentication:

GSSAPIAuthentication yes
GSSAPICleanupCredentials yes

If one really trusts one’s kerberos setup one might permit root login using Kerberos and/or disable usage of PAM and password authentication. The latter one should always be done when one allows root login using ssh:

UsePAM no
PasswordAuthentication no

and to allow root login:

PermitRootLogin yes

One might restrict login using ssh further using

AllowGroups GROUP1 GROUP2 GROUP3

For example to permit login for wheel users and mqadmin users one would set

AllowGroups wheel mqadmin

After that one has to add a list of users allowed to login into a given user account to the ${HOME}/.k5login file. To allow the users with the names sample@EXAMPLE.COM and sample2@EXAMPLE.COM to login for root one would write the following file into /root/.k5login:

sample@EXAMPLE.COM
sample2@EXAMPLE.COM

Any user listed inside the .k5login inside a users home directory might login using the UID of the user to whom the home directory belongs.

Adding an client

Basically a client wouldn’t need any configuration. One might enable GSSAPI authentication for ssh when connecting to a specific set of hosts or to hosts under a given domain. One shouldn’t enable that as a wildcard. To do so one might edit /etc/ssh/ssh_config and add an per host configuration:

Host host1.example.com
	GSSAPIAuthentication yes
	GSSAPIDelegateCredentials yes

One might also do this (when one really trusts all hosts to not steal forwardable tickets) under a given domain:

Host *.example.com
	GSSAPIAuthentication yes
	GSSAPIDelegateCredentials yes

This configuration also automatically forwards one own’s tickets to the given host (this is what the GSSAPIDelegateCredentials option does) and tries authentication (using the GSSAPIAuthentication option).

This article is tagged:


Data protection policy

Dipl.-Ing. Thomas Spielauer, Wien (webcomplains389t48957@tspi.at)

This webpage is also available via TOR at http://rh6v563nt2dnxd5h2vhhqkudmyvjaevgiv77c62xflas52d5omtkxuid.onion/

Valid HTML 4.01 Strict Powered by FreeBSD IPv6 support