Kerberos mit Linux und AD

Auch Linux-Systeme können relativ problemlos in ein Active Directory eingebunden werden. Auf dieser Seite sammle ich meine Erfahrungen mit den unterschiedlichen Varianten. Ich bin sicher nicht der Linux-Fachmann aber vielleicht helfen meine Erläuterungen dem ein oder anderen Windows Admin bei der Integration von Clients und Produkten mittels Kerberos.

Anmelden und User

Windows und Linux sind gar nicht so arg unterschiedlich. Beide sind Multitasking-Systeme und erfordern eine Anmeldung und dazu braucht es eine Benutzerdatenbank. Beide haben eine lokale Benutzerdatenbank, die man aber mit Ausnahme für rein lokale Dienstkonten und Administratoren nicht wirklich nutzt, sondern in einem Netzwerk werden Clients in einen Verbund integriert. Bei Windows ist das heute das Active Directory, welches eine zentrale Datenbank für Benutzer und Gruppen, Anmeldedienste, Namensauflösung und Einstellmöglichkeiten mittels Gruppenrichtlinien bereitstellt. Mit den Gruppenrichtlinien kann Linux nun nicht viel anfangen aber DNS, DHCP, LDAP und insbesondere Kerberos sind natürlich Dienste, die auch ein Linux verwenden kann und sollte. Natürlich gibt es auch auf Linux vergleichbare Dienste, z.B. Samba.

Wenn wir von Kerberos sprechen dann geht es aber nur um die Anmeldung, d.h. ein Benutzer kann sich vom Active Directory ein Kerberos-Ticket für Service auf einem Linux-System holen und sich dort authentifizieren. Sie können in der lokalen Benutzerdatenbank natürlich entsprechende Konten anlegen und statt der lokalen Kennwort auf Kerberos setzen. Wenn Sie aber auch Benutzer auf einem Linux-System über das Active Directory verwalten wollen, dann recht Kerberos nicht aus. Sie benötige einen Verzeichnisdient wie OpenLDAP, FreeIPA, ApacheDS, NIS oder eben das Active Directory LDAP.

Wichtig: Sie müssen den Linux Client nicht zwingend in die Domain aufnehmen, damit ein darauf installierter Service wie z.B. Squid eine Anmeldung per Kerberos erlaubt. Wenn Sie den Client aufnehmen, dann sind weitere Konfigurationen erforderlich, z.B. zu DynDNS oder dass nicht alle Benutzer auch auf dem Linux anmelden dürfen und welche Shell sie bekommen.

Wenn ihr Linux-Client aber zur Anmeldung die Benutzerdatenbank des Active Directory nutzen soll, dann müssen Sie den Client auch in die Domain aufnehmen. Damit bekommt der Client ein Computerkonto und speichert sich die Zugangsdaten lokal ab. Dies ist erforderlich, dass er auch ohne angemeldeten Benutzer auf das Active Directory zugreifen kann.

Kerberos Basiseinrichtung

Zuerst sorgen wir aber erst einmal für eine Konfiguration von Kerberos, um z.B. unsere Anwender an einem lokalen Service zuzulassen, der einfach nur ein Kerberos-Token mit dem Benutzernamen benötigt. Ein Beispiel ist meine Konfiguration von Squid-Proxy auf WSL mit Kerberos.

Aktion Status

Vorarbeit: DNS-Name

Der Client sollte den gleichen DNS-Domain Name wie das AD haben und so auch in der "/etc/hosts"eingetragen sein. Testen Sie dies mit dem Befehl "Hostname".

hostname

Vorarbeit: Zeitsynchronisation

Kerberos-Tickets sind zeitabhängig und alle Systeme im LAN sollten die gleiche Uhrzeit haben. Debian-Systeme nutzen normalerweise "0.debian.pool.ntp.org". Installieren Sie ggfls. den NTP-Dienst und konfigurieren Sie diesen auf ihre Domaincontroller.

apt-get install ntp 

nano /etc/ntp.conf

Die Datei sollte dann "server dc01.msxfaq.net" o.ä. beinhalten.

Kerberos konfigurieren

Für die Authentifizierung müssen wir Kerberos installieren und konfigurieren.

apt-get install krb5-user 

Mit einem Editor, z.B. "nano /etc/krb5.conf" legen Sie mindestens eine rudimentäre Konfiguration an, damit der Computer weiß, wie er mit dem AD umgehen muss.

Achtung: Groß/Kleinschrift ist bei Unix wichtig!

Hier ein Beispiel mit statischer Vorgabe eine DC. Sie können die Eintrage auch komplett leer lassen, wie ich weiter unten noch zeige. Dann wird DNS genutzt, was einer AD-Zone auch funktioniert.

[libdefaults]
    default_realm = MSXFAQ.NET
    dns_lookup_realm = false
    dns_lookup_kdc = false

[realms]
    MSXFAQ.NET = {
        admin_server = DC01.MSXFAQ.NET
        kdc = DC01.MSXFAQ.NET
    }

[domain_realm]
    .msxfaq.net = MSXFAQ.NET

Die Datei wird später auch von anderen Diensten genutzt, die Kerberos verwenden.

Anmelden mit KINIT testen

Nun sollte es uns schon möglich sein, ein Kerberos-Ticket auf dem Linux Client für einen AD-Benutzer anzufordern. Dazu nutzen wir KINIT.

