Skip to main content

Version_0.5 xfreerdp - Skript

RDP-Launcher mit xfreerdp3 – Schnellstart & Nutzung

Quickstart: Schritt für Schritt (wenn venv schon existiert)
  1. Terminal öffnen
    Ctrl+Alt+T
  2. In Projektordner wechseln
    cd ~/rdp-launcher
  3. Virtuelle Umgebung aktivieren
    source .venv/bin/activate
    (Bei jedem neuen Terminal nötig!)
  4. Launcher starten
    ./xfreerdp_launcher.py
    (Falls nicht ausführbar: chmod +x xfreerdp_launcher.py nur 1x nötig)
    Oder per Python:
    python3 xfreerdp_launcher.py
  5. Menü nutzen, Standort & Server auswählen
  6. Erste Passwortabfrage – wird sicher im Keyring gespeichert

Diese Anleitung richtet sich an absolute Einsteiger und führt dich in wenigen Schritten zur ersten RDP-Sitzung.
Bitte arbeite jeden Schritt der Reihe nach ab.


1. Voraussetzungen prüfen (nur 1x nötig)

  1. Python & Pip:
    python3 --version
    pip3 --version
    Fehlt was?
    sudo apt update sudo apt install python3 python3-pip python3-venv
  2. xfreerdp3 installieren:
    sudo apt install freerdp3-x11
  3. Keyring-Backend? (Gnome, KDE etc: schon dabei)

2. Projektordner & venv erstellen (nur 1x nötig)

  1. Ordner anlegen & wechseln:
    mkdir -p ~/rdp-launcher
    cd ~/rdp-launcher
  2. Virtuelle Umgebung erstellen:
    python3 -m venv .venv
  3. venv aktivieren:
    source .venv/bin/activate
  4. Abhängigkeit installieren:
    pip install keyring
Tipp: Immer zuerst source .venv/bin/activate ausführen, bevor du arbeitest!

3. Python-Skript anlegen

Speichere folgendes als xfreerdp_launcher.py im Projektordner:

▶ Python-Code anzeigen / ausklappen
#!/usr/bin/env python3
"""
xfreerdp_launcher.py – RDP-Launcher mit TUI und Keyring-Support

Features:
- Übersichtliche, farbige Menüführung (TUI)
- Passwörter sicher im System-Keyring gespeichert
- Automatisches Neuladen der Konfiguration bei Änderungen
- Voll kompatibel mit xfreerdp3-Parametern

Benötigt:
- Python ≥ 3.9
- keyring (pip install keyring)
- config.json im selben Ordner
"""

import argparse
import json
import subprocess
import sys
import os
from pathlib import Path
from getpass import getpass
import keyring

CONFIG_FILE = Path("./config.json").resolve()
SERVICE = "xfreerdp_launcher"

def farbig(text, farbe="reset"):
    farben = {
        "reset": "\033[0m", "bold": "\033[1m", "red": "\033[31m",
        "green": "\033[32m", "yellow": "\033[33m", "blue": "\033[34m",
        "magenta": "\033[35m", "cyan": "\033[36m", "gray": "\033[90m",
        "bright_red": "\033[91m", "bright_green": "\033[92m",
        "bright_yellow": "\033[93m", "bright_blue": "\033[94m",
        "bright_magenta": "\033[95m", "bright_cyan": "\033[96m",
        "bright_white": "\033[97m"
    }
    return f"{farben.get(farbe, '')}{text}{farben['reset']}"

def lade_config():
    try:
        return json.loads(CONFIG_FILE.read_text())
    except Exception as e:
        print(farbig(f"⚠️  Fehler in config.json: {e}", "red"))
        return {}

def passwort_holen(cred_alias, domain, user):
    cred_id = f"{cred_alias}|{domain}|{user}"
    pw = keyring.get_password(SERVICE, cred_id)
    if pw is None:
        pw = getpass(f"Passwort für {user}@{domain}: ")
        if not pw:
            sys.exit("Abbruch – kein Passwort eingegeben.")
        keyring.set_password(SERVICE, cred_id, pw)
        print(farbig("Passwort gespeichert.", "green"))
    return pw

def rdp_starten(ip, domain, user, pw, extra_args):
    cmd = [
        "xfreerdp3",
        f"/u:{user}", f"/d:{domain}", f"/v:{ip}",
        "/dynamic-resolution", "/clipboard", "/cert:ignore",
        f"/p:{pw}"
    ] + extra_args
    try:
        subprocess.Popen(cmd)
    except Exception as e:
        print(farbig(f"Fehler beim Start: {e}", "red"))

