Remote Desktop für das Homeoffice, sicher und günstig

Android Türsteher prüft am leuchtenden Server Tor die Identität eines Clients während eine verdächtige Gestalt von einem Schutzschild abgewiesen wird.
RustDesk Server Setup mit Fail2ban Schutz für sicheres Remote Desktop im Homeoffice. KI-generiert (GPT Image 2).

Wenn Sie einen Server remote steuern müssen, dann reicht dafür SSH völlig aus. Aber wenn es um einen Desktop geht? Und vor allem, wenn der remote Desktop nicht das gleiche Betriebssystem hat wie das System, auf dem Sie arbeiten? Dafür stellen wir Ihnen heute RustDesk vor, eine Open-Source-Lösung, die sehr sicher ist und keine Lizenzkosten verursacht. Sie finden außerdem eine Anleitung, wie Sie RustDesk auf einem eigenen oder gemieteten Server installieren können.

Man könnte natürlich Teamviewer verwenden, aber Teamviewer ist nur für die private Nutzung kostenlos, für die geschäftliche sind die Preise gesalzen. Abgesehen davon ist Teamviewer zwar ursprünglich ein deutsches Unternehmen, wurde dann aber von einem US-Unternehmen aufgekauft, und wie es seither mit der Vertraulichkeit und Sicherheit der Daten ist, ist naturgemäß schwer zu sagen. Teamviewer ist eine hervorragende Lösung, keine Frage, und bietet viel Funktionalität. Aber vielleicht brauchen Sie ja nur die Grundfunktionen, oder Sie möchten in Ihrem Unternehmen sicherstellen, dass nur berechtigte Nutzer Zugang zu Ihrem Server haben und alle anfallenden Daten vollständig unter Ihrer Kontrolle sind ohne Einbeziehung von Fremdanbietern.

Dann ist RustDesk https://rustdesk.com/ eine hervorragende Alternative. Es ist Open Source und Sie können es auf einem eigenen Server betreiben. Oder man mietet einen Server, der nicht besonders leistungsstark sein muss, und deshalb recht günstig zu bekommen ist bei vielen Anbietern, zum Beispiel Hetzner, Strato oder Hostinger.

Aus der Eigenbeschreibung von RustDesk:

Inmitten der Covid-19-Pandemie Mitte 2020 sah sich der Gründer gezwungen, eine kommerzielle Lizenz für TeamViewer zu erwerben, um Fernarbeit zu ermöglichen. Die hohen Kosten überraschten ihn jedoch. Nach einer schlaflosen Nacht machte er sich daran, eine alternative Lösung zu entwickeln. So entstand RustDesk – eine Open-Source-Software für Fernzugriff, die in zahlreichen schlaflosen Nächten sorgfältig entwickelt wurde. Diese Arbeit voller Hingabe und Entschlossenheit gipfelte in der Veröffentlichung von RustDesk auf GitHub im Jahr 2021, wodurch es von Menschen weltweit genutzt werden konnte.

RustDesk ist quelloffen unter der AGPL-3.0-Lizenz – Client und Server finden Sie im offiziellen GitHub-Repository. Kommerzielle Nutzung, Modifikation und Eigenbetrieb sind ausdrücklich kostenlos erlaubt; lediglich die optionale, separate „Server Pro“-Zusatzkonsole mit zentraler Geräteverwaltung ist kostenpflichtig und nicht Teil der offenen Basis, die wir hier einsetzen.

Ob Sie es aber auf einem eigenen Server oder einem gemieteten installieren, Sie benötigen Root Access. Dann ist es nicht schwer, eine RustDesk-Instanz aufzusetzen und in einem Vormittag erledigt.

So bauen Sie Ihre eigene RustDesk-Instanz

Das Grundgerüst besteht aus zwei kleinen Docker-Containern: hbbs, dem Signal- und ID-Server, und hbbr, dem Relay, der die eigentlichen Daten durchschleust, wenn eine direkte Verbindung nicht zustande kommt. Beide zusammen laufen auf praktisch jedem günstigen VPS.

