Timo Denissen vom Professional Service Team von Univention hat im Blog Artikel „Desktops mit Guacamole fernsteuern“ beschrieben, wie sich Rechner über den Browser fernsteuern lassen. Ich möchte in diesem How To zeigen, wie sich dieses Prinzip mit Hilfe von privacyIDEA und xRDP zu einer Terminal Server Umgebung ausbauen lässt, die vollständig im Browser genutzt werden kann, in die Domäne des UCS integriert und mittels 2-Faktor-Authentifizierung abgesichert ist.


Ich gehe in dem HowTo davon aus, dass bereits ein funktionsfähiger UCS Master vorhanden ist. Bei mir läuft dieser virtualisiert unter Proxmox. Darüber stelle ich auch eine zweite VM für die Terminal Server Umgebung bereit.
Die folgenden Schritte beschreibe ich in diesem HowTo im Detail:

  1. LinuxMint mit xRDP vorbereiten
  2. privacyIDEA und RADIUS auf dem UCS Master installieren und konfigurieren
  3. xRDP mit privacyIDEA integrieren
  4. Guacamole mit RADIUS Plugin installieren und konfigurieren

LinuxMint mit xRDP vorbereiten

Als Basis für den Terminal Server verwende ich eine LinuxMint 19.1 XFCE Installation. LinuxMint läuft als Virtuelle Maschine auf einem Proxmox Cluster und hat keine eigenen Grafikkarte mit 3D Unterstützung. Sofern diese vorhanden ist und an die VM durchgereicht wird, kann auch Cinnamon als Desktop zum Einsatz kommen. Die Basis-Installation wird ganz normal mit dem Installationsassistenten durchgeführt und dabei der Benutzer local-admin angelegt.
Nach dem Neustart logge ich mich auf der virtuellen Konsole ein und konfiguriere die statische IP Adresse 10.0.0.2 und lege den UCS Master (IP-Adresse 10.0.0.1) als DNS Server fest.
Ich aktualisiere die Paketquellen und für die Administration installiere ich openssh-server (grundsätzlich auf allen VM‘s) und hinterlege meinen SSH Public Key in den Admin-Benutzerkonten in ~/.ssh/authorized_keys.
Im nächsten Schritt integriere ich LinuxMint entsprechend der Univention Anleitung in der Dokumentation für Ubuntu Clients, die unverändert auch für LinuxMint funktioniert. Der Ubuntu Domain Join Client ist laut Dokumentation inzwischen auch kompatibel mit LinuxMint.
Auf dem Desktop kann ich mich jetzt schon als Domänen Benutzer testweise anmelden.

Als nächstes installiere ich den xRDP Server:
sudo apt-get install xrdp xorgxrdp xrdp-pulseaudio-installer

Damit xRDP auch den XFCE Desktop verwendet, ersetze ich die letzten beiden Zeilen der Datei /etc/xrdp/startwm.sh
test -x /etc/X11/Xsession && exec /etc/X11/Xsession
exec /bin/sh /etc/X11/Xsession
durch
/usr/bin/startxfce4

Jetzt sollte die Anmeldung mit einem RDP Client wie z.B. Remmina von meinem eigenen Linux Desktop aus oder mit dem Windows Remote Desktop Client funktionieren.
Auf die weitere Konfiguration des Desktops gehe ich hier nicht näher ein.
Der erste Schritt ist damit geschafft. Wir können über RDP auf unseren LinuxMint Desktop zugreifen.

privacyIDEA installieren und einrichten

Die Installation von privacyIDEA nehme ich über das Univention App Center auf meinem UCS Master vor. Dazu benötige ich die Apps „RADIUS“, „privacyIDEA“ und „privacyIDEA RADIUS“. privacyIDEA RADIUS integriert sich in den RADIUS Server des UCS, welcher auf FreeRADIUS basiert.
Damit der LinuxMint Rechner eine Verbindung zum UCS Radius Server herstellen kann, mache ich freeradius diesen als Client bekannt. Dazu mache ich auf dem UCS Server als Benutzer root folgenden Eintrag in der Datei /etc/freeradius/3.0/clients.conf
client linuxmint.example.com {
ipaddr = 10.0.0.2
secret = changeme
}

Anschließend starte ich den freeradius Server einmal durch.
service freeradius restart

Nach der Installation von privacyIDEA komme ich über das UCS Portal zur privacyIDEA Administration. Dort logge ich mich mit dem Konto „Administrator@admin“ und dem Administrator Passwort der UCS Domäne ein. Nach dem Info-Dialog erstelle ich unter „Konfiguration“ -> „Richtlinien“ eine neue Richtlinie, um die Benutzeranmeldung mit OTP zu konfigurieren.