kinit -v user@MSXFAQ.NET

kinit sollte eine Verbindung aufbauen, nach dem Kennwort fragen und danach ein "Authenticated to Kerberos v5" ausgeben:

Ticket anzeigen

Mit dem Befehl KLIST kann ich mir alle Tickets anzeigen lassen, die sich in meinem Cache befinden:

admin@linux1:/mnt/c/Users/admin$ klist /tmp/krb5cc_1000
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: user@MSXFAQ.NET

Valid starting     Expires            Service principal
03/01/24 00:04:29  03/01/24 10:04:29  krbtgt/MSXFAQ.NET@MSXFAQ.NET
        renew until 03/02/24 00:04:25

Ticket löschen

Es gibt zwar kein klassisches "Logout" aber ich kann mit kdestroy das Ticket löschen.

kdestroy

Damit ist die grundlegende Funktion von Kerberos mit dem AD belegt.

Fehlersuche

Sollte der einfache "kinit" schon nicht gehen, dann nutze ich einen ausführlicheren Aufruf, der sehr detaillierte Ausgaben generiert:

env KRB5_TRACE=/dev/stdout kinit -V FCADMIN@MSXFAQ.NET 2>&1

Dieser Aufruf erscheint komplex aber setzt eigentlich nur die Umgebungsvariable KRB5_TRACE auf stdout und startet dann "kinit". Es gibt mit "kinit" auch den Schalter "-V" für Verbose aber viel mehr Informationen habe ich damit nicht bekommen. Erst der Trace hat mit bei der Suche wirklich geholfen. Folgende Fehler habe ich schon gesehen und behoben:

Fehler Lösung
Error loading plugin module pkinit: 2/unable to find plugin
kinit: KDC reply did not match expectations while getting initial credentials

Interessanterweise reicht es nicht immer ein APT INSTAL KERB-USER zu machen. Installieren Sie das Paket krb5-pkinit nach

sudo apt install krb5-pkinit

kinit: KDC reply did not match expectations while getting initial credentials

Ein Möglicher Fehler ist in der Groß//Kleinschreibnug. Versuchen Sie die Domain des Usernamens in Großbuchstaben zu schreiben.

kinit: Invalid argument while getting initial credentials

Ich hatte in der krb5.conf folgenden falschen Eintrag.

[realms]
   MSXFAQ.NET = {
    kdc = tcp://192.168.178.201:88
}

Das Prefix "tcp://" hat gestört.

kinit: No supported encryption types (config file error?) while getting initial credentials

Die vom KDC angebotenen Encryption Types passen nicht. Denken Sie daran, dass aktuelle Windows Server kein DES mehr unterstützen und RC4 auch nicht mehr genutzt werden sollte. Aktuell Linux Versionen nutzen auch AES128 oder AES256 aber vielleicht haben Sie in der krb5.conf dies anders angegeben. Hier ein Beispiel, wie es nicht sein sollte.

[libdefaults]
   default_tgs_enctypes = des-cbc-crc des-cbc-md5
   default_tkt_enctypes = des-cbc-crc des-cbc-md5
   permitted_enctypes = des-cbc-crc des-cbc-md5

Ich lasse die Werte entweder weg und vertraue auf die Default, die das Active Directory vorgibt oder erzwinge hier AES wie folgt:

[libdefaults]
   default_tgs_enctypes = aes256-cts-hmac-sha1-96
   default_tkt_enctypes = aes256-cts-hmac-sha1-96
   permitted_enctypes = aes256-cts-hmac-sha1-96

kinit: Cannot contact any KDC for realm 'MSXFAQ.NET' while getting initial credentials

Kontrollieren Sie auch hier die Konfiguration der angegeben Server. Ich hatte einen Fehler in IP-Adressen und Ports. Eventuell ist der DC auch nicht erreichbar, weil eine Firewall die Verbindung blockiert. Her geht es um Port 88/UDP/TCP. Es kann auch an der Namensauflösung liegen. Mein Trace zeigte gut, dass ich eine "89" statt "88" angegeben hatte.

[1408] 1709248638.387203: Sending initial UDP request to dgram 192.168.178.201:89
[1408] 1709248639.393730: Initiating TCP connection to stream 192.168.178.201:89
[1408] 1709248642.397520: Sending retry UDP request to dgram 192.168.178.201:89
[1408] 1709248647.403005: Sending retry UDP request to dgram 192.168.178.201:89
[1408] 1709248656.412456: Terminating TCP connection to stream 192.168.178.201:89

kinit: Improper format of Kerberos configuration file while initializing Kerberos 5 library

Hier ist die krb5.conf nicht korrekt. Prüfen Sie, ob sie beim Ein/Auskommentieren vielleicht eine Klammer vergessen haben.

kinit: Configuration file does not specify default realm when parsing name username

In dem Fall hatte ich bei "kinit" keinen vollständigen UPN sondern nur den SAMAccountname angegeben. Damit weiß Kerberos nicht, welches Realm es nutzen soll. Sie können "kurze Namen" erlauben, wenn Sie einen "default_realm = MSXFAQ.NET" unter "[libdefaults]" in der krb5.conf setzen.

[libdefaults]
   default_realm = MSXFAQ.NET

kinit: Password incorrect while getting initial credentials

Bei mir war es wirklich immer ein vertipptes Kennwort. Denken Sie z.B. an unterschiedliche Tastaturlayouts speziell bei Sonderzeichen.