def host_verbinden(entry, creds, default_cred, extra_args):
    cred = entry.get("cred", default_cred)
    profile = creds.get(cred)
    if not profile:
        print(farbig(f"Credential '{cred}' fehlt!", "red"))
        input("⏎ Weiter...")
        return
    pw = passwort_holen(cred, profile["domain"], profile["user"])
    rdp_starten(entry["host"], profile["domain"], profile["user"], pw, extra_args)
    print(farbig(f"Sitzung zu {entry['alias']} gestartet.", "cyan"))
    input("⏎ Weiter...")

def menue(section, creds, default_cred, extra_args, path="", offene=set()):
    is_root = (path == "")
    while True:
        config = lade_config()
        groups = config.get("groups", {})
        credentials = config.get("credentials", {})
        default = config.get("default_cred", default_cred)
        if is_root:
            section = {"groups": groups}
        creds = credentials
        default_cred = default

        os.system("clear")
        print(farbig(f"=== RDP-Menü {path} ===\n", "bold"))
        groups = section.get("groups", {})
        hosts = section.get("hosts", [])
        index = {}
        i = 1
        if is_root:
            for name, content in groups.items():
                print(f" {i:2}) {farbig(name, content.get('color', 'reset'))} →")
                index[str(i)] = ("group", content, f"{path}/{name}")
                i += 1
        else:
            for h in hosts:
                alias = h["alias"]
                mark = farbig("✅", "green") if alias in offene else "  "
                print(f" {i:2}) {farbig(alias, h.get('color', 'reset'))} – {h['host']} {mark}")
                index[str(i)] = ("host", h)
                i += 1

        print("\n  b) Zurück")
        print("  q) Beenden")
        sel = input(farbig("Auswahl: ", "bold")).strip()
        if sel == "q":
            sys.exit("Beende Launcher.")
        elif sel == "b":
            return
        elif sel in index:
            typ, eintrag, *rest = index[sel]
            if typ == "group":
                menue({"hosts": eintrag.get("hosts", [])}, creds, default_cred, extra_args, rest[0], offene)
            elif typ == "host":
                offene.add(eintrag["alias"])
                host_verbinden(eintrag, creds, default_cred, extra_args)
        else:
            print(farbig("Ungültige Auswahl.", "red"))
            input("⏎ Weiter...")

def main():
    parser = argparse.ArgumentParser(description="xfreerdp Launcher mit Keyring")
    parser.add_argument("freerdp_args", nargs=argparse.REMAINDER, help="zusätzliche xfreerdp3-Parameter")
    args = parser.parse_args()
    offene = set()
    while True:
        config = lade_config()
        creds = config.get("credentials", {})
        default = config.get("default_cred", "")
        groups = config.get("groups")
        if not groups:
            print(farbig("⚠️  Keine Gruppen in config.json.", "yellow"))
            input("⏎ Weiter...")
            continue
        menue({"groups": groups}, creds, default, args.freerdp_args, "", offene)

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n[Abbruch]")

4. Beispiel config.json

Erstelle im selben Ordner eine Datei config.json mit folgendem Inhalt:

▶ Beispiel-Konfiguration anzeigen / ausklappen
{
  "default_cred": "user1",
  "credentials": {
    "user1": { "domain": "FIRMENNETZ", "user": "max.mustermann" },
    "user2": { "domain": "INTRANET",   "user": "maria.musterfrau" }
  },
  "groups": {
    "Standort_A": {
      "color": "bright_blue",
      "hosts": [
        { "alias": "Server-A1", "host": "10.0.10.11", "color": "bright_green",  "cred": "user1" },
        { "alias": "Server-A2", "host": "10.0.10.12", "color": "bright_magenta","cred": "user2" }
      ]
    },
    "Standort_B": {
      "color": "bright_yellow",
      "hosts": [
        { "alias": "Server-B1", "host": "10.0.20.21", "color": "bright_cyan",   "cred": "user1" },
        { "alias": "Server-B2", "host": "10.0.20.22", "color": "bright_red",    "cred": "user2" }
      ]
    }
  }
}

IP-Adressen, Farben etc. kannst du jederzeit anpassen!


5. Alles ausführen – Zusammengefasst

  • Terminal öffnencd ~/rdp-launcher
  • venv aktivierensource .venv/bin/activate
  • Launcher starten./xfreerdp_launcher.py
  • Durch das Menü klicken: Standort → Server → Passwort
  • Passwort wird einmalig abgefragt & im Keyring gespeichert
  • Zum Beenden: q eingeben
Mini-Quickstart:
Ctrl+Alt+T  cd ~/rdp-launcher  source .venv/bin/activate  ./xfreerdp_launcher.py