php-Session-Cookies mit Authentifizierung über IServ-LDAP

Authentifizierung einer PHP-Webanwendung über den IServ-LDAP-Server

Jüngst standen wir bei uns am Georg-Büchner-Gymnasium in Seelze vor der Herausforderung, eine eigene PHP-basierte Webanwendung mit PHP-Session-Cookies über den IServ-LDAP authentifizieren zu wollen, um so zu erreichen, dass sich die Nutzerinnen und Nutzer dort mit ihren IServ-Zugangsdaten anmelden können.

Wie sich herausstellte, gab es dabei einige Fallstricke. In diesem Blog-Post werde ich darstellen, was man machen muss, um erfolgreich die Authentifizierung am IServ-LDAP in der PHP-Anwendung durchzuführen.

Als erstes muss man auf dem IServ-Server einen neuen Bind-Benutzer für LDAP anlegen. Dafür muss man in die Datei /etc/iserv/ldapusers folgende Zeile hinzufügen:

gbg-webserver:+userPassword:10.2.31.28

Dabei ist gbg-webserver der Name des Bind-Benutzers und die IP-Adresse ist die unseres Webservers mit der PHP-Anwendung.

Dann muss man mit folgendem Befehl die Konfigurationsänderung sichern:

iconf save /etc/iserv/ldapusers
iservchk

Als nächstes muss man das LDAP-Passwort mit

cat /var/lib/iserv/server-openldap/pwd/gbg-webserver.pwd

vom IServ holen. Jetzt kann man auf dem Testsystem prüfen, ob eine LDAP-Abfrage mit dem soeben eingerichteten Bind-Benutzer und dem Passwort geht. Dafür muss man auf dem Server 10.2.31.28 Folgendes ausführen:

ldapsearch -o ldif-wrap=no -H ldaps://gbg-seelze.eu:10636 -D "cn=gbg-webserver,ou=ldap,dc=gbg-seelze,dc=eu" -w PasswortAusVarLibIservEtc -b "cn=user.name,ou=users,dc=gbg-seelze,dc=eu"

Einer der Fallstricke war, dass IServ standardmäßig LDAP v3 nutzt, wohingegen PHP standardmäßig mit LDAP v2 arbeitet. Die Umsetzung der Abfrage sieht dann in PHP implementiert folgendermaßen aus:

$ds=ldap_connect("ldaps://gbg-seelze.eu:10636");  // must be a valid LDAP server!
if (ldap_set_option($ds,LDAP_OPT_PROTOCOL_VERSION,3))
 {
    echo "Using LDAP v3";
 }else{
    echo "Failed to set version to protocol 3";
      }
 if ($ds) {
    $passwd="PasswortAusVarLibIservEtc";
    $r=ldap_bind_ext($ds, "cn=gbg-webserver,ou=ldap,dc=gbg-seelze,dc=eu", $passwd);
                         //cn=... der User aus /etc/iserv/ldapusers
    if (ldap_parse_result($ds, $r, $errcode, $matcheddn, $errmsg, $referrals, $ctrls)) {
        if ($errcode != 0) {
            die("Error: $errmsg ($errcode)");
                           }
        }
    $sq="(memberOf=*)";
    echo "Searching for $sq";
    $act="erika.mustermann"; // bzw. der zu authentifizierende User
    $sr=ldap_search($ds, "cn=".$act.",ou=users,dc=gbg-seelze,dc=eu",$sq);
    if (ldap_parse_result($ds, $sr, $errcode, $matcheddn, $errmsg, $referrals, $ctrls)) {
        if ($errcode != 0) {
            die("Error: $errmsg ($errcode)");
                           }
        }
    $info = ldap_get_entries($ds, $sr); //hier sollte nur ein Entry rauskommen (keine Wildcards im User erlauben)
    for ($i=0; $i<$info["count"]; $i++) {
//----------------Passworttesten hier!---------------------------------------
      $hashpasswd=explode ("{crypt}",$info[$i]["userpassword"][0])[1];
      if (password_verify('testpasswort', $hashpasswd )) {  //bzw. das zu testende Passwort
       echo 'Password is valid!';
       } else {
        echo 'Invalid password.';
        }
//----------------Gruppenzugehörigkeit hier!------------------------------------
    $memberof=[];
    for ($j=0; $j<$info[$i]["memberof"]["count"]; $j++) {
    $memberof[]= explode(",",explode("cn=",$info[$i]["memberof"][$j])[1])[0];

//----------optimistische Auswertung, hier sollte man sich etwas vor Fehlern schützen----
      }
    }
    print_r($memberof); //$memberof enthält jetzt alle iserv-Gruppenzugehörigkeiten
    ldap_close($ds);

IServ-Linux-Client per LTSP an festplattenlose Rechner ausliefern: Arbeit mit Active Directory

In meinem Blogpost mit dem Titel „IServ-Linux-Client per LTSP an festplattenlose Rechner ausliefern“ habe ich beschrieben, wie man einen solchen Linux Terminal Server installiert. Die Anleitung basiert noch auf der Arbeit mit einer Windows-NT-Domäne. Nun wurde unser IServ-Server auf Active Directory umgestellt. Aus diesem Grund sind zwei Anpassungen nötig geworden, damit die LTSP-Clients beim Hochfahren automatisch zur Domäne hinzugefügt werden. Zum Verständnis dieses Blogposts sollte zunächst die ursprüngliche Anleitung gelesen werden.

Zum einen muss sichergestellt werden, dass in der Samba-Konfiguration in /etc/samba/smb.conf als realm der korrekte Domänenname eingetragen wird (bei uns: realm=ad.gbg-seelze.eu) und zum anderen muss dann das Skript zum Domänenbeitritt entsprechend für Active Directory angepasst werden.

An dieser Stelle sei nochmals erwähnt, dass die von mir beschriebene Lösung eher ein Workaround ist, der langfristig besser gelöst werden muss, da in dem Skript join-domain.sh das Domänenadministratorpasswort im Klartext enthalten ist. Zwar sind die Zugriffsrechte mit 700 gesetzt, sodass die Datei von einem unterprivilegierten Benutzer nicht gelesen oder ausgeführt werden kann, aber dennoch bietet das Skript eine gewisse Angriffsfläche. Alternativ kann man den Befehl zum Domänenbeitritt auch in der ltsp.conf in dem Abschnitt zur Client-Konfiguration hinterlegen. Damit hätte man das Domänenadministratorpassword immerhin nicht mehr im Client-Image. Das Grundproblem bleibt aber bestehen.

Nach dieser Vorrede hier nun der veränderte Befehl zum Domänenbeitritt:

echo -n 'password' | net ads join -U domainadmin ad.gbg-seelze.eu --no-dns-updates

Bei diesem Befehl ist domainadmin entsprechend durch den Benutzernamen des verwendeten Domänenadministrators, password durch das Passwort sowie ad.gbg-seelze.eu durch den Namen der AD-Domäne zu ersetzen. Damit kann man dann den LTSP-Client automatisch zur AD-Domäne hinzufügen.

Zentrales Management von Desktop-Clients mit einem Linux-Terminalserver

Ungeachtet der vielen mobilen Endgeräte und dem Wunsch, flexibel mit einem mobilen Gerät arbeiten zu können, haben bei uns in der Schule die Desktop-Clients noch längst nicht ausgedient. Um die Administration wesentlich zu vereinfachen, haben wir uns vor eineinhalb Jahren entschieden, auf festplattenlose Fat-Clients mit einem Linux-Terminalserver zu setzen.

In diesem Blog-Beitrag werde ich die Installation eines solchen Systems in Verbindung mit dem IServ-Schulserver beschreiben. Meine Anleitung bezieht sich auf LTSP5. Diesen Sommer wurde das LTSP-Projekt von Grund auf neu programmiert.

Wir nutzen aber weiterhin die alte Version, da jetzt alles geschmeidig läuft. Nichtsdestotrotz bietet die neue Version viele Verbesserungen. Deswegen werden wir nächstes Jahr umsteigen und ich werde alles hier dokumentieren.

Diese Anleitung bezieht sich auf Ubuntu Mate 18.04 LTS (Bionic) und einen Server mit zwei Netzwerkkarten (eno1 und eno2).

Der Ubuntu-LTSP-Server in Raum 501 stellt für die dort vorhanden Computer („Clients“) ein Festplattenabbild über das Netzwerk zur Verfügung, von dem die Clients starten. Auf diese Weise benötigen die Clients keine eigene Festplatte mehr und der Wartungsaufwand reduziert sich auf die Aktualisierung des Festplattenabbildes auf dem Server. Zudem können neue Clients direkt und ohne Installationsaufwand in das bestehende Netzwerk integriert werden.
Die Clients im Raum 501 befinden sich in einem eigenen Subnetz, was von der internen Netzwerkkarte des Servers bedient wird. Auf dem Server läuft ein DHCP-Server, der den Clients IP-Adressen sowie das Festplattenabbild zum Starten des Betriebssystems zur Verfügung stellt. Ferner arbeitet der Server als Router in das IServ-Netzwerk, sodass ein Zugriff auf dieses sowie auf das Internet möglich ist. Bei der Benutzeranmeldung an einem Client erfolgt eine Authentifizierung über ssh am Server und es wird das Heimatverzeichnis des Nutzers per sshfs eingebunden.

Netzwerktopologie unserer LTSP-Installation

Installation des Grundsystems

Als erstes muss das Grundbetriebssystem Ubuntu Mate 18.04 LTS installiert werden. Von diesem System wird später das Festplattenabbild erstellt, mit dem die Clients starten werden. Dieses bedeutet, dass das Betriebssystem von Server und Clients dasselbe ist. Alle Programme, die auf den Clients verfügbar sein sollen, müssen somit immer zuerst auf dem Server installiert werden. Die Installation des Grundbetriebssystems kann beispielsweise von einem USB-Stick erfolgen. Da es sich hierbei um eine Standardinstallation handelt, wird diese in diesem Handbuch nicht weiter dokumentiert.
Im nächsten Schritt müssen die Netzwerkkarten entsprechend unserer Anforderungen konfiguriert werden. Dieses geschieht bei Ubuntu durch das Bearbeiten der Konfigurationsdatei /etc/network/interfaces mit einem Texteditor mit root-Rechten.

sudo nano /etc/network/interfaces

Die Datei muss so angepasst werden, dass eine Netzwerkkarte (in unserem Fall eno1) die IP-Adresse dynamisch per DHCP von dem IServ-DHCP-Server bezieht. Die andere Netzwerkkarte benötigt eine statische IP-Adresse (in unserem Fall eno2). Auf dieser wird dann der interne DHCP-Server „lauschen“ und IP-Adressen sowie das Festplattenabbild an die mit dieser Netzwerkkarte verbundenen Clients verteilen. Diese Konfiguration wird bei unserem Server mit folgender Konfiguration von /etc/network/interfaces erreicht.

auto lo
iface lo inet loopback

auto eno1
iface eno1 inet dhcp

auto eno2
iface eno2 inet static
    address 192.168.0.1
    netmask 255.255.255.0
    broadcast 192.168.0.255

Nach diesen Änderungen sollte der Systemdienst, der für die Netzwerkkommunikation verantwortlich ist, neugestartet werden, damit die Änderungen sofort wirksam werden.

sudo systemctl restart networking.service

Nach der Konfiguration der beiden Netzwerkkarten muss der LTSP-Server installiert werden, der die Programme bereitstellt, die für die Erstellung und Auslieferung des Festplattenabbildes an die Clients verantwortlich sind. Mit folgenden Befehl werden die hierfür erforderlichen Programme installiert.

sudo apt-get install ltsp-server-standalone isc-dhcp-server tftpd-hpa ltsp-client ldm-ubuntu-theme

Im nächsten Schritt muss der interne DHCP-Server so konfiguriert werden, dass er das gewünschte Verhalten zeigt. Als erstes muss dem DHCP-Server mitgeteilt werden, auf welcher Netzwerkkarte er IP-Adressen verteilen soll. Dieses geschieht durch Bearbeiten der Konfigurationsdatei /etc/default/isc-dhcp-server. In dieser Datei muss folgende Bedingung eingetragen werden, damit der DHCP-Server auf der Netzwerkkarte eno2 arbeitet.

INTERFACESv4="eno2"

Für die weitere Konfiguration muss die Datei /etc/ltsp/dhcpd.conf bearbeitet werden.

#
# Default LTSP dhcpd.conf config file.
#

authoritative;

subnet 192.168.0.0 netmask 255.255.255.0 {
    range 192.168.0.100 192.168.0.250;
    option domain-name "501.ltsp";
    option domain-name-servers 10.0.0.1;
    option broadcast-address 192.168.0.255;
    option routers 192.168.0.1;
    next-server 192.168.0.1;
#    get-lease-hostnames true;
    option subnet-mask 255.255.255.0;
    option root-path "/opt/ltsp/amd64";
    if substring( option vendor-class-identifier, 0, 9 ) = "PXEClient" {
        filename "/ltsp/amd64/pxelinux.0";
    } else {
        filename "/ltsp/amd64/nbi.img";
    }
}

Nach diesen Änderungen muss der DHCP-Server neugestartet werden, damit die Änderungen sofort wirksam werden.

sudo systemctl restart isc-dhcp-server.service

Jetzt ist das Netzwerk eingerichtet und Clients, die mit der internen Netzwerkkarte des Servers verbunden sind, sollten eine IP-Adresse bekommen. Als nächster Schritt muss das Festplattenabbild erzeugt werden, von dem die Clients starten sollen. Hierfür muss als erstes ein LTSP-Kernel-Update durchgeführt werden.

sudo /usr/share/ltsp/update-kernels

Als nächstes muss das Festplattenabbild erzeugt werden. Je nach Prozessorleistung des Servers und Größe des Abbilds kann dieses mehrere Minuten dauern.

sudo ltsp-update-image --cleanup /

Um Probleme zu vermeiden, sollte an dieser Stelle der nbd-Server neugestartet werden, der die Aufgabe hat, das Festplattenabbild für die Clients zur Verfügung zu stellen.

sudo systemctl restart nbd-server.service

Jetzt bekommen mit der internen Netzwerkkarte des Servers verbundene Clients nicht nur eine IP-Adresse, sondern sie sollten auch mit dem soeben erzeugten Festplattenabbild starten. Allerdings wird man mit den Clients zu diesem Zeitpunkt noch nicht ins Internet kommen, weil der Server noch nicht so konfiguriert ist, dass er Datenpakete von den Clients in das IServ-Netz weiterleitet.

Einrichtung des Servers als Router

In der Konfigurationsdatei /etc/sysctl.conf muss folgende Zeile hinzugefügt werden, die dafür sorgt, dass Datenpakete weitergeleitet werden.

net.ipv4.ip_forward=1

Diese Änderung ist erst nach einem Neustart wirksam. Mit folgendem Befehl kann man das Verhalten aber dennoch sofort erzielen.

sudo sysctl -w net.ipv4.ip_forward=1

Als nächstes muss NAT aktiviert werden. Dieses geschieht mit dem folgenden Befehl.

sudo iptables --table nat --append POSTROUTING --jump MASQUERADE  --source 192.168.0.0/24

Um NAT permanent zu aktivieren, müssen wir diese Konfiguration in der Textdatei /etc/ltsp/nat hinterlegen.

sudo sh -c 'iptables-save > /etc/ltsp/nat'

Im folgenden Schritt müssen wir die NAT-Konfiguration in der Datei /etc/network/interfaces für die entsprechende Netzwerkkarte hinterlegen. Dieses geschieht, in dem die folgende Zeile für eno2 als letzte Zeile ergänzt wird.

up iptables-restore < /etc/ltsp/nat

An dieser Stelle sollte nochmals der Netzwerkdienst neugestartet werden.

sudo systemctl restart networking.service

Um sicherzugehen, dass alle Dienste mit der richtigen Konfiguration laufen, kann man aber auch einfach einen kompletten Neustart des Servers durchführen.

sudo reboot

Einrichtung der Anmeldung mit der IServ-Kennung

Damit man sich einfach mit der IServ-Kennung an einem Client anmelden kann, muss man am Server die Benutzerauthentifizierung an der Samba-Domäne „SCHULE“ einrichten. Hierfür müssen zunächst folgende Pakete installiert werden.

sudo apt-get install winbind libpam-winbind libnss-winbind cifs-utils libpam-mount

Als nächstes muss der LTSP-Server der Domäne „SCHULE“ beitreten.

net rpc join -U benutzername

Hierbei ist „benutzername“ durch den Benutzernamen eines IServ-Domänen-Administrators zu ersetzen. Bei dem Beitritt zur Domäne wird das Passwort des IServ-Domänen-Administrators abgefragt. Als nächstes ist die Konfigurationsdatei /etc/samba/smb.conf wie folgt zu bearbeiten.

[global]
workgroup = SCHULE
security = DOMAIN
os level = 0
local master = No
domain master = No
template homedir = /home/%U
template shell = /bin/bash
winbind separator = +
winbind cache time = 10
winbind enum users = Yes
winbind enum groups = Yes
winbind use default domain = Yes
idmap config * : range = 10000-20000
idmap config * : backend = tdb

Im folgenden Schritt ist in der Datei /etc/nsswitch.conf in den Zeilen, die mit „passwd:“ sowie mit „group“ beginnen noch „winbind“ als letzter Eintrag zu ergänzen. In der Konfigurationsdatei /etc/security/pam_mount.conf.xml muss noch festgelegt werden, wie die Samba-Shares eingebunden werden sollen. Dafür müssen die folgenden Zeilen in /etc/security/pam_mount.conf.xml direkt nach „<!– Volume definitions –>“ eingefügt werden.

<volume uid="10000-20000" fstype="cifs" server="iserv" path="home" mountpoint="/home/%(USER)/Files" options="iocharset=utf8,dir_mode=0700"/>
<volume uid="10000-20000" fstype="cifs" server="iserv" path="groups" mountpoint="/home/%(USER)/Groups" options="iocharset=utf8,dir_mode=0700"/>

Um die Änderungen wirksam werden zu lassen, muss winbind neugestartet werden.

sudo systemctl restart windbind.service

Nach diesen paar kleinen Schritten hat man einen LTSP-Server mit Fat-Clients, an denen man sich mit der IServ-Kennung anmelden und die Netzwerklaufwerke mit Samba nutzen kann.

Aktuellere Software

Um aktuellere Software als die aus den Ubuntu-Paketquellen zu erhalten, ist es empfehlenswert das Repository des „Hellenic Schools Technical Support Team“ zu den Paketquellen hinzuzufügen. Dieses wird sehr gut gewartet und Bugs werden schnell durch entsprechende Updates behoben.

sudo add-apt-repository ppa:ts.sch.gr/ppa
sudo apt-get update

Update des Images

Um das Festplattenimage zu aktualisieren, aktualisiert man zunächst den Server.

sudo apt-get update
sudo apt-get dist-upgrade

Falls im Rahmen der Updates ein Kernel-Update eingespielt wurde, muss man auch ein Kernel-Update im LTSP-Verzeichnis durchführen:

sudo /usr/share/ltsp/update-kernels

Jetzt kann man das Image neu erzeugen:

sudo ltsp-update-image --cleanup /

Schließlich sollte man noch den NBD-Server neustarten, um Probleme zu vermeiden:

sudo systemctl restart nbd-server.service

Modifiziertes Ubuntu im Laptop-Einsatz: Lesezeichen für IServ-webdav-Laufwerk bei Anmeldung erstellen

Auf unseren Laptops werden keinerlei Daten dauerhaft gespeichert. Aus diesem Grund müssen die Schülerinnen und Schüler bearbeitete Dateien in der Cloud speichern. Wir nutzen an unserer Schule zurzeit den IServ-Schulserver, der es den Nutzerinnen und Nutzern ermöglicht, auf ihre Dateien über ein webdav-Laufwerk zuzugreifen.

Das Hinzufügen eines webdav-Laufwerks im Dateimanager ist für erfahrene Computernutzerinnen und -nutzer sicherlich kein Problem. Allerdings sind Einstellungen nötig, für die man genaue Informationen über die Erreichbarkeit des Speichers benötigt. Über diese Informationen verfügen Schülerinnen und Schüler in der Regel nicht. Aus diesem Grund soll nach dem Anmelden direkt ein fertig konfiguriertes Lesezeichen erstellt werden, was nur noch im Dateimanager angeklickt werden muss, um eine Verbindung herzustellen.

Hierfür benötigt man ein kleines Bash-Skript („erstelle_lesezeichen.sh“), was nach dem IServ-Benutzernamen fragt und dann das Lesezeichen passend anlegt. Dieses Skript sollte in /usr/local/bin abgelegt und ausführbar gemacht werden.


#!/bin/bash

if ! NAME=$(zenity --entry --text "IServ-Benutzername:" --title "Nutzername"); then
exit;
fi

sed "s/\__NUTZERNAME/$NAME/g" /etc/skel/.templates/bookmarks_TEMPLATE >~/.config/gtk-3.0/bookmarks

Dieses Skript erfordert eine Blanko-Lesezeichendatei („bookmarks_TEMPLATE“), die wie folgt aussehen muss und die ich in /etc/skel/.templates/ abgelegt habe:


davs://__NUTZERNAME@gbg-seelze.eu/webdav IServ

Damit das Skript zur Abfrage des Benutzernamens und zum Anlegen des Lesezeichens auch nach der Anmeldung automatisch startet, muss man hierfür in /etc/xdg/autostart/ eine *.desktop-Datei anlegen:


[Desktop Entry]
Type=Application
Name=IServ-Lesezeichen erstellen
Exec=/usr/local/bin/erstelle_lesezeichen.sh
X-GNOME-Autostart-enabled=true