Nachdem der mittlerweie mehrere Jahre alte Beitrag Remotedesktopverbindung mit SSL schützen in dieser Form heute nicht mehr funktioniert, nun eine aktualisierte Fassung.

Im Gegensatz zur ursprünglichen Fassung werden diesmal in Verbindung mit stunnel zwei unterschiedliche Ansätze vorgestellt. Zum einen die recht einfache Variante mit einem Pre-shared Key (PSK), zum anderen mit Zertifikaten. Das Ganze wurde erfolgreich unter Windows 10 Pro 1909 und stunnel 5.56 getestet.

Der Einfachheit halber wurde stunnel unter “C:\stunnel” installiert. So hat man es leichter die Konfigurationsdatei zu bearbeiten und Zertifikate zu erstellen, ohne das man ständig mit der Benutzerkontensteuerung von Windows aneinander gerät. Die Daten können über die NTFS-Berechtigungen vor unerwünschten Zugriffe geschützt werden.

Warum nicht Certificate-Pinning?

Als einfachste und quasi-nachfolge Methode zum ursprünglichen gegenseitigem Vertrauen der Zertifikate erscheint Certificate-Pinning. Client/Server-seitig ist dieses einfach zu konfigurieren:

Server:

; *** Logging ***
debug = info
output = stunnel.log

; *** Services ***

[RDP-TLS]

accept = 9000
connect = 127.0.0.1:3389
cert = stunnel.pem

Client:

; *** Logging ***
debug = info
output = stunnel.log

; *** Services ***

[RDP-TLS]
client = yes
accept = 127.0.0.1:9000
connect = <Ziel-IP-oder-Hostname>:9000
CAfile = stunnel.pem
verifyPeer = yes

Allerdings scheint dies ebenfalls nicht (mehr) zu funktionieren, denn im Log finden sich beim Verbindungsversuch folgende Meldungen:

CERT: Pre-verification error: unsupported certificate purpose
Rejected by CERT at depth=0...

Ich habe eine ganze Weile versucht das zu klären, hatte allerdings keinen Erfolg damit. Daher (lieber) die nachfolgenden Methoden.

stunnel mit PSK verwenden

Server-seitig benötigt man folgende Konfigurationsdatei:

; *** Logging ***
debug = info
output = stunnel.log

; *** Services ***
[RDP-PSK]
accept = 9000
connect = 127.0.0.1:3389
ciphers = PSK
PSKsecrets = secrets.txt

Anschließend erzeugt man den bzw. die PSK(s). Am einfachsten geht das mit einme kleinen Skript:

@echo off

set openssl_conf=C:\stunnel\config\openssl.cnf
set RANDFILE=C:\stunnel\config\.rnd

echo.

C:\stunnel\bin\openssl.exe rand -hex 32

echo.
pause

Den erzeugten PSK speichert man zusammen mit einem frei-definierbaren Benutzernamen in der Datei “C:\stunnel\config\secrets.txt” ab:

<Benutzername>:<PSK>

Wahlweise kann man nun die “stunnel.exe” mit einem Doppelklick aus dem Ordner “C:\stunnel\bin” starten oder stunnel als Dienst einrichten und starten. Ersteres ist für Anfang und zum Beobachten des Live-Logs interessanter. Letzteres geht mit:

c:\stunnel\bin\stunnel.exe -install
c:\stunnel\bin\stunnel.exe -start

In der Firewall muss der entsprechende Port, im Beispiel “9000/tcp” freigegeben sein, damit ein Verbindungsaufbau erfolgreich verlaufen kann. I.d.R. richtet stunnel bei der Installation von selbst Regeln für sich ein.

Die Client-Seite sieht nur leicht anders aus:

; *** Logging ***
debug = info
output = stunnel.log

; *** Services ***
[RDP-PSK]
client = yes
accept = 127.0.0.1:9000
connect = <Ziel-IP-oder-Hostname>:9000
ciphers = PSK
PSKsecrets = secrets.txt

In der “secrets.txt” muss nur der Satz an Daten enthalten sein, der für diesen Client bestimmt ist. Auf dem Client kann man stunnel ebenso wie auf dem Server starten. Öffnet man nun die Remotedesktopverbindung (mstsc) gibt man bei “Computer:” “127.0.0.1:9000” ein.