sudo mkdir -p /opt/rustdesk-server/data && cd /opt/rustdesk-server
sudo tee compose.yml >/dev/null <<'EOF'
services:
  hbbs:
    image: rustdesk/rustdesk-server:1.1.16
    command: hbbs
    volumes: ["./data:/root"]
    network_mode: "host"
    restart: unless-stopped
  hbbr:
    image: rustdesk/rustdesk-server:1.1.16
    command: hbbr -k _
    volumes: ["./data:/root"]
    network_mode: "host"
    restart: unless-stopped
EOF
sudo docker compose up -d hbbs
sudo cat data/id_ed25519.pub   # dieser Key kommt später in jeden Client
sudo docker compose up -d hbbr

(Hinweis: docker compose up lädt auch das Image, wenn es noch nicht am Server vorhanden ist. Außerdem, diese Anleitung ist für Debian, funktioniert aber auch für RHEL und Arch. Für letztere beide müssten Sie aber den Firewall-Part, siehe unten, entsprechend anpassen.)

Zwei Details lohnen sich, bevor Sie loslegen: Setzen Sie network_mode: "host", denn bei klassischem Port-Publishing legt Docker seine Regeln in Ketten an, an denen UFW vorbeigreift – die Firewall sieht dann brav aus, wirkt aber nicht. Und starten Sie hbbs zuerst, und alleine, damit es sein Schlüsselpaar erzeugen kann, bevor hbbr mitmischt.

Danach öffnen Sie die nötigen Ports:

sudo ufw allow 21115/tcp
sudo ufw allow 21116/tcp
sudo ufw allow 21116/udp
sudo ufw allow 21117/tcp

Fail2ban gegen Brute-Force-Versuche

RustDesk protokolliert jeden Verbindungsversuch mit falschem Schlüssel. Der Haken: docker compose logs liest aus einer Datei, deren Pfad die Container-ID enthält – die ändert sich bei jedem Neustart des Containers, und Fail2ban braucht aber einen stabilen Log-Zugang. Die Lösung ist, die Container nach journald loggen zu lassen. Ergänzen Sie dazu die compose.yml aus dem vorigen Schritt um jeweils einen Logging-Block:

services:
  hbbs:
    image: rustdesk/rustdesk-server:1.1.16
    command: hbbs
    volumes: ["./data:/root"]
    network_mode: "host"
    restart: unless-stopped
    logging:
      driver: journald
  hbbr:
    image: rustdesk/rustdesk-server:1.1.16
    command: hbbr -k _
    volumes: ["./data:/root"]
    network_mode: "host"
    restart: unless-stopped
    logging:
      driver: journald

Nach sudo docker compose up -d lesen Sie die Logs fortan nicht mehr über Compose, sondern direkt über journald:

sudo journalctl CONTAINER_NAME=hbbs -o cat | tail

Die Logzeilen, um die es geht, sehen so aus:

WARN [src/rendezvous_server.rs:683] Authentication failed from [::ffff:1.2.3.4]:59705 for peer <ID> - invalid key
WARN [src/relay_server.rs:431] Relay authentication failed from [1.2.3.4]:14286 - invalid key

Legen Sie dafür einen eigenen Fail2ban-Filter an:

sudo tee /etc/fail2ban/filter.d/rustdesk.conf >/dev/null <<'EOF'
[Definition]
failregex = (?:Relay )?[Aa]uthentication failed from \[(?:::ffff:)?<HOST>\]:\d+(?: for peer \S+)? - invalid key
ignoreregex =
EOF

Das (?:::ffff:)? ist kein Zierrat: Docker im Host-Networking-Modus liefert IPv4-Adressen im Log manchmal als IPv6-gemappte Form aus ([::ffff:1.2.3.4]), und ohne dieses optionale Präfix greift die Regel bei genau der Hälfte der Fälle ins Leere.

Dann das eigentliche Jail:

sudo tee /etc/fail2ban/jail.d/rustdesk-server.conf >/dev/null <<'EOF'
[rustdesk]
enabled      = true
backend      = systemd
journalmatch = CONTAINER_NAME=hbbs CONTAINER_NAME=hbbr
logpath      = /dev/null
filter       = rustdesk
banaction    = ufw
findtime     = 600
maxretry     = 3
bantime      = 60
EOF
sudo systemctl restart fail2ban