kinit: Cannot find KDC for realm "msxfaq.net" while getting initial credentials

Ich habe den UPN und die Domain bei "kinit" in Kleinbuchstaben eingegeben. Damit passt dies nicht auf die krb5.conf, wenn ich nicht die Aliase wie folgt gepflegt habe:

[domain_realm]
   .msxfaq.net = MSXFAQ.NET
   msxfaq.net = MSXFAQ.NET

Allerdings habe ich auch Fälle gesehen, wo selbst mit diesen Einträgen der Fehler aufgetreten ist, während mit "Großbuchstaben" das Ticket erfolgreich erhalten wurde.

Ich werde die Liste sicher noch etwas erweitern aber die erweiterten Diagnoseausgaben von KINIT helfen schon bei der Analyse eigentlich aller Fehler.

kinit ohne krb5.conf

Genaugenommen müssen sie keine krb5.conf-Datei anlegen, denn ohne diese Datei nutzen die Kerberos Routinen einfach die von ihnen angegeben Reals und versuchen sich anhand der Standardwerte hinsichtlich Cipher-Suites und DNS-Auflösung zu verbinden. Ich habe das in meiner Umgebung einfach mal gemacht und mit KINIT und aktiviertem Debugging mich erfolgreich am DC angemeldet. Anhand des Logs sehen Sie, was mein Debian per Default versucht und auch geschafft hat:

root@LINUX1:/home/fcarius# env KRB5_TRACE=/dev/stdout kinit -V FCADMIN@MSXFAQ.NET 2>&1
Using default cache: /tmp/krb5cc_0
Using principal: FCADMIN@MSXFAQ.NET
[235378] 1709225747.061415: Getting initial credentials for FCADMIN@MSXFAQ.NET
[235378] 1709225747.061417: Sending unauthenticated request
[235378] 1709225747.061418: Sending request (191 bytes) to MSXFAQ.NET
[235378] 1709225747.061419: Sending DNS URI query for _kerberos.MSXFAQ.NET.
[235378] 1709225747.061420: No URI records found
[235378] 1709225747.061421: Sending DNS SRV query for _kerberos._udp.MSXFAQ.NET.
[235378] 1709225747.061422: SRV answer: 0 100 88 "dc01.MSXFAQ.NET."
[235378] 1709225747.061423: SRV answer: 0 100 88 "dc02.MSXFAQ.NET."
[235378] 1709225747.061425: Sending DNS SRV query for _kerberos._tcp.MSXFAQ.NET.
[235378] 1709225747.061427: SRV answer: 0 100 88 "dc01.MSXFAQ.NET."
[235378] 1709225747.061428: SRV answer: 0 100 88 "dc02.MSXFAQ.NET."
[235378] 1709225747.061429: Resolving hostname dc01.MSXFAQ.NET.
[235378] 1709225747.061430: Sending initial UDP request to dgram 192.168.178.202:88
[235378] 1709225747.061431: Received answer (191 bytes) from dgram 192.168.178.202:88
[235378] 1709225747.061432: Sending DNS URI query for _kerberos.MSXFAQ.NET.
[235378] 1709225747.061433: No URI records found
[235378] 1709225747.061434: Sending DNS SRV query for _kerberos-master._udp.MSXFAQ.NET.
[235378] 1709225747.061435: No SRV records found
[235378] 1709225747.061436: Response was not from primary KDC
[235378] 1709225747.061437: Received error from KDC: -1765328359/Additional pre-authentication required
[235378] 1709225747.061440: Preauthenticating using KDC method data
[235378] 1709225747.061441: Processing preauth types: PA-PK-AS-REQ (16), PA-PK-AS-REP_OLD (15), PA-ETYPE-INFO2 (19), PA-ENC-TIMESTAMP (2)
[235378] 1709225747.061442: Selected etype info: etype aes256-cts, salt "MSXFAQ.NETFCADMIN", params ""
[235378] 1709225747.061443: PKINIT client has no configured identity; giving up
[235378] 1709225747.061444: Preauth module pkinit (16) (real) returned: -1765328174/No pkinit_anchors supplied
Password for FCADMIN@MSXFAQ.NET: <hier habe ich dann das Kennwort eingegeben
[235378] 1709225750.601433: AS key obtained for encrypted timestamp: aes256-cts/DF81
[235378] 1709225750.601435: Encrypted timestamp (for 1709225751.261490): plain xxxxxx, encrypted xxxxxxx
[235378] 1709225750.601436: Preauth module encrypted_timestamp (2) (real) returned: 0/Success
[235378] 1709225750.601437: Produced preauth for next request: PA-ENC-TIMESTAMP (2)
[235378] 1709225750.601438: Sending request (271 bytes) to MSXFAQ.NET
[235378] 1709225750.601439: Sending DNS URI query for _kerberos.MSXFAQ.NET.
[235378] 1709225750.601440: No URI records found
[235378] 1709225750.601441: Sending DNS SRV query for _kerberos._udp.MSXFAQ.NET.
[235378] 1709225750.601442: SRV answer: 0 100 88 "dc02.MSXFAQ.NET."
[235378] 1709225750.601444: SRV answer: 0 100 88 "dc01.MSXFAQ.NET."
[235378] 1709225750.601445: Sending DNS SRV query for _kerberos._tcp.MSXFAQ.NET.
[235378] 1709225750.601446: SRV answer: 0 100 88 "dc01.MSXFAQ.NET."
[235378] 1709225750.601447: SRV answer: 0 100 88 "dc02.MSXFAQ.NET."
[235378] 1709225750.601449: Resolving hostname dc02.MSXFAQ.NET.
[235378] 1709225750.601450: Sending initial UDP request to dgram 192.168.178.201:88
[235378] 1709225750.601451: Received answer (96 bytes) from dgram 192.168.178.201:88
[235378] 1709225750.601452: Sending DNS URI query for _kerberos.MSXFAQ.NET.
[235378] 1709225750.601453: No URI records found
[235378] 1709225750.601454: Sending DNS SRV query for _kerberos-master._udp.MSXFAQ.NET.
[235378] 1709225750.601455: No SRV records found
[235378] 1709225750.601456: Response was not from primary KDC
[235378] 1709225750.601457: Received error from KDC: -1765328332/Response too big for UDP, retry with TCP
[235378] 1709225750.601458: Request or response is too big for UDP; retrying with TCP
[235378] 1709225750.601459: Sending request (271 bytes) to MSXFAQ.NET (tcp only)
[235378] 1709225750.601460: Sending DNS URI query for _kerberos.MSXFAQ.NET.
[235378] 1709225750.601461: No URI records found
[235378] 1709225750.601462: Sending DNS SRV query for _kerberos._tcp.MSXFAQ.NET.
[235378] 1709225750.601463: SRV answer: 0 100 88 "dc02.MSXFAQ.NET."
[235378] 1709225750.601465: SRV answer: 0 100 88 "dc01.MSXFAQ.NET."
[235378] 1709225750.601466: Resolving hostname dc02.MSXFAQ.NET.
[235378] 1709225750.601467: Initiating TCP connection to stream 192.168.178.201:88
[235378] 1709225750.601468: Sending TCP request to stream 192.168.178.201:88
[235378] 1709225750.601469: Received answer (1908 bytes) from stream 192.168.178.201:88
[235378] 1709225750.601470: Terminating TCP connection to stream 192.168.178.201:88
[235378] 1709225750.601471: Sending DNS URI query for _kerberos.MSXFAQ.NET.
[235378] 1709225750.601472: No URI records found
[235378] 1709225750.601473: Sending DNS SRV query for _kerberos-master._tcp.MSXFAQ.NET.
[235378] 1709225750.601474: No SRV records found
[235378] 1709225750.601475: Response was not from primary KDC
[235378] 1709225750.601476: Processing preauth types: PA-ETYPE-INFO2 (19)
[235378] 1709225750.601477: Selected etype info: etype aes256-cts, salt "MSXFAQ.NETFCADMIN", params ""
[235378] 1709225750.601478: Produced preauth for next request: (empty)
[235378] 1709225750.601479: AS key determined by preauth: aes256-cts/DF81
[235378] 1709225750.601480: Decrypted AS reply; session key is: aes256-cts/CAB4
[235378] 1709225750.601481: FAST negotiation: unavailable
[235378] 1709225750.601482: Resolving unique ccache of type MEMORY
[235378] 1709225750.601483: Initializing MEMORY:HCxMbQn with default princ FCADMIN@MSXFAQ.NET
[235378] 1709225750.601484: Storing config in MEMORY:HCxMbQn for krbtgt/MSXFAQ.NET@MSXFAQ.NET: pa_type: 2
[235378] 1709225750.601485: Storing FCADMIN@MSXFAQ.NET -> krb5_ccache_conf_data/pa_type/krbtgt\/MSXFAQ.NET\@MSXFAQ.NET@X-CACHECONF: in MEMORY:HCxMbQn
[235378] 1709225750.601486: Storing FCADMIN@MSXFAQ.NET -> krbtgt/MSXFAQ.NET@MSXFAQ.NET in MEMORY:HCxMbQn
[235378] 1709225750.601487: Moving ccache MEMORY:HCxMbQn to FILE:/tmp/krb5cc_0
[235378] 1709225750.601488: Destroying ccache MEMORY:HCxMbQn
Authenticated to Kerberos v5

Der Trace zeigt schön, dass Linux per DNS nach _kerberos.<REALM>, _kerberos._udp.<REALM> und _kerberos._tcp.<REALM> sucht und die beiden letzten Einträge im Active Directory auch aufgelöst werden können. Die erweiterten DNS-Einträge von Windows mit "_msdcs" werden nicht genutzt. Danach versuch er sich mit AES265 über UDP anzumelden, was für die PreAuthentication noch geht aber dann das Paket zu groß wird und ein Wechsel zu TCP erfolgt. Die erhaltenen Tickets werden in einer Cache-Datei gespeichert.

Dennoch rate ich immer dazu, eine krb5.conf so anzulegen, dass Sie ihre Active Directory Umgebung wiedergibt.

KEYTAB erstellen

