802.1x mit FreeRADIUS und OpenLDAP

Die folgende Anleitung beschreibt den Aufbau eines Netzwerks mit 802.1x-Authentifizierung (z.B. für „WPA2 Enterprise“) mittels OpenLDAP und FreeRADIUS.

SSL-Zertifikate / CA

Grundlage für eine vertrauenswürdige Kommunikation ist eine anständige Publik-Key-Infrastruktur (PKI, siehe Wikipedia). Hierfür legen wir uns eine eigene Zertifizierungsstelle (CA – Certificate Authority) an, mit der wir später alle benötigten SSL/TLS-Zertifikate ausstellen.
Zuerst aber installieren wir die benötigten Werkzeuge:

apt-get install openssl ssl-cert

Anschließend erzeugen wir ein eigenes CA-Zertifikat. Der private Schlüssel für dieses Zertifikat sollte an einem sicheren Ort aufbewahrt werden und mit einem sicheren und möglichst langem Passwort versehen sein! (Tipp: das Programm „apg“ generiert zufällige Passwörter)

Das CA-Zertifikat ist in diesem Beispiel 10 Jahre lang gültig, damit man nicht alle paar Jahre seine gesamte IT-Infrastruktur neu konfigurieren muss 🙂

openssl req -x509 -new -extensions v3_ca -newkey rsa:4096 \
  -keyout ca.key -days 3652 -out ca.pem -sha512

Beispieldaten für eine CA:
Country Name: DE
State or Province Name: Bayern
Locality Name: Muenchen
Organization Name: Familie Mustermann
Organizational Unit Name: (leer)
Common Name: Familie Mustermann CA 2016
Email Address: (leer)

Mit diesem CA-Zertifikat erstellen wir nun ein erstes Zertifikat für den Server selbst, welches später u.a. für LDAP und RADIUS verwendet wird. So lange diese Dienste auf dem selben Server laufen empfehle ich, ein gemeinsames Zertifikat anzulegen, das vereinfacht dann den Austausch wenn es abläuft:

openssl req -new -newkey rsa:2048 -keyout server.key \
  -out server.csr -nodes -sha512

Bei den Zertifikatsdaten kann man die selben Informationen angeben wie beim CA-Zertifikat, oder auch beliebig andere. Wichtig ist aber, beim Common Name den Namen des Servers anzugeben:

Common Name (e.g. server FQDN or YOUR name) []: server.example.org

Außerdem benötigen wir noch eine kleine Textdatei mit den X509v3-Extensions, welche in das Zertifikat aufgenommen werden sollen. Ich nenne die mal ca-sign.cfg:

[ usr_cert ]
basicConstraints=CA:FALSE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer:always
extendedKeyUsage = 1.3.6.1.5.5.7.3.1
# identisch: extendedKeyUsage = serverAuth

Besonders wichtig ist die „extendedKeyUsage“-Einschränkung – ohne diese akzeptiert Windows das Serverzertifikat nicht (KB#814394)

Diesen Certificate Signing Request unterschreiben wir mit dem CA-Zertifikat. Die Gültigkeit wird auf 2 Jahre festgelegt (dann muss das Zertifikat ersetzt werden!):

openssl x509 -req -in server.csr -out server.pem \
  -CA ca.pem -CAkey ca.key -CAcreateserial -days 730 -sha512 \
  -extfile ca-sign.cfg -extensions usr_cert

Die Dateien werden anschließend in die richtigen Zielverzeichnisse kopiert sowie die Dateiberechtigungen angepasst:

cp ca.pem /etc/ssl/certs/ca.pem
cp server.pem /etc/ssl/certs/server.pem
cp server.key /etc/ssl/private/server.key
chown root:ssl-cert /etc/ssl/private/server.key
chmod 640 /etc/ssl/private/server.key

Das war’s vorerst was SSL-Zertifikate betrifft.

LDAP

Erst mal das OpenLDAP-Paket installieren:

apt-get install slapd ldap-utils

Falls die Konfiguration des LDAP-Server (slapd) übersprungen wurde oder was geändert werden muss, einfach den Befehl dpkg-reconfigure slapd ausführen.

Die relevanten Einstellungen für den LDAP-Server sind:
DNS domain name: server.example.org
Organization name: Familie Mustermann
Administrator password: (gut merken!)
Database backend: MDB
Allow LDAPv2 protocol? no

Mit dem Befehl slapcat kann man sich die Konfigurationsdaten anzeigen lassen.

Nun müssen wir das LDAP-Schema erweitert, um Benutzer (users) und Gruppen (groups) anlegen zu können. Dazu legen wir eine Datei namens „base.ldif“ mit folgendem Inhalt an:

dn: ou=people,dc=example,dc=org
objectClass: organizationalUnit
ou: people

dn: ou=groups,dc=example,dc=org
objectClass: organizationalUnit
ou: groups

Mit folgendem Befehl werden die neuen Einträge angelegt:

ldapadd -x -D cn=admin,dc=example,dc=org -W -f base.ldif

TLS für LDAP einrichten

Damit der OpenLDAP-Server Zugriff auf den privaten Schlüssel des Serverzertifikats erhält, müssen wir ihn in die Gruppe ssl-cert aufnehmen. Außerdem müssen wir den Dienst neu starten, damit die neue Gruppenmitgliedschaft wirksam wird (sonst gibt es später beim ocTLS.ldif einen Fehler):

usermod -a -G ssl-cert openldap
service slapd restart

Anschließend legen wir eine Datei namens olcTLS.ldif an:

dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ssl/certs/ca.pem
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ssl/certs/server.pem
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ssl/private/server.key

Diese wird importiert mit:

ldapmodify -Y EXTERNAL -H ldapi:/// -f olcTLS.ldif

Zuletzt wird in /etc/default/slapd in die Variable SLAPD_SERVICES noch „ldaps:///“ mit aufgenommen:

SLAPD_SERVICES="ldap:/// ldapi:/// ldaps:///"

Dann (noch mal) slapd neu starten:

service slapd restart

Fertig.

RADIUS

Wie immer installieren wir zuerst die benötigten Pakete:

apt-get install freeradius freeradius-ldap freeradius-utils

Während der Installation werden individuelle 1024-Bit Diffie-Hellman-Parameter erzeugt. Streng genommen gelten 1024 Bit nicht mehr als (langfristig) sicher – ich empfehle, 2048-Bit DH-Parameter zu erzeugen und diese entsprechend in der Datei /etc/freeradius/certs/dh zu ersetzen. Zur Erzeugung den Befehl „openssl gendh 2048“ ausführen – auf einem Raspberry kann das aber eine mittlere Ewigkeit dauern…

Zudem ersetzen wir die symbolischen Links auf die „Snakeoil“-Zertifikate durch unsere eigenen Dateien. So bleibt alles da wo es hingehört und wir müssen weniger an der Konfiguration ändern.

cd /etc/freeradius/certs
ln -sf /etc/ssl/certs/ca.pem ca.pem
ln -sf /etc/ssl/certs/server.pem server.pem
ln -sf /etc/ssl/private/server.key server.key

In der Datei /etc/freeradius/clients.conf legen wir dann jeweils einen Eintrag für den Switch sowie für den WLAN-Accesspoint an. Die IP-Adressen sind die jeweiligen Geräte-IPs aus dem Management-VLAN. Die Passwörter sind selbstverständlich zu ersetzen! 😉

# Switch:
client 192.168.10.3 {
        secret = PaSsWoRtNuRfUeRsWiTcH
        shortname = switch
}

# WLAN Access Point:
client 192.168.10.4 {
        secret = AcCeSsPoInTpAsSwOrT
        shortname = wlan
}

Anschließend wird die Authentifzierung konfiguriert. In der Datei /etc/freeradius/eap.conf muss der Eintrag default_eap_type (im Abschnitt eap {…} ) auf ttls gestellt werden:

default_eap_type = ttls

In /etc/freeradius/modules/ldap müssen wir den LDAP-Server definieren:

ldap {
    server = "server.example.org"
    port = 636
    basedn = "dc=example,dc=org"
    filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
    base_filter = "(objectclass=radiusprofile)"
    ldap_connections_number=5
    dictionary_mapping = ${confdir}/ldap.attrmap
}

Dann in /etc/freeradius/sites-enabled/default sowie in /etc/freeradius/sites-enabled/inner-tunnel LDAP aktivieren:

authorized {
    [...]
    ldap
    [...]
}
[...]
authenticate {
    [...]
    Auth-Type LDAP {
        ldap
    }
    [...]
}

Zum Schluss starten wir freeradius neu:

service freeradius restart

RADIUS-Schema in LDAP importieren

Das für RADIUS benötigte LDAP-Schema liegt in /usr/share/doc/freeradius/examples/openldap.schema. Lästig und unverständlich ist die Tatsache, dass dieses Schema nicht als „.ldif“-Datei vorliegt und man sich das relativ kompliziert selbst erzeugen muss. Ein schneller Workaround ist dabei das Script schema2ldif.sh. Damit ist die Konvertierung schnell erledigt:

wget "http://technik.blogs.nde.ag/files/2012/08/schema2ldif.sh"
sh schema2ldif.sh /usr/share/doc/freeradius/examples/openldap.schema

Mit ldapadd importieren wir das erzeugte openldap.ldif:

ldapadd -Y EXTERNAL -H ldapi:/// -f openldap.ldif

#

Test

Nun wird es Zeit, die Dienste mal zu testen. Zuerst legen wir eine Datei „test123.ldif“ an, welche die Daten für einen Test-Account enthält:

dn: uid=test123,ou=people,dc=example,dc=org
objectClass: top
objectClass: radiusprofile
objectClass: inetOrgPerson
cn: test123
sn: test123
uid: test123
description: Test User
radiusTunnelType: VLAN
radiusTunnelMediumType: 6
radiusTunnelPrivateGroupId: 10
# Passwort: PaSs123 (erzeugt mit "slappasswd")
userPasswort: {SSHA}Kznn1PyjcYJEkn96avu74r8qqBjm8Mou

Dieser wird mit ldapadd angelegt:

ldapadd -x -D cn=admin,dc=example,dc=org -W -f test123.ldif

Mit dem Befehl radtest testen wir dann eine Anmeldung:

radtest "test123" "PaSs123" localhost 18120 testing123

Wenn alles geklappt hat, sollte die Ausgabe etwa so aussehen:

Sending Access-Request of id 199 to 127.0.0.1 port 1812
        User-Name = "test123"
        User-Password = "PaSs123"
        NAS-IP-Address = 127.0.1.1
        NAS-Port = 18120
        Message-Authenticator = 0x00000000000000000000000000000000
rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=199, length=36
        Tunnel-Private-Group-Id:0 = "10"
        Tunnel-Medium-Type:0 = IEEE-802
        Tunnel-Type:0 = VLAN

Falls der Test nicht erfolgreich war, dann sollte man freeradius beenden (service freeradius stop) und im Debug-Modus starten (freeradius -XXX). Von einer zweiten SSH-Verbindung/Konsole aus dann den radtest-Befehl ausführen und prüfen, was freeradius so meldet.

EAP testen (optional)

Die Authentifizierung für 802.1x läuft via EAP (Extensible Authentication Protocol). Um das zu testen, installieren wir das Tool eapol_test (muss leider aus dem Source compiliert werden):

apt-get install libssl-dev libnl-dev
cd /tmp
wget "http://w1.fi/releases/wpa_supplicant-2.5.tar.gz"
tar xvf wpa_supplicant-2.5.tar.gz
cd wpa_supplicant-2.5/wpa_supplicant
cp defconfig .config
echo "CONFIG_EAPOL_TEST=y" >>.config
make eapol_test

eapol_test benötigt eine Konfigurationsdatei (wie auch wpa_supplicant unter Linux). Diese einfach als „eapol_test.conf“ anlegen:

network={
  eap=TTLS
  eapol_flags=0
  key_mgmt=IEEE8021X
  identity="test123"
  password="PaSs123"
  ca_cert="/etc/ssl/certs/ca.pem"
  phase2="auth=PAP"
}

Und dann der spannende Moment:

./eapol_test -c ./eapol_test.conf -a 127.0.0.1 -p 1812 -s testing123

Wenn alles passt, sollte (nach vielen, vielen Bildschirmseiten voller Debug-Meldungen) als letzte Zeile ein SUCCESS ausgegeben werden. 🙂

Absicherung / Aufräumen

## „testing123“-Account entfernen

# (Fotsetzung folgt)