Kerberos On Ubuntu

Please note, this article is not quite finished yet, and probably never will be. I'll leave it here because there is some useful information, anyway.

The goal of this article is to provide an easy, step-by-step guide to setting up Kerberos on Ubuntu systems. Most of the instructions are very relevant to, e.g., Debian, but are also fairly applicable to the majority of *nix systems.

The NTP Server

Installation

First, go ahead an install the package ntp-server. This is pretty much required. Kerberos timestamps tickets, so if your computers aren't synch'ed up, your authorization may fail. In order for synchronization to occur, you will have to make sure that your server can be accessed by incoming connections on UDP port 123. You may need to open this up on your firewall (don't forget to port-forward, if necessary).

Configuration

Edit /etc/ntp.conf. Mine looks like this:

# /etc/ntp.conf, configuration for ntpd

# ntpd will use syslog() if logfile is not defined
#logfile /var/log/ntpd

driftfile /var/lib/ntp/ntp.drift
statsdir /var/log/ntpstats/

statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable

# Synch to these servers
server pool.ntp.org
server ntp.ubuntulinux.org
server time.nist.gov

# Use local system clock as fallback
server 127.127.1.0
fudge 127.127.1.0 stratum 13

# By default, exchange time with everybody, but don't allow configuration.
restrict default kod notrap nomodify nopeer noquery

# Local users may interrogate the ntp server more closely.
restrict 127.0.0.1 nomodify

# Broadcast time
broadcast 192.168.0.255

You can probably just use the same configuration, however, double-check the broadcast address (last line), and make sure the security restrictions are consistent with your local network environment. Then:

# /etc/init.d/ntp-server restart

Verification

You can just do this to monitor the synchronization:

# watch 'sh -c "ntpq -p -c as && echo && ntptrace"'

Prior to synchronization, the output will look something like this:

     remote           refid      st t when poll reach   delay   offset  jitter
===========================================================
 entry.verboten. 130.149.17.21    2 u   18   64    1  135.474    2.615   0.004
 fiordland.ubunt 193.79.237.14    2 u   17   64    1   99.671    2.091   0.004
 time.nist.gov   .ACTS.           1 u   16   64    1   79.459   -0.478   0.004
 LOCAL(0)        LOCAL(0)        13 l   16   64    1    0.000    0.000   0.004
 192.168.0.255   .BCST.          16 u    -   64    0    0.000    0.000 4000.00

ind assID status  conf reach auth condition  last_event cnt
===========================================================
  1 40124  9014   yes   yes  none    reject   reachable  1
  2 40125  9014   yes   yes  none    reject   reachable  1
  3 40126  9014   yes   yes  none    reject   reachable  1
  4 40127  9014   yes   yes  none    reject   reachable  1
  5 40128  8000   yes   yes  none    reject

localhost.localdomain: stratum 16, offset 0.000000, synch distance 0.000285

However, after your server is sync'ed, you'll see something like this:

     remote           refid      st t when poll reach   delay   offset  jitter
===========================================================
 entry.verboten. 130.149.17.21    2 u   27   64   17  135.287    2.550   0.234
 fiordland.ubunt 193.79.237.14    2 u   21   64   17   99.671    2.091   0.344
*time.nist.gov   .ACTS.           1 u   25   64   17   78.778    0.036   0.301
 LOCAL(0)        LOCAL(0)        13 l   20   64   17    0.000    0.000   0.004
 192.168.0.255   .BCST.          16 u    -   64    0    0.000    0.000 4000.00

ind assID status  conf reach auth condition  last_event cnt
===========================================================
  1 40124  9014   yes   yes  none    reject   reachable  1
  2 40125  9014   yes   yes  none    reject   reachable  1
  3 40126  9614   yes   yes  none  sys.peer   reachable  1
  4 40127  9014   yes   yes  none    reject   reachable  1
  5 40128  8000   yes   yes  none    reject

localhost.localdomain: stratum 2, offset 0.000036, synch distance 0.979354
time.nist.gov: stratum 1, offset 0.000000, synch distance 0.002650, refid 'ACTS'

NTP synchronization can sometimes take a fair amount of time (10+ minutes). The delay is largely dependent upon connection speed. If you have decent broadband service, it shouldn't take longer than ten minutes. The NTP server will fail to respond to queries properly until full synchronization has been achieved. If the output of ntpq -c as lists no hosts as reachable, you have forgotten to open your firewall up properly. Once things are ready to go, you should be able to do this on your workstation:

# ntpdate -dsv server.local.network

If you get an error that says the server was dropped due to a "strata to high" (or something like that), it's because your server hasn't sync'ed yet. Double check that it can reach the NTP hosts specified in the configuration file, and then just keep waiting for the synch to occur.

Kerberos Packages

Installation

Install krb5-admin-server, krb5-kdc, krb5-config, krb5-user, krb5-clients, and krb5-rsh-server. These will bring some dependencies with them.

Basic Kerberos Configuration

Edit /etc/krb5.conf. Here's mine:

[libdefaults]
default_realm = LOCAL.NETWORK

# Here, we specify the kdc and admin server for the realm
# LOCAL.NETWORK
[realms]
LOCAL.NETWORK = {
  kdc = server.local.network
  admin_server = server.local.network
}

# This informs the kdc of which hosts it should consider part of the
# LOCAL.NETWORK realm
[domain_realm]
local.network = LOCAL.NETWORK
.local.network = LOCAL.NETWORK

# I disable kerberos 4 compatibility altogether.  I understand it had
# some real security issues.  I don't know if this is important here,
# but, it doesn't hurt in my particular case (all clients on my network
# are kerberos 5 compatible).
[login]
krb4_convert = false
krb4_get_tickets = false

kdc Configuration

Edit /etc/krb5kdc/kdc.conf. (Most likely, the default will be suitable.) Mine is the same as the Ubuntu default:

[kdcdefaults]
    kdc_ports = 750,88

[realms]
    @MYREALM = {
        database_name = /var/lib/krb5kdc/principal
        admin_keytab = FILE:/etc/krb5kdc/kadm5.keytab
        acl_file = /etc/krb5kdc/kadm5.acl
        key_stash_file = /etc/krb5kdc/stash
        kdc_ports = 750,88
        max_life = 10h 0m 0s
        max_renewable_life = 7d 0h 0m 0s
        master_key_type = des3-hmac-sha1
        supported_enctypes = des3-hmac-sha1:normal des-cbc-crc:normal des:normal des:v4 des:norealm des:onlyrealm des:afs3  
        default_principal_flags = +preauth
    }
Restart your kdc and kerberos admin servers:
# for script in /etc/init.d/krb5*; do $script restart; done

I don't recall this being necessary at the time this article was first written, however, I've been informed that a kerberos database must be created before kadmin will start correctly. It is possible that it was done automatically for me by the install scripts. The current install scripts (Gutsy) do not do this. Perhaps I actually created it but forgot that I did so.

In any case, if kadmin complains about not having a database to work with, you can create one using the following command:

kdb5_util -s

Adding Principals, Creating Keys

All that's left to get a basic, functional Kerberos setup is to add principals and create keys for them. The first thing to do is create the kerberos database, and set the master key for the realm:

# kdb5_util create -s
[type password]

Don't forget this key! Next, create an administrative principal so you can do remote administration (if you are logged into the machine running the administrative server, you can just use kadmin.local, and you really don't need the admin principal, but create it anyway for posterity's sake):

# kadmin.local -q "addprinc admin/admin"
[type password]

Next, start an interactive kadmin session (using the admin principal), and add principals for your username, the host the kdc and kadmin servers are running on, and your workstation, like this:

# kadmin.local -p admin/admin
kadmin.local: addprinc -randkey host/server.local.network
kadmin.local: addprinc [username]
[type password]
kadmin.local: addprinc -randkey host/workstation.local.network
kadmin.local: ktadd host/server.local.network
kadmin.local: quit

Substitute your username for [username].

I suggest you use random keys for the hosts, but make sure you remember the key for your username. You will need this to authenticate to the kdc. Note that it is very important that you use fully-qualified host names. Kerberos does reverse DNS lookups to verify host names, and will not authenticate your workstation if a reverse DNS lookup yields a hostname different than the one you presented to it.

If you intend to login remotely using kerberos, you will need to explicitly allow access to your account on the server. This should do the trick:

# su [username]
> echo [username]@[REALM] > ~/.k5login
> exit

This simply permits access to your UNIX account on the server to anyone who authenticates to kerberos as your username.

Configuring Your Workstation

Assuming you are using an Ubuntu workstation, you can configure your system to access kerberos-authenticated services fairly easily. This does not cover web services, however; I've yet to tackle that part of things, myself. You can easily do kerberized remote logins, though.

To start with, install the packages krb5-clients, krb5-config, krb5-user, and libpam-krb5. Typically, what you'd like to accomplish is kerberos authentication during workstation login. In other words, you sign into your workstation, and are immediately able to access kerberized services without having to re-enter a password. This requires the kerberos PAM module.

You will need to edit /etc/krb5.conf. The contents should be the same as on the server. After doing this, verify that your configuration is working by typing this at a console:

kinit [username]

Do not move on to configuring PAM until you have this working, or you could be locked out of your own computer. Generally speaking, if you see failure here, you either haven't configured your kerberos server correctly (perhaps you mistyped a principal name), or you have a DNS-related problem. DNS lookups are used by kerberos to decide what kerberos realm a host belongs to, as well as to help verify the authenticity of the host. Ideally, gethostbyaddr(gethostbyname(host)) should return the fully qualified domain name of your machine. In practice, if your network does not have a functional DNS server, this simply means that the /etc/hosts file should contain a fully qualified domain name for your workstation, and that it should be listed before the short name.

Next, tackle the PAM configuration. I did this by adding a file, 'common-krb5', to the directory /etc/pam.d. This file contains one line only:

auth    sufficient      /lib/security/pam_krb5.so use_first_pass

At the very least, you will probably want to make sure kerberos authentication is utilized for logins on your workstation, both at a console, and to GDM (or whatever other X display manager you use, if any). To do this, edit /etc/pam.d/login and /etc/pam.d/gdm, and modify the lines:

# Standard Un*x authentication.
@include common-auth

...such that they read:

# Kerberos authentication.
@include common-krb5
# Standard Un*x authentication.
@include common-auth