Ein Ticket für einen Benutzer zu erhalten ist nur ein Teil. Interessanter wird es nun, wenn ein Dienst auf dem Server ein Kerberos-Ticket überprüfen muss. Dazu müssen Sie wieder die grundlegende Funktion von Kerberos im Netzwerk verstanden haben. (Siehe auch Kerberos Grundlagen)

  1. Ein UserA greift auf einen ServiceB zu
  2. Der Service lehnt mit "Authentication Required" ab und signalisiert, dass er Kerberos versteht
  3. Der Client geht zum Domain Controller, um sich ein Ticket für ServiceB mit dem gewünschten Kerberos SPN und seinen Namen UserA ausstellen zu lassen.
  4. Der KDC sucht im AD nach einem Konto (Computer oder Serviceaccount) mit dem SPN und erstellt ein Ticket, welche mit dem Schüssel des Kontos geschützt ist und sendet es an den Client
  5. Der Client greift mit dem Ticket auf dem Service zu
  6. Der Service muss nun das passende Kennwort haben, um das Ticket zu decodieren und die Signatur des KDC zu prüfen. Nur dann akzeptiert er es.

Wenn sie nun aufgepasst haben, dann muss es ein "Konto" im AD geben, welches ein Kennwort hat und diese Information muss auch dem Service zur Verfügung stehen.

Die "Keytab"-Datei enthält das Schlüsselmaterial zu einem AD-Konto und ist entsprechend zu schützen

Die Keytab-Datei ist aber nicht zwingend an den Linux-Client gebunden. Wenn Sie z.B. auf mehreren Servern den gleichen Dienste nutzen und ein Loadbalancer oder DNS Round Robin die Clients verteilt dann müssen Sie die KEYTAB auch auf mehreren Computern einsetzen. Das kennen Windows Administratoren aber auch schon von Exchange ASA-Konto (Siehe E2010CAS und Kerberos)

Die KEYTAB-Datei können Sie über zwei Wege anlegen:

  1. KTPASS auf Windows
    Als Administrator starten Sie auf dem Windows Server das Programm um ein Konto mit SPN und KEYTAB anzulegen, die Sie dann auf den Linux-Client übertragen
  2. MSKTUTIL auf Linux
    Sie haben Kerberos auf Linux schon eingerichtet und sich mit KINIT ein Ticket für einen Benutzer besorgt, der auch Computerkonten anlegen kann und nutzen dann das Linux-Tool, um ein Konto im AD anzulegen

Letztlich sind beide Wege legitim aber wenn ich eh schon auf dem Linux-Server bin, dann kann ich auch direkt von dort die Datei anlegen und abspeichern lassen.

Installation des Pakets mit vorherigem SU
apt install msktutil
#sudo apt-get install -y msktutil 

msktutil -c -b "CN=COMPUTERS"   \
   -s HTTP/squid.msxfaq.net     \
   -k /etc/squid/squid.keytab   \
   --computer-name squid        \
   --upn HTTP/squid.msxfaq.net  \
   --server dc01.msxfaq.net     \
   --enctypes 24                \
   --verbose

Mit dem Encryption Type 24 gebe ich vor, dass ich nur "aes128-cts-hmac-sha1-96" oder "aes256-cts-hmac-sha1-96" möchte aber kein RC4 oder gar DES

Bit            Hex       EncryptionType
0x00000001     01hex     DES_CBC_CRC
0x00000010     02hex     DES_CBC_MD5
0x00000100     04hex     RC4_HMAC_MD5
0x00001000     08hex     aes128-cts-hmac-sha1-96
0x00010000     10hex     aes256-cts-hmac-sha1-96

Im März 2024 konnte ich mit dem AD nicht mehr DES nutzen und Werte über 1fh wurden von kinit nicht angenommen

Danach haben Sie im Active Directory ein Computerkonto mit dem Namen "Squid", einem SPN und lokal eine "squid.keytab".

Für den Einsatz von msktutil ist aber eine korrekte Konfiguration der krb5.conf erforderlich, da hieraus z.B. der "Default_realm" gelesen wird.

Folgende Fehler habe ich bei meinen Test provozieren können:

Fehler Lösung

ERROR: Can't continue with wrong UPN

Prüfen Sie, dass der UPN bei Parameter "--upn" in "Großbuchstaben" geschrieben ist.

Error: krb5_get_default_realm failed

Die Lösung bestand darin, in der "krb5.conf" zumindest folgende Zeile zu addieren.

[libdefaults]
   default_realm = MSXFAQ.NET

Bei einem erfolgreichen Lauf mit "--verbose" sieht dies bei mir wie folgt aus.

--enctypes 24
 -- init_password: Wiping the computer password structure
 -- generate_new_password: Generating a new, random password for the computer account
 -- generate_new_password: Characters read from /dev/urandom: 87
 -- create_fake_krb5_conf: Created fake krb5.conf file: /tmp/.msktkrb5.conf-xHSQ90
 -- destroy_g_context: Destroying Kerberos context
 -- initialize_g_context: Creating Kerberos context
 -- finalize_exec: sAMAccountName: squid$
 -- get_short_hostname: Determined short hostname: squid
 -- get_short_hostname: Determined short hostname: squid
 -- try_machine_keytab_princ: Trying to authenticate squid$ from local keytab
 -- switch_default_ccache: Using the local credential cache: FILE:/tmp/.mskt_krb5_ccache-smL2HL
 -- finalize_exec: Authenticated using method 1
 -- LDAPConnection: Connecting to LDAP server: nawdc01.MSXFAQ.NET
SASL/GSS-SPNEGO authentication started
SASL username: squid$@MSXFAQ.NET
SASL SSF: 256
SASL data security layer installed.
 -- ldap_get_base_dn: Determined default LDAP base: dc=NETATWORK,dc=DE
 -- get_default_ou: Using OU: CN=COMPUTERS,dc=NETATWORK,dc=DE
 -- ldap_check_account: Checking that a computer account for squid$ exists
 -- ldap_check_account: Found computer account
 -- ldap_check_account: Found userAccountControl: 0x1000
 -- ldap_check_account: Found supportedEncryptionTypes: 28
 -- ldap_check_account: Found dNSHostName: squid.MSXFAQ.NET
 -- ldap_check_account: Found servicePrincipalName: host/squid
 -- ldap_check_account: Found servicePrincipalName: host/squid.MSXFAQ.NET
 -- ldap_check_account: Found servicePrincipalName: HTTP/squid.MSXFAQ.NET
 -- ldap_check_account: User principal specified on command line
 -- ldap_check_account_strings: Inspecting (and updating) computer account attributes
 -- ldap_check_account_strings: Found userPrincipalName: HTTP/squid.MSXFAQ.NET@MSXFAQ.NET
 -- ldap_check_account_strings: userPrincipalName should be HTTP/squid.MSXFAQ.NET@MSXFAQ.NET
 -- ldap_check_account_strings: Nothing to do
 -- ldap_set_supportedEncryptionTypes: No need to change msDs-supportedEncryptionTypes they are 28
 -- ldap_set_userAccountControl_flag: Setting userAccountControl bit at 0x200000 to 0x0
 -- ldap_set_userAccountControl_flag: userAccountControl not changed 0x1000
 -- ldap_get_kvno: Found KVNO: 1
 -- set_password: Attempting to reset computer's password
 -- set_password: Trying to use keytab for squid$ to change password
 -- set_password: Successfully set password
 -- remove_keytab_entries: Trying to remove entries for squid$ from keytab
 -- execute: Updating all entries for computer account squid$ in keytab WRFILE:/etc/squid/squid.keytab
 -- update_keytab: Updating all entries for squid$
 -- add_principal_keytab: Adding principal to keytab: squid$@MSXFAQ.NET
 -- add_principal_keytab: Using supportedEncryptionTypes: 28
 -- get_salt: Using salt: MSXFAQ.NEThostsquid.MSXFAQ.NET
 -- add_principal_keytab:   Adding entry of enctype 0x17
 -- add_principal_keytab:   Adding entry of enctype 0x11
 -- add_principal_keytab:   Adding entry of enctype 0x12
 -- add_principal_keytab: Adding principal to keytab: squid$@MSXFAQ.NET
 -- add_principal_keytab: Using supportedEncryptionTypes: 28
 -- get_salt: Using salt: MSXFAQ.NEThostsquid.MSXFAQ.NET
 -- add_principal_keytab:   Adding entry of enctype 0x17
 -- add_principal_keytab:   Adding entry of enctype 0x11
 -- add_principal_keytab:   Adding entry of enctype 0x12
 -- add_principal_keytab: Adding principal to keytab: HTTP/squid.MSXFAQ.NET@MSXFAQ.NET
 -- add_principal_keytab: Using supportedEncryptionTypes: 28
 -- get_salt: Using salt: MSXFAQ.NEThostsquid.MSXFAQ.NET
 -- add_principal_keytab:   Adding entry of enctype 0x17
 -- add_principal_keytab:   Adding entry of enctype 0x11
 -- add_principal_keytab:   Adding entry of enctype 0x12
 -- add_principal_keytab: Adding principal to keytab: host/squid@MSXFAQ.NET
 -- add_principal_keytab: Using supportedEncryptionTypes: 28
 -- get_salt: Using salt: MSXFAQ.NEThostsquid.MSXFAQ.NET
 -- add_principal_keytab:   Adding entry of enctype 0x17
 -- add_principal_keytab:   Adding entry of enctype 0x11
 -- add_principal_keytab:   Adding entry of enctype 0x12
 -- add_principal_keytab: Adding principal to keytab: host/squid.MSXFAQ.NET@MSXFAQ.NET
 -- add_principal_keytab: Using supportedEncryptionTypes: 28
 -- get_salt: Using salt: MSXFAQ.NEThostsquid.MSXFAQ.NET
 -- add_principal_keytab:   Adding entry of enctype 0x17
 -- add_principal_keytab:   Adding entry of enctype 0x11
 -- add_principal_keytab:   Adding entry of enctype 0x12
 -- update_keytab: Entries for SPN HTTP/squid.MSXFAQ.NET have already been added. Skipping ...
 -- add_keytab_entries: Trying to add missing entries for squid$ to keytab
 -- add_keytab_entries: Checking if host/squid needs to be added to keytab
 -- add_keytab_entries: Checking if host/squid.MSXFAQ.NET needs to be added to keytab
 -- add_keytab_entries: Checking if HTTP/squid.MSXFAQ.NET needs to be added to keytab

Sie können Kinit auch häufiger aufrufen um weitere SPNs und Encryption Types in die gleiche Keytab-Datei zu addieren.

Achtung: Allerdings wird dabei auch das Computerkennwort zurückgesetzt, so dass die alten Schlüssel nicht mehr gültig sind.

Der Inhalt der KEYTAB-Datei können sie sich mit KLIST ebenfalls anzeigen.

root@squid:/home/fcarius# klist -ket /etc/squid/squid.keytab
Keytab name: FILE:/etc/squid/squid.keytab
KVNO Timestamp         Principal
---- ----------------- --------------------------------------------------------
   1 03/01/24 09:35:14 squid$@MSXFAQ.NET (aes128-cts-hmac-sha1-96)
   1 03/01/24 09:35:14 squid$@MSXFAQ.NET (aes256-cts-hmac-sha1-96)
   1 03/01/24 09:35:14 squid$@MSXFAQ.NET (aes128-cts-hmac-sha1-96)
   1 03/01/24 09:35:14 squid$@MSXFAQ.NET (aes256-cts-hmac-sha1-96)
   1 03/01/24 09:35:14 HTTP/squid.MSXFAQ.NET@MSXFAQ.NET (aes128-cts-hmac-sha1-96)
   1 03/01/24 09:35:14 HTTP/squid.MSXFAQ.NET@MSXFAQ.NET (aes256-cts-hmac-sha1-96)
   1 03/01/24 09:35:14 host/squid@MSXFAQ.NET (aes128-cts-hmac-sha1-96)
   1 03/01/24 09:35:14 host/squid@MSXFAQ.NET (aes256-cts-hmac-sha1-96)
   1 03/01/24 09:35:14 host/squid.MSXFAQ.NET@MSXFAQ.NET (aes128-cts-hmac-sha1-96)
   1 03/01/24 09:35:14 host/squid.MSXFAQ.NET@MSXFAQ.NET (aes256-cts-hmac-sha1-96)

Sie sehen, dass in der einen KEYTAB-Datei die verschiedenen Schlüsselverfahren hinterlegt sind.

KEYTAB schützen

Die KEYTAB-Datei enthält z.B. den passenden Schlüssel zum Computerkonto im Active Directory und muss daher geschützt werden. Das MIT schreibt dazu:

... A keytab is a host's copy of its own keylist, which is analogous to a user's password. ...
... You should always store keytab files on local disk, and make them readable only by root...
... you should never send a keytab file over a network in the clear. ....
...  Ideally, you should run the kadmin command to extract a keytab on the host on which the keytab is to reside.
https://web.mit.edu/kerberos/krb5-1.5/krb5-1.5.4/doc/krb5-admin/Keytabs.html

Wenn Sie für ihren Linux Client ein richtiges "Computerkonto" angelegt haben oder diesen sogar in die Domain aufgenommen haben, dann landet eine KEYTAB-Datei an der Standardlocation /etc/krb5.keytab". Dort kann im Grund jeder Lesen und daher sollten sie die Rechte auf diese Datei beschränken.. An vielen Stellen finde ich den Hinweis, wie Sie das Recht auf "Root beschränken, wenn es nicht schon per Default so gesetzt ist. Bei mir war es so

root@SQUID:/home/fcadmin# ls -lias /etc/krb5.keytab
786085 4 -rw------- 1 root root 804 Mar  1 12:13 /etc/krb5.keytab

da aber nur "Root" die Rechte hat, konnte ich diese Datei so in Squid nicht einbinden. Das Squid-Log lieferte dazu in Endlosschleife:

2024/03/01 13:21:19 kid1| helperOpenServers: Starting 1/10 'negotiate_kerberos_auth' processes
    current master transaction: master54
ERROR: keytab file /etc/krb5.keytab is not accessible
2024/03/01 13:21:19 kid1| WARNING: negotiateauthenticator #Hlpr2111 exited
    current master transaction: master54
2024/03/01 13:21:19 kid1| Too few negotiateauthenticator processes are running (need 1/10)
    current master transaction: master54
2024/03/01 13:21:19 kid1| Starting new helpers
    current master transaction: master54
2024/03/01 13:21:19 kid1| helperOpenServers: Starting 1/10 'negotiate_kerberos_auth' processes
    current master transaction: master54
ERROR: keytab file /etc/krb5.keytab is not accessible
2024/03/01 13:21:19 kid1| WARNING: negotiateauthenticator #Hlpr2112 exited
    current master transaction: master54
2024/03/01 13:21:19 kid1| Too few negotiateauthenticator processes are running (need 1/10)
    current master transaction: master54

Nun wollte ich nicht die Rechte der Default Keytab verändern, da diese vielleicht noch andere Dienste nutzen. Vielleicht sollte ich eine Gruppe anlegen, die berechtigt ist und alle Dienste in die Gruppe aufnehmen. Ich habe mich erst einmal für einen einfacheren Weg entschieden und die KEYTAB einfach in das Squid Konfigurationsverzeichnis kopiert und berechtigt.

cp /etc/krb5.keytab /etc/squid/squid.keytab
chown Proxy: /etc/squid/squid.keytab
chmod 0640 /etc/squid/squid.keytab

Danach habe ich die neue KEYTAB-Datei in der Squid-Konfiguration eintragen und den Squid mit "systemctl restart squid" neu gestartet.

Unschön ist dabei natürlich, dass bei einer Änderung der primären Keytab-Datei auch die Kopien aktualisiert würden müssen.

Daher würde ich jedem Dienst einfach einen eigenen virtuellen Namen im DNS mit dazugehörigem SPN, eigenem Computer-Konto und KEYTAB-Datei geben. Damit ist eine klare Trennung und Berechtigung gesichert.

 

Achtung: "Schützen" sie ihre KEYTAB-Datei gegen Diebstahl, Fremdzugriff o.ä. über Berechtigungen, z.B.: über Dateisystemrechte
Aber achten Sie darauf, dass alle Dienste diese dennoch nutzen können oder geben Sie jedem Dienst seine eigene Keytab oder eine eigene Kopie mit eigenen ACLs

Dienste mit Kerberos

Wenn die Konfiguration bislang fehlerfrei erfolgte dann haben Sie im Active Directory nun ein Computerkonto mit einem passenden SPN und einem Kennwort während auf dem Linux-System eine dazu passende KEYTAB-Datei für die weitere Verwendung vorliegt. Sie können diese Datei natürlich über die krb5.conf als "Default" hinterlegen, z.B. mit:

[libdefaults]
   default_keytab_name = /etc/krb5.keytab

Der Pfad /etc/krb5.conf ist auch ohne explizite Konfiguration die Standardeinstellung. Sie können aber auch für jeden Dienst mit einem eigenen SPN auch eine eigene KEYTAB mit einem passenden Computerkonto oder Servicekonto im Active Directory anlegen.

Die Existenz einer KEYTAB am Standardort oder durch krb5.conf vorgegeben bedeutet aber nicht, dass ein Service auf diesem Computer automatische Kerberos anbietet. In der Regel ist diese eine explizite Konfiguration.

Machen Sie immer eine Sicherheitskopie der Konfigurationsdatei und beachten Sie, dass teilweise noch Module installiert werden müssen und es unterschiede zwischen den verschiedenen Linux-Derivaten gibt.

Es gibt sicher noch viele weitere Dienste, die individuell für Kerberos aktiviert werden können. Auch gibt es, wie so oft, wohl Dienste wie Squid , die Kerberos mittels externen Programme bereitstellen, während andere Dienst auf GSSAPI und PAM (Pluggable Authentication Modules) aufsetzen.

Service Einstellungen

Anmelden über Netzwerk am Squid Proxy

In der Konfiguration des SQUID-Proxy muss die Keytab-Daten angegeben und die Anmeldung per Negotiate aktiviert werden.  

$ sudo nano /etc/squid/squid.conf

Hier muss ich drei Abschnitte addieren.

# Konfiguration von Kerberos mit de Helper und der Datei
auth_param negotiate program /usr/lib/squid/negotiate_kerberos_auth -k /etc/squid/squid.keytab -s HTTP/squid@msxfaq.net -s GSS_C_NO_NAME
auth_param negotiate children 10
auth_param negotiate keep_alive on

# Konfiguration einer ACL, damit ProxyAuth erforderlich ist. 
# Der Eintrag ist eventuell durch die BasicAuth schon da
acl authenticated proxy_auth REQUIRED

# Anlegen eienes Allow HTTP_Access-Eintrags vor einem DENY
http_access allow authenticated

Die erste Zeile definiert Negotiate und verweist auf den helper "negotiate_kerberos_auth", der Zugriff auf die Keytab-Datei braucht und welcher SPN genutzt wird.

Anmelden über Netzwerk am lokalen SSH-Server

Ich habe den SSH-Server auf meinem Linux noch nicht mit Kerberos aktiviert. Die Konfiguration erfolgt über die Datei "/etc/ssh/sshd_config" aber kann je nach Distribution abweichen. Zudem muss die SSH-Software mit dem Schalter "--with-kerberos5" kompiliert worden sein.

KerberosAuthentication yes
KerberosTicketCleanup yes
KerberosOrLocalPasswd yes

Allerdings habe ich auch Anleitungen gefunden, die auf GSSAPI aufsetzen.

GSSAPIAuthentication yes
GSSAPICleanupCredentials yes

Anmelden per SSH-Client mit Kerberos bei anderen Servern

Auch der SSHClient zum Verbinden von einem Linux-Client zu einem SSH-Server (SSHD) muss auf das Angebot zur Anmeldung per Kerberos eingehen. Editieren Sie die /etc/ssh/ssh_config und setzen Sie die folgenden Werte

GSSAPIAuthentication yes
GSSAPIDelegateCredentials yes
GSSAPITrustDns yes

Samba

Samba nutzt Kerberos anhand der krb5.conf

Domainmitglied

Nachdem ich nun quasi alle Belange von Kerberos beschrieben habe, die ich in meinem täglichen Betrieb bislang gesehen habe, bleibt noch die Frage einer richtigen "Domainmitgliedschaft". Es geht nicht nur die Authentifizierung an einem Linux-Service über ein Kerberos-Ticket, sondern dass die Benutzer und Gruppen aus dem Active Directory zu legitimen Anmeldekonten werden, ohne dass diese lokal in der "/etc/passwd" angelegt werden müssten. Als ich um 1995 noch mit Novell Netzwerk, Windows NT 3.51/4.0 und SUN/SPARC-Linux zu tun hatte, haben wir die UNIX-Systeme mittels NIS und NFS in die NetWare NDS integriert. Selbst Microsoft hat mit Windows 2012R2 mit den "Services for Unix" auf Windows entsprechende Dienste zur Integration und Kopplung bereitgestellt.

Auch wenn es heute noch Umgebungen mit NIS-Servern gibt, so dürften die meisten Systeme mittlerweile direkt mit dem Active Directory interagieren.

Ich erspare mir hier aber die Schritte erneut zu beschreiben, da Sie je nach Umgebung und Linux Distribution auch auch unterscheiden. Es gibt aber jede Menge Links zu dem Thema.

Weitere Links