AttributnameAttributwert
Richtliniennamelogin_userpass_otp
ScopeAuthentication
AktionMiscellaneous
otppin: userstore
auth_cache: 2m
Benutzerrealmexample.com
Benutzer-ResolverUsers
Priorität1

Ich brauche noch eine zweite Policy, um Details über die Benutzer aus dem LDAP durchreichen zu können.

AttributnameAttributwert
Richtliniennamereturn_user_details
ScopeAuthorization
AktionMiscellaneous
add_user_in_respnse: check
Benutzerrealmexample.com
Benutzer-ResolverUsers
Priorität1

Da ich mit der ersten Richtlinie den auth_cache eingeschaltet habe, brauche ich noch einen Cron-Job, der diesen z.B. täglich aufräumt, um die Datenbank sauber zu halten. Der Zweck des auth_cache wird später noch erklärt.
Daher lege ich auf dem UCS Server die Datei /etc/cron.daily/pi-authcache-cleanup mit dem folgenden Inhalt an:
#!/bin/sh
/opt/privacyidea/privacyidea-venv/bin/pi-manage authcache cleanup

Anschließend aktiviere ich das privacyIDEA RADIUS Modul auf dem UCS Server noch über die Univention Configuration Registry Weboberfläche oder Command-Line:
ucr set privacyidea/radius/enable=1

In der privacyIDEA Dokumentation ist beschrieben, wie die RADIUS Konfiguration von der Command-Line aus getestet werden kann. Dazu muss auf dem LinuxMint Rechner noch das Softwarepaket freeradius-utils installiert werden. Solange noch kein OTP Token einem Benutzer zugewiesen ist, kann eine weitere Richtlinie mit Scope „authentication“ angelegt werden, in der die Option „passthru“ auf „userstore“ gesetzt werden. Ist der Test erfolgreich, kann die Richtlinie deaktiviert werden, für einen User ein TOTP Token ausgerollt werden (z.B. mit den Apps privacyIDEA Authenticator oder FreeOTP Authenticator für Android und iOS) und nun erneut getestet werden. Dieses Mal wird direkt an das Passwort der OTP Wert angehängt.

Der zweite Schritt ist abgeschlossen! Wir können Benutzer der UCS Domäne mit Domänen-Passwort + OTP via RADIUS authentifizieren.

xRDP mit privacyIDEA integrieren

Als Nächstes werde ich die Authentifizierung von xRDP an privacyIDEA anbinden. Da der RADIUS Server den LinuxMint bereits als Client kennt, verwende ich das PAM RADIUS Modul.
sudo apt-get install libpam-radius-auth

In der Datei /etc/pam_radius_auth.conf füge ich noch den RADIUS Server und das Secret ein.
Nun ergänze ich noch die Datei /etc/pam.d/xrdp-sesman um die Anweisung
auth required pam_radius_auth.so
sodass diese wie folgt aussieht:
#%PAM-1.0
auth sufficient pam_radius_auth.so
@include common-auth
@include common-account
@include common-session
@include common-password

Nach einem Neutstart des LinuxMint kann ich mich nun mit einen RDP Client mit Benutzername und Passwort + OTP anmelden. Alternativ könnte hier auch das privacyIDEA PAM Modul verwendet werden.


Desktops mit Guacamole fernsteuern

Mit Guacamole haben Sie jederzeit und von jedem Ort aus Zugriff auf Ihre Systeme. Sie können es ganz einfach in unserem Univention App Center herunterladen. Erfahren Sie in diesem Artikel, wie Sie Guacamole installieren, konfigurieren und benutzen.

Weiter lesen


Guacamole mit RADIUS Erweiterung aufsetzen

Die Guacamole Version, die im UCS App-Store enthalten ist, kommt leider ohne RADIUS Modul. Daher werden wir Guacamole mit Docker basierend auf dem GitHub Repository bauen. Dies erfordert zwar momentan etwas mehr Handarbeit, ermöglicht aber über RADIUS die Integration mit privacyIDEA und somit die zentrale Verwaltung der zweiten Faktoren. Für Guacamole könnte man auch eine eigene VM mit Docker aufsetzen. Um das HowTo einfach zu halten, habe ich mich entschieden Docker und Guacamole ebenfalls auf dem LinuxMint aufzusetzen.

Dafür installieren wir zuerst einmal Docker und docker-compose
sudo apt-get install docker.io docker-compose
und laden den aktuellen Source Code des Guacamole Client herunter:
cd ~
mkdir dev
wget https://github.com/apache/guacamole-client/archive/master.zip
unzip master.zip