Drei Stolpersteine, die hier schon gelöst sind:

  • backend = systemd statt der Standardeinstellung – ohne diesen Parameter erwartet Fail2ban eine klassische Logdatei, die es bei journald-Logging nie zu sehen bekommt.
  • logpath = /dev/null ist nur ein Platzhalter, den das systemd-Backend als Pflichtfeld verlangt – ausgewertet wird stattdessen journalmatch.
  • banaction = ufw reiht den Bann direkt in Ihre bestehenden UFW-Regeln ein, statt eine parallele iptables-Kette aufzumachen, die sich mit UFW ins Gehege kommen könnte. Das funktioniert nur zuverlässig, weil die Container im vorigen Schritt mit network_mode: "host" laufen – sonst würde der Bann an denselben Docker-NAT-Regeln vorbeigehen, die schon UFW selbst umgangen haben.

Testen lässt sich der Filter, ohne den Daemon anzufassen:

sudo journalctl CONTAINER_NAME=hbbs CONTAINER_NAME=hbbr --since "24 hours ago" -o short > /tmp/rustdesk.log
sudo fail2ban-regex /tmp/rustdesk.log /etc/fail2ban/filter.d/rustdesk.conf

Wichtig: das Format muss -o short sein, nicht -o cat – ohne Zeitstempel verwirft Fail2ban jede Zeile, obwohl der Regex eigentlich passt.

Und ob am Ende wirklich gesperrt wird, lässt sich risikofrei mit einer Testadresse aus dem reservierten Dokumentations-Bereich prüfen:

sudo fail2ban-client set rustdesk banip 203.0.113.7
sudo ufw status | grep 203.0.113
sudo fail2ban-client unban 203.0.113.7

Ein letzter Punkt, damit Sie sich nicht selbst aussperren: Setzen Sie bantime anfangs niedrig (z. B. 60 Sekunden), solange noch alte Clients mit falschem Schlüssel im Netz hängen könnten – ein zu hoher Wert verwandelt einen versehentlichen Fehlversuch in eine stundenlange Sperre für sich selbst. Erst wenn alle Geräte auf den richtigen Key umgestellt sind, auf den Endwert von einer Stunde oder einem Tag hochsetzen.

Client einrichten

Feld Wert
ID-Server Ihre Server-IP oder ein DNS-Name
Relay-Server leer lassen
Key Inhalt von data/id_ed25519.pub

Ein Hinweis zur Beruhigung: Der öffentliche Schlüssel ist kein Geheimnis – er steckt in jedem Client und taucht sogar im Server-Log auf. Wer ihn kennt, kann trotzdem weder Sitzungen übernehmen noch einen Rechner steuern, denn die Gegenstelle muss die Verbindung weiterhin aktiv freigeben.

Und zur Wartung: Ein Versions-Update ist ein einzeiliger Image-Pull, die Schlüssel und Konfiguration bleiben im Bind-Mount erhalten. Nur eines sollten Sie nicht tun – auf latest pinnen, sonst fehlt Ihnen im Ernstfall der Rollback-Anker.

Noch zwei Tipps: Das Schlüsselpaar gilt für Ihre gesamte Installation, also alle Clients. Falls Sie also die Zugangsberechtigung ungültig machen wollen, zum Beispiel für ausgeschiedene Mitarbeiter, müssen Sie leider das Schlüsselpaar rotieren. Das geht ganz einfach, stoppen Sie die beiden RustDesk-Dienste und löschen Sie das Schlüsselpaar id_ed25519 und id_ed25519.pub in /opt/rustdesk-server/data/. Beim Neustarten der RustDesk-Dienste wird das Schlüsselpaar neu angelegt, Sie müssen dann aber den Public Key in id_ed25519.pub neu an alle berechtigten Nutzer verteilen.

Das eben beschriebene Verfahren eignet sich übrigens auch, wenn Sie eine bereits bestehende RustDesk-Installation auf einen anderen Server umziehen möchten. Kopieren Sie das Schlüsselpaar vom alten Server und legen Sie es im data-Verzeichnis ab, bevor Sie auf dem neuen Server RustDesk erstmals starten.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert