In der Griechischen Mythologie wurde der Eingang zur Unterwelt von einem Wesen mit drei Hundeköpfen, auf denen sich mehrere Schlangen ringelten, bewacht. Er hatte zur Aufgabe, dafür zu sorgen, dass keine der eingetretenen Seelen jemals wieder herauskam. Der Name dieses Wächters, Kerberos, sollte das Knurren eines bissigen Hundes wiedergeben.
1983 wurde am Massachusetts Institute of Technology (MIT) das Projekt Athena initiiert. Dabei handelt es sich um ein Programm zur Implementierung einer »Client-Server-Landschaft« im akademischen Umfeld. Der darin genutzte Authentifizierungsmechanismus hieß ebenfalls Kerberos und fungiert als Vermittler zwischen Client und Server. Das Protokoll setzt auf symmetrischen Verschlüsselungsverfahren auf und teilt sich mit jedem Verfahrensbeteiligten einen geheimen Schlüssel. Die Kenntnis dieser Schlüssel dient zum Nachweis der Identität.
Das Kerberos-Protokoll der Versionen 1 bis 3 waren reine Entwicklerversionen und wurden nur intern am MIT genutzt. Version 4 war die erste veröffentlichte Version, die verschiedene Funktionalitäten vermissen ließ, neu überarbeitet wurde und 1993 als Version 5 (was auch der aktuellen Version entspricht) verabschiedet und standardisiert wurde, RFC 1510.
Mittlerweile existieren verschiedene Implementierungen des Protokolls, wobei die am MIT weiter entwickelte Kerberos-Version häufig in den USA eingesetzt wird und außerhalb der USA - einmal mehr wegen der Export-Beschränkung - die an der Universität von Stockholm entwickelte Implementierung Heimdal ihre Anwendung fand. Die folgenden Beispiele beziehen sich auf die Heimdal-Distribution unter NetBSD, wobei auch hier »Kerberos« als Bezeichnung für die Implementierung und das Protokoll genutzt wird.
Die Authentifizierung innerhalb eines Kerberos-Netzwerkes erfolgt nicht direkt zwischen Anwender und Netzwerk-Service, sondern über einen vertrauenswürdigen Dritten, dem Key Distribution Center (KDC). Auf diesem werden die zum Nachweis der Identität erforderlichen, geheimen Schlüssel der Applikationsserver sowie der Principals, also der Anwender, Hosts oder Dienste, abgelegt. Ein KDC ist somit nichts anderes, als eine Datenbank in der die geheimen Schlüssel, die dem Nachweis der jeweiligen Identität dienen, verwaltet werden. Dieser geheime Schlüssel wird beispielsweise bei einem Anwender aus seinem Passwort abgeleitet.
Die Bezeichnung eines Principals setzt sich aus name@REALM zusammen, wobei REALM in der Regel dem Namen der zu verwaltenden Domain in Grossbuchstaben entspricht (im Prinzip ist die Bezeichnung jedoch frei wählbar) und name der Name des Principals. Der Bezeichnung kann noch eine weitere Kennung zugefügt werden, beispielsweise für einen Administrator, dessen »Rolle« mit in die Bezeichnung aufzunehmen ist, name/admin@REALM.
Für jeden Applikationsserver innerhalb des Netzwerkes muss ein Host-Principal angelegt werden. Die Bezeichnung hierfür setzt sich aus host/hostname@REALM zusammen, wobei hostname dem FQDN (Fully-Qualified Domain Name) entspricht. Analog hierzu wird die Bezeichnung für einen Service gebildet, service/hostname@REALM.
Die Authentifizierung wird in Kerberos über sogenannte Tickets realisiert, die vom KDC verteilt werden. Ein »spezielles Ticket« ist das Ticket Granting Ticket (TGT) welches ein Principal zunächst beim KDC anfordern muss, bevor er den Dienst eines Applikationsserver nutzen kann. Das TGT wird vom Anwender transparent über ein entsprechendes Client-Programm oder über das Programm kinit vom KDC angefordert.
Das KDC sucht in seiner Datenbank nach diesem Principal und generiert bei erfolgreicher Überprüfung einen Sitzungsschlüssel, der mit dem geheimen Schlüssel des Principal, ebenso wie das angeforderte TGT, chiffriert wird. Das Resultat wird an den Principal zurück gesandt.
Das Client-Programm oder kinit versuchen das TGT mit dem geheimen Schlüssel des Anwenders zu entschlüsseln. Konnte das TGT erfolgreich entschlüsselt werden, steht somit gleichfalls der Sitzungsschlüssel zur Verfügung.
Bei diesem Ablauf wird der geheime Schlüssel des Anwenders zu keinem Zeitpunkt über das Netz übertragen.
Das TGT ist nur einen bestimmten Zeitraum gültig und wird im Ticket-Cache (oder Credential-Cache) des Anwenders gespeichert. Wenn der Anwender auf einen kerberisierten Dienst innerhalb des Netzwerkes zugreifen will, berechtigt ihn das gültige TGT vom Ticket Granting Service (TGS) - welcher in der Regel ebenfalls auf dem KDC »untergebracht« ist - das erforderliche Ticket für den Service anzufordern. Der TGS stellt das gewünschte Ticket aus, welches von dem Server zur Authentifizierung genutzt wird.
Bleibt die Frage offen wie die Authentifizierung letztlich erfolgt. Bei der Anforderung eines TGTs findet diese nicht statt, das Ticket kann praktisch von »Jedermann« angefordert werden. Allerdings kann nur der Principal daraus Nutzen ziehen, der im Besitz des geheimen Schlüssels ist mit dem das TGT chiffriert wurde. Nur bei »erfolgreicher Dechiffrierung« ist es dem Principal möglich, in den Besitz des Sitzungsschlüssel zu gelangen der für die Anforderung der Tickets beim TGS erforderlich ist.
Fordert ein Anwender ein Ticket für einen Service beim TGS an, wird ausser diesem Ticket ein weiterer Sitzungsschlüssel generiert, der mit dem geheimen Schlüssel des Servers chiffriert wird. Dieses Resultat leitet das Client-Programm an den Server weiter. Kann der Sitzungsschlüssel erfolgreich entschlüsselt werden, gilt der Principal als authentifiziert.
Im weiteren Verlauf werden anhand eines einfachen Beispiels, die erforderlichen Schritte aufgezeigt um Kerberos nutzen zu können. Dabei wird von folgendem »Netzwerk« ausgegangen:
Außerdem wurde sichergestellt dass zwischen den beiden Rechnern Zeitsynchronisation besteht und die DNS-Namen vor- und rückwärts aufgelöst werden können. Beide Punkte müssen im Vorfeld beachtet werden, da sonst eine Authentifizierung über Kerberos nicht möglich ist.
Die Datei /etc/krb5.conf ist die zentrale Konfiguratonsdatei für Kerberos. Diese Datei wird beispielsweise beim Starten des KDCs ausgelesen und steuert das Verhalten entsprechend. Die Datei ist in verschiedene Sektionen unterteilt und hat beispielsweise folgenden Aufbau:
[libdefaults]
default_realm = JUPITER.NET
[realms]
JUPITER.NET = {
kdc = ganymed.jupiter.net
admin_server = ganymed.jupiter.net
kpasswd_server = ganymed.jupiter.net
}
[domain_realm]
.jupiter.net = JUPITER.NET
Hier werden zunächst der Name der lokalen Realm (libdefaults) sowie auf welchem Server sich das KDC befindet (realms) angegeben. Auf admin_server befindet sich die Datenbank des KDC, die geheimen Schlüssel werden auf dem Host kpasswd_server verwaltet. Diese Angaben sind optional, wenn sie nicht gesetzt sind, wird davon ausgegangen, dass sie sich auf dem gleichen Server wie das KDC befinden.
In der Sektion domain_realm können Domainnamen und Realms miteinander verknüpft werden. Angaben die mit einem Punkt beginnen, bedeuten, dass jeder Host dieser Domain zu der entsprechenden Realm gehört.
Diese Angaben setzen voraus, dass der FQDN (Fully Qualified Domain Name) des KDCs ganymed.jupiter.net ist. Abweichend können die Angaben, welcher Host Kerberos Dienste bereitstellt auch über die entsprechenden SRV Einträge im DNS (Domain Name Service) hinterlegt werden. Ein TXT Eintrag ermöglicht die Zuordnung der Hosts zu einem Realm.
Die Verwendung von DNS bietet sich in der Regel bei größeren Netzwerken an, da bestimmte Änderungen erfolgen können, ohne dass die Datei /etc/krb5.conf angepasst werden muss. Außerdem entfallen die Angaben zu realms und domain_realm, so dass die Konfigurationsdatei letztlich »übersichtlicher« wird.
In dem obigen - einfach gehaltenen - Beispiel wird jedoch auf diese Möglichkeit verzichtet.
Im nächsten Schritt wird die Datenbank auf dem KDC eingerichtet, die alle Schlüssel der Principals enthält. Die Datenbank wird mit einem Passwort geschützt, welches zuerst generiert wird (wobei sicher zu stellen ist, dass in das entsprechende Verzeichnis - hier /var/heimdal/ - geschrieben werden kann):
ganymed# kstash Master key: <passwort> Verifying password - Master key: <passwort> kstash: writing key to `/var/heimdal/m-key' ganymed#
Die Initialisierung - wie auch gegebenenfalls später vorzunehmende Modifizierungen - der Datenbank werden mit dem Programm kadmin vorgenommen. Die Option -l gibt an, dass die Datenbank lokal bearbeitet werden soll und mit init wird diese zunächst für die Realm eingerichtet.
ganymed# kadmin -l kadmin> init JUPITER.NET Realm max ticket life [unlimited]: <return> Realm max renewable ticket life [unlimited]: <return> kadmin>
Nachdem die Datenbank angelegt wurde, kann anschließend der erste Principal (hier der Host-Principal auf dem das KDC läuft) angelegt werden.
kadmin> add --random-key host/ganymed.jupiter.net Max ticket life [1 day]: <return> Max renewable life [1 week]: <return> Principal expiration time [never]: <return> Password expiration time [never]: <return> Attributes []: <return> kadmin>
Nachdem der Principal angelegt wurde, ist dessen Schlüssel in eine Datei (ohne zusätzliche Angaben nach /etc/krb5.keytab) zu extrahieren. Diese Datei ist eine »Liste« aller Principals und ihrer Schlüssel, welche für die gegenseitige Authentifizierung erforderlich sind.
kadmin> ext host/ganymed.jupiter.net
Das Administrationsprogramm kann nunmehr verlassen werden
kadmin> quit
Der Inhalt der Datei /etc/krb5.keytab kann mit dem Programm ktutil - über das auch verschiedene Angaben der Principals oder der Realm geändert werden können - angezeigt werden.
Auf den bisherigen Ablauf bezogen, ergibt sich die folgende Ausgabe:
ganymed# ktutil list FILE:/etc/krb5.keytab: Vno Type Principal 1 des-cbc-crc host/ganymed.jupiter.net@JUPITER.NET 1 des-cbc-md4 host/ganymed.jupiter.net@JUPITER.NET 1 des-cbc-md5 host/ganymed.jupiter.net@JUPITER.NET 1 des3-cbc-sha1 host/ganymed.jupiter.net@JUPITER.NET
Um die bisherige Installation zu testen, ist unter NetBSD wie folgt zu verfahren. Zunächst ist sicher zu stellen, dass sich der Eintrag
kdc=YES
in der Datei /etc/rc.conf befindet. Anschliessend kann das KDC gestartet werden.
ganymed# /etc/rc.d/kdc start Starting kdc. ganymed#
Außerdem sind die folgenden Änderungen in der Datei /etc/inetd.conf vorzunehmen:
kerberos-adm stream tcp nowait root /usr/libexec/kadmind kadmind kerberos-adm stream tcp6 nowait root /usr/libexec/kadmind kadmind kpasswd dgram udp wait root /usr/libexec/kpasswdd kpasswdd kpasswd dgram udp6 wait root /usr/libexec/kpasswdd kpasswdd
Nach diesen Anpassungen ist der Daemon neu zu starten:
ganymed# /etc/rc.d/inetd reload Reloading inetd config files. ganymed#
Auf anderen Distributionen ist entsprechend zu verfahren, wobei darauf zu achten ist, dass auch der »Administrations-Server« (kadmind und gegebenenfalls kpasswdd) gestartet werden und nicht nur das »eigentliche KDC«.
Über das Administrationsprogramm kadmin kann nunmehr der erste Anwender angelegt werden.
kadmin> add tl Max ticket life [1 day]: <return> Max renewable life [1 week]: <return> Principal expiration time [never]: <return> Password expiration time [never]: <return> Attributes []: <return> tl@JUPITER.NET's Password: <passwort> Verifying password - tl@JUPITER.NET's Password: <passwort> kadmin>
Anschließend kann der Anwender tl ein Ticket mit kinit beantragen. Der Inhalt des »Ticket-Cache« (Credential-Cache), in dem alle erhaltenen Tickets gespeichert werden, lässt sich mit dem Programm klist angezeigen. Konnte das Ticket erfolgreich erzeugt werden, ergibt sich die folgende Ausgabe:
$ kinit
tl@JUPITER.NET's Password: <passwort>
$ klist
Credentials cache: FILE:/tmp/krb5cc_1008
Principal: tl@JUPITER.NET
Issued Expires Principal
Nov 1 18:24:29 Nov 2 04:24:29 krbtgt/JUPITER.NET@JUPITER.NET
Nov 1 18:24:29 Nov 2 04:24:29 krbtgt/JUPITER.NET@JUPITER.NET
v4-ticket file: /tmp/tkt1008
Principal: tl@JUPITER.NET
Issued Expires Principal
Nov 1 18:24:29 Nov 2 04:24:29 krbtgt.JUPITER.NET@JUPITER.NET
$
Wie aus der Ausgabe ersichtlich wurde ein Ticket für tl mit einer Gültigkeitsdauer von zehn Stunden (die über die Datei /etc/krb5.conf angepasst werden kann) angelegt. Falls bislang keinerlei Fehlermeldungen angezeigt wurden, sollte noch ein weiterer Test durchgeführt werden, indem sich tl per Telnet auf dem KDC anmeldet.
$ telnet ganymed.jupiter.net
Trying 192.168.1.8...
Connected to ganymed.jupiter.net
Escape character is '^]'.
[ Trying KERBEROS5 ... ]
[ Kerberos V5 accepts you as ``tl@JUPITER.NET'' ]
Last login: Sat Nov 1 17:28:35 2003 from ganymed
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
The Regents of the University of California. All rights reserved.
NetBSD 1.6 (GENERIC) #0: Sun Sep 8 19:43:40 UTC 2002
Welcome to NetBSD!
....
Bei erfolgreicher Authentifizierung über Kerberos werden weder Login noch Passwort des Anwenders abgefragt. Ist kein TGT vorhanden, wird der herkömmliche Authentifizierungsmechanismus benutzt.
Bevor die Kerberos-Dienste und Clients eingerichtet werden, sollte zunächst ein weiterer Principal auf dem KDC angelegt werden, der mit Administrationsrechten auszustatten ist. Die Vorgehensweise ist analog zu dem vorigen Beispiel,
ganymed# kadmin -l kadmin> add root/admin Max ticket life [1 day]: <return> Max renewable life [1 week]: <return> Principal expiration time [never]: <return> Password expiration time [never]: <return> Attributes []: <return> root/admin@JUPITER.NET's Password: <passwort> Verifying password - root/admin@JUPITER.NET's Password: <passwort>
Zusätzlich sind dem Administrator (hier root) noch die entsprechenden Rechte einzuräumen, was über die Datei /var/heimdal/kadmind.acl erfolgt. Falls dem Administrator alle Rechte an der Datenbank gestattet werden sollen, ist folgender Eintrag vorzunehmen:
root/admin@JUPITER.NET all
Mit diesen Schritten verfügt root über die notwendigen Rechte die Datenbank zu administrieren und weitere Principals anzulegen oder bereits eingetragene zu bearbeiten.
Nachdem ein Administrator angelegt wurde und die Authentifizierung über Kerberos auf dem lokalen Server überprüft wurde, ist in einem nächsten Schritt - um beispielsweise eine Telnet-Verbindung zu einem zweiten Host aufzunehmen - der entsprechende Host-Principal anzulegen:
ganymed# kadmin -l kadmin> add --random-key host/callisto.jupiter.net Max ticket life [1 day]: <return> Max renewable life [1 week]: <return> Principal expiration time [never]: <return> Password expiration time [never]: <return> Attributes []: <return>
Auf jedem Server, der einen kerberisierten Dienst anbietet, muss ebenfalls die Datei /etc/krb5.conf angelegt werden (wobei zweckmäßigerweise die »Variante« vom KDC genutzt werden sollte).
Anschliessend ist, analog zu der Vorgehensweise auf dem KDC, auch hier die Datei /etc/krb5.keytab zu generieren. In dieser Datei wird der Schlüssel des Servers abgelegt, mit dem sich dieser gegenüber dem KDC authentifizieren kann. Im Gegensatz zu einem »normalen Anwender« muss für jeden Server die Datei keytab angelegt und anschliessend sicher übertragen werden. Im »einfachsten Fall« wird die Datei mit kadmin übertragen:
callisto# kadmin kadmin> ext host/callisto.jupiter.net root/admin@JUPITER.NET's Password: <passwort> kadmin> quit
Wenn auf dem KDC, beispielsweise aus Sicherheitsgründen, kein kadmind läuft (und dementsprechend nicht von anderen Rechnern genutzt werden kann), ist der Schlüssel für den Host-Prinicipal callisto.jupiter.net auf dem KDC zu erzeugen, wobei der Schlüssel in eine temporäre Datei zu extrahieren ist.
ganymed# kadmin -l kadmin> ext -k /tmp/callisto.keytab host/callisto.jupiter.net kadmin> quit
Anschliessend kann die Datei callisto.keytab sicher auf den Server übertragen werden. Beim Extrahieren des Schlüssels ist darauf zu achten, dass eine andere Datei angegeben wird, da andernfalls die keytab des KDC überschrieben wird.
Ob die Authentifizierung über Kerberos erfolgt lässt sich wie im vorigen Beispiel überprüfen:
ganymed$ telnet callisto.jupiter.net
Trying 192.168.1.7...
Connected to callisto.jupiter.net
Escape character is '^]'.
[ Trying KERBEROS5 ... ]
[ Kerberos V5 accepts you as ``tl@JUPITER.NET'' ]
Last login: Sat Nov 1 18:58:08 2003 from 192.168.1.7
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
The Regents of the University of California. All rights reserved.
NetBSD 1.6.1 (GENERIC) #0: Tue Apr 8 12:05:52 UTC 2003
Welcome to NetBSD!
....
Mit diesen Schritten ist ein funktionsfähige Kerberos-Realm eingerichtet, die analog zu der gezeigten Vorgehensweise um weitere Principals ergänzt werden kann.
Das Einrichten eines Kerberos-Client ist wesentlich einfacher als die bisherige Vorgehensweise. Allerdings sind auch hier zunächst einige Voraussetzungen zu schaffen, dazu gehören insbesondere:
Liegen die Voraussetzungen vor, kann der Client sich mit kinit Tickets vom KDC anfordern, sich diese mit klist anzeigen lassen und mit kdestroy aus dem Ticket-Cache löschen.
Als weitere Anwendung ist in der Regel noch das Programm kpasswd installiert, mit dem Passwörter geändert werden können.
Kerberos ist in erster Linie zur Anwender-Host-Authentifizierung entworfen worden. So zuverlässig das System auch sein mag, es hat auch seine negativen Seiten.
Als problematisch wird unter anderem die Tatsache gesehen, dass sämtliche geheimen Schlüssel auf einem Server gespeichert sind. Das KDC muss entsprechend physikalisch gesichert werden und es sollten keine weiteren Dienste auf dem Server laufen. Aber nicht nur die in der Datenbank gespeicherten geheimen Schlüssel stellen ein Risiko dar. Falls das KDC »einmal ausfallen sollte« (beispielsweise durch einen Denial-of-Service Angriff), kann innerhalb des Netzwerkes kein Service genutzt werden (wobei sich dieses Risiko durch den Betrieb mehrerer KDCs minimieren lässt).
Kerberos ist eine »Alles-oder-Nichts-Lösung«. Wenn die Entscheidung gefallen ist, das Protokoll einzusetzen sollten entweder alle Anwendungen, die Passwörter im Klartext versenden, kerberisiert werden oder auf die betreffende Anwendung sollte gänzlich verzichtet werden. Es macht wenig Sinn beispielsweise für telnet Kerberos zu nutzen und bei rsh darauf zu verzichten.
Insbesondere in Mehrbenutzer-Umgebungen ist im Zusammenhang mit den Tickets Vorsicht geboten, da diese unter /tmp gespeichert werden, was von »Jedermann« eingesehen werden kann. Mit der Option -c ist es möglich ein von der Standardeinstellung abweichendes Verzeichnis anzugeben (alternativ kann dies auch über die Umgebungsvariable gesetzt werden).