Als nächsten legen wir uns die docker-compose Konfiguration für Guacamole an:
cd ~
mkdir -p docker/guacamole
cd docker/guacamole
mkdir certs dbinit mysql-data

cat >docker-compose.yml <<EOF
version: '3'
services:
guacamole:
image: guacamole:latest
build:
context: ../../dev/guacamole-client-master
args:
- BUILD_PROFILE=lgpl-extensions
restart: always
# Set your hostname to the FQDN under which your
# sattelites will reach this container
hostname: linuxmint.example.com
env_file: ./env.secrets
environment:
- MYSQL_HOSTNAME=mariadb
- MYSQL_DATABASE=guacamole_db
- MYSQL_USER=guacamole_user
- GUACD_HOSTNAME=guacd
- RADIUS_EXT_LINKNAME=1-guacamole-auth-radius
- RADIUS_HOSTNAME=10.0.0.1
- RADIUS_AUTH_PROTOCOL=pap
- VIRTUAL_HOST=linuxmint.example.com
- LOGBACK_LEVEL=warn
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "10"
volumes:
- ./dbinit:/root/dbinit
networks:
- guac-tier
guacd:
image: guacamole/guacd
restart: always
environment:
- GUACD_LOG_LEVEL=warning
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "10"
networks:
- guac-tier
mariadb:
image: mariadb:10.4
restart: always
env_file: ./env.secrets
environment:
- MYSQL_DATABASE=guacamole_db
- MYSQL_USER=guacamole_user
volumes:
- ./dbinit/initdb.sql:/docker-entrypoint-initdb.d/initdb.sql
- ./mysql-data:/var/lib/mysql
networks:
- guac-tier

nginx-proxy:
image: jwilder/nginx-proxy
restart: always
ports:
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs
networks:
- guac-tier

networks:
guac-tier:
EOF

Schauen wir uns an, was die docker-compose Konfiguration macht. Erst einmal wird der Guacamole Container definiert und festgelegt, dass das Image dafür lokal aus dem Verzeichnis gebaut wird, in das wir den Source Code ausgepackt haben. Wichtig ist dabei das Build Profil, damit das Radius Modul mitgebaut wird.
services:
guacamole:
image: guacamole:latest
build:
context: ../../dev/guacamole-client-master
args:
- BUILD_PROFILE=lgpl-extensions

Mit den folgenden Umgebungsvariablen wird dem Radius Modul mitgeteilt, wo der Radius Server läuft und welches Protokoll mit diesem gesprochen wird.
- RADIUS_EXT_LINKNAME=1-guacamole-auth-radius
- RADIUS_HOSTNAME=10.0.0.1
- RADIUS_AUTH_PROTOCOL=pap

Um Guacamole über HTTPS erreichbar zu machen, wird davor ein Nginx als Reverse Proxy eingesetzt. Der eingesetzte Container generiert seine Konfiguration für jeden Container, der die Umgebungsvariable VIRTUAL_HOST definiert.
- VIRTUAL_HOST=linuxmint.example.com

Für die Guacamole Container wird noch die Logfile Rotation konfiguriert, damit das Logging der Guacamole Container mir nicht die Festplatte vollschreibt.
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "10"

Zudem wird noch der MySQL Datenbank Container und der Nginx Container definiert.
In einer separaten Datei stellen wir docker-compose die Passwörter zur Verfügung. Diese sollten auf jeden Fall durch sichere Passwörter ersetzt werden.
cat >env.secrets <<EOF
MYSQL_ROOT_PASSWORD=changeme
MYSQL_PASSWORD=changeme
RADIUS_SHARED_SECRET=changeme
EOF

Nun kann ich das Guacamole Client Docker Image bauen:
sudo docker-compose build

Bevor ich die Umgebung starte, generiere ich mit Hilfe des Guacamole Images das Skript zur Datenbank Initialisierung.
sudo docker run --rm guacamole /opt/guacamole/bin/initdb.sh --mysql > ./dbinit/initdb.sql

Ebenso brauche ich noch das Zertifikat für den Nginx Reverse Proxy. Dieses generiere ich auf dem UCS Master und kopiere es auf die LinuxMint VM. Die Dateinamen müssen sich dabei aus dem FQDN und der Dateierweiterung .crt bzw .key zusammensetzen. Der FQDN muss mit dem Wert der Variable VIRTUAL_HOST in der Datei docker-compose.yml übereinstimmen.
ssh root@10.0.0.1
cd /etc/univention/ssl
univention-certificate new -name linuxmint.example.com -days 365
cd linuxmint.example.com
scp cert.pem local-admin@10.0.0.2:/home/local-admin/docker/guacamole/certs/linuxmint.example.com.crt
scp private.key local-admin@10.0.0.2:/home/local-admin/docker/guacamole/certs/linuxmint.example.com.key