stunnel mit Zertifikaten verwenden

Früher war’s einfacher, konnte man schlicht die jeweils selbst-signierten Zertifikate die stunnel bei der Installation generiert gegeneinander verifizieren lassen, einen vorigen Austausch vorausgesetzt. Das funktioniert so heute nicht mehr. Man kommt um den Einsatz eine PKI (Public Key Infrastructure, Zertifikatsinfrastruktur) nicht mehr herum. Das ist zwar komplexer, dafür allerdings auch sicherer.

CA einrichten

Damit erfolgreich Zertifikate ausgestellt werden können, sind ein paar Schritte notwendig. Zunächst die notwendigen Vorbereitungen:

  • OpenSSL (Light) herunterladen und nach “C:\OpenSSL” installieren. Dieser Schritt ist empfohlen, da die openssl-Version die stunnel beiliegt nicht aktuell ist, ferner fehlt eine für die CA brauchbare “openssl.cnf”.
  • Die Datei “C:\Program Files\Common Files\SSL\openssl.cnf” editieren und wie folgt ändern:
    dir = C:/stunnel/config
  • Unter “C:\OpenSSL\bin” einen Ordner namens “newcerts” anlegen.
  • Eine leere “index.txt” unter “C:\OpenSSL\bin” erzeugen.

Steht das Notwendige soweit, kann mit der Generierung der eigentlichen CA fortgefahren werden. Im Ordner “C:\OpenSSL\bin” eine Eingabeaufforderung öffnen und folgende Befehle ausführen:

Privaten Schlüssel der CA erzeugen:

openssl genrsa -out ca.key

Zertifikatsanfrage der CA erzeugen:

openssl req -new -key ca.key -out ca.csr

Zertifikat der CA ausstellen:

openssl x509 -req -days 3650 -in ca.csr -out ca.crt -signkey ca.key

Server-Zertifikat ausstellen

Mit den nachfolgenden Befehlen werden die notwendigen Zertifikate samt Schlüssel sowohl für den Server als auch den Client erzeugt:

openssl genrsa -out server.key
openssl req -new -key server.key -out server.csr
openssl ca -in server.csr -cert ca.crt -keyfile ca.key -out server.crt -create_serial

Client-Zertifikat ausstellen

openssl genrsa -out client.key
openssl req -new -key client.key -out client.csr
openssl ca -in client.csr -cert ca.crt -keyfile ca.key -out client.crt

Die *.csr-Dateien können nach dem Ausstellen der Zertifikate gelöscht werden.

Server

Nachdem die CA steht, kommt die eigentliche stunnel-Konfiguration, die vergleichsweise einfach ausfällt. Die zuvor erstellten Dateien “ca.crt”, “server.crt” und “server.key” müssen nach “C:\stunnel\config” kopiert werden.

; *** Logging ***
debug = info
output = stunnel.log

; *** Services ***

[RDP-TLS]

accept = 9000
connect = 127.0.0.1:3389
CAfile = ca.crt
verifyChain = yes
cert = server.crt
key = server.key

Client

Und hier die passende Client-Konfiguration. Wichtig ist, das auf den Client die Dateien “ca.crt”, “client.crt” und “client.key” hinterlegt werden.

; *** Logging ***
debug = info
output = stunnel.log

; *** Services ***

[RDP-TLS]
client = yes
accept = 127.0.0.1:9000
connect = <Ziel-IP-oder-Hostname>:9000
CAfile = ca.crt
verifyChain = yes
cert = client.crt
key = client.key

Client-seitig kann ein mehr an Sicherheit durch das Hinzufügen folgender Zeile(n) erreicht werden:

checkHost = <CommonName des Server-Zertifikats>
checkIP = <IP-Adresse des Servers>

Der restliche Ablauf, d.h. stunnel starten und mittels Remotedesktopverbindung arbeiten ist wie zuvor weiter oben beschrieben.

Quellen:

stackoverflow – OpenSSL as a CA without touching the certs/crl/index/etc environment

stunnel – Auth

stunnel – Docs – X509_check_host