Nun kann schließlich die ganze Umgebung gestartet werden und die Log Ausgabe überwacht werden:
sudo docker-compose up -d
sudo docker-compose logs -f

Sobald die Log-Ausgabe wenig neues bringt, kann ich die Guacamole Weboberfläche aufrufen: https://linuxmint.example.com/guacamole.
Auf der Weboberfläche kann ich mich nun mit Benutzername und Passwort + OTP anmelden und erhalte die leere Verbindungsübersicht. Damit funktioniert die Authentifizierung. Jetzt gilt es noch die Authorisierung in Guacamole zu konfigurieren. Dazu melde ich mich wieder ab und melde mich mit dem Benutzer „guacadmin“ mit Passwort „guacadmin“ an. Als erstes ändere ich das Passwort über das Benutzermenü rechts oben -> „Settings“ -> „Preferences“. Dann lege ich über das Benutzermenü -> „Settings“ -> „Connections“ eine neue Verbindung mit den Namen „LinuxMint“ an. Wesentlich sind die folgenden Werte:

AttributnameAttributwert
NameLinuxMint
ProtocolRDP
Parameters -> Network
Hostname10.0.0.2
Parameters -> Authentication
Username${GUAC_USERNAME}
Password${GUAC_PASSWORD}
Parameters -> Display
Color depthTrue color (24-bits)

Im Benutzermenü -> „Settings“ -> „Users“ lege ich noch einen Benutzer mit meinen Benutzernamen aus der Domäne ohne Passwort an. Dem Benutzer weise ich nun die Verbindung zu. Alternativ könnte ich eine Gruppe in Guacamole anlegen, der Gruppe die Verbindung zuweisen und den Benutzer in die Gruppe aufnehmen. Leider unterstützt das Guacamole RADIUS Modul noch keine Gruppen. Einen entsprechenden Feature Request gibt es dazu im Issue Tracker des Projektes.

Für Benutzer, die nur Berechtigung für eine Verbindung haben, öffnet Guacamole diese direkt nach dem Login. Die Variablen im Username und Password führen dazu, dass Guacamole beim Öffnen der Verbindung Benutzername und Passwort durchreicht, welche für die Anmeldung an Guacamole verwendet wurden.
Hier wird jetzt der Authentication Cache von privacyIDEA relevant, den wir in der Richtlinie „login_userpass_otp“ definiert haben. Da das Passwort ja ein OTP enthält, würde die automatische Anmeldung am xRDP einen Fehler liefern, da ein One-Time-Passcode gemäß seines Namen nur einmal verwendet werden kann. Um den Anmeldeprozess für die Benutzer komfortabler zu gestalten, habe ich entschieden, den Auth-Cache zu nutzen.

In einem Umfeld mit begrenzter Anwenderzahl lässt sich die Sicherheit noch weiter verbessern, indem der Zugriff auf den NGINX vor dem Guacamole z.B. mit Client-Zertifikats-Authentifikation eingeschränkt wird.

Fazit

Damit ist es geschafft. Mit xRDP, privacyIDEA und Guacamole wurde eine web-basierte Open Source Remote Desktop Umgebung mit 2-Faktor-Authentifizierung erstellt.

Obwohld der bei Windows RDP mögliche Zugriff auf lokale Dateien und Drucker des Clients mit Guacamole (siehe Guacamole FAQ) leider noch nicht möglich ist, bietet die Lösung für Unternehmen eine Open Source Alternative für eine Remote Desktop Umgebung mit einem guten Sicherheitsniveau.

UCS Core Edition jetzt kostenfrei einsetzen!

Zum Downloadbereich
Jörn Lentes

Jörn Lentes ist 42 Jahre alt, verheiratet, Vater von 5 Söhnen, selbstständiger Unternehmensberater und Coach, sowie Kommunikationstrainer für Gewaltfreie Kommunikation. Mehr als 15 Jahre beriet er als IT-Consultant für Hewlett-Packard DAX Unternehmen aus der Automobil-, Luftfahrt- und Pharmabranche. Heute berät er vorwiegend KMU und schätzt dort die effektiven Entscheidungswege und die Innovationsbereitschaft. In seiner Freizeit geht er mit der Familie im Mittelmeer und auf dem Atlantik segeln.