Remote Access: Unterschied zwischen den Versionen
Ca (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
Sv (Diskussion | Beiträge) password authentication: URL form, code API, auth order; launcher menu entries |
||
| (9 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
{{Languages|Remote Access|label=Deutsch}} |
|||
Remote access is the ability to access a remote computer or a remote network from a local computer. |
|||
Remote desktop software lets you access your computer and all its applications over the Internet |
|||
using another device, essentially by streaming a feed of your desktop. To do this, you’ll need |
|||
to set up a remote desktop server on the PC you want to connect to. |
|||
'''Fernzugriff''' bezeichnet die Möglichkeit, einen entfernten |
|||
Telnet |
|||
Rechner oder ein entferntes Netzwerk aus diesem expecco-Image heraus |
|||
Telnet is an application protocol used on the Internet or local area network to provide a |
|||
zu bedienen — Shells zu öffnen, Befehle abzusetzen, Dateien zu |
|||
bidirectional interactive text-oriented communication facility using a virtual terminal |
|||
verschieben oder ein Testgerät anzusteuern. Drei Protokoll-Familien |
|||
connection. User data is interspersed in-band with Telnet control information in an 8-bit |
|||
sind unterstützt, in absteigender Empfehlungsreihenfolge: |
|||
byte oriented data connection over the Transmission Control Protocol (TCP). |
|||
Telnet is a strongly outdated network protocol with few security mechanisms. Passwords |
|||
are transmitted in plain text. |
|||
A connection between two computers is established, even if these are under |
|||
run different operating systems. |
|||
* '''SSH und SFTP''' (empfohlen) — verschlüsselte Shell und sichere Dateiübertragung über einen SSH-2-Tunnel. Reine Smalltalk-Implementierung in <code>exept:libcrypt/ssh</code>; keine externe Abhängigkeit von OpenSSL oder libssh. Für alles mit Zugangsdaten oder sensiblen Nutzdaten. |
|||
Only use Telnet when you really need it. |
|||
* '''Lokale Kommando-Shell''' — fork + exec auf der lokalen Maschine. Für die Anbindung lokaler Werkzeuge und für die lokale Seite eines hybriden Workflows. |
|||
* '''Telnet''' (veraltet) — Klartext-Terminalsitzung. Keine Verschlüsselung, Passwörter im Klartext auf der Leitung. Nur einsetzen, wenn die Gegenstelle keine Alternative bietet. |
|||
= SSH und SFTP = |
|||
Example: (found in the RemoteAccess library) |
|||
Telnet - Open Remote Connection With Login |
|||
Telnet - Execute Remote Command |
|||
Example - Remote Device Control via Telnet (used internal only) |
|||
Der SSH-Stack deckt das vollständige SSH-2-Protokoll ab |
|||
Command Shell |
|||
(RFC 4251–4254, RFC 5656, RFC 8709, RFC 8731) inklusive der |
|||
Command shell on your local computer. Typical applications include local command-line, |
|||
chacha20-poly1305-Transportchiffrierung von OpenSSH sowie das |
|||
and local command execution. |
|||
SFTP-v3-Subsystem (draft-ietf-secsh-filexfer-02). Zwei Schichten: |
|||
* '''<code>SSH::Client</code>''' — programmatischer SSH-Zugriff (entferntes <code>exec</code>, TTY-Shell, Agent-Weiterleitung, ProxyJump-Bastion). |
|||
Example: (found in the RemoteAccess library) |
|||
* '''<code>SSH::SftpFilename</code>''' — eine |
|||
CmdShell - Open |
|||
<code>Filename</code>-Unterklasse, die es dem restlichen ST/X |
|||
erlaubt, einen entfernten SFTP-Pfad zu behandeln wie eine lokale |
|||
Datei. |
|||
Die folgenden Abschnitte sind nutzeraufgaben-zuerst aufgebaut: |
|||
zuerst das, was der Anwender sieht und tut, darunter die |
|||
expecco-Bibliotheks-Anbindung, ganz unten Implementierungsdetails |
|||
für Interessierte. |
|||
== Aus dem FileBrowserV2 == |
|||
SSH (Secure Shell) |
|||
Secure Shell (SSH) is a cryptographic network protocol for operating network services |
|||
securely over an unsecured network. Typical applications include remote command-line, |
|||
login, and remote command execution, but any network service can be secured with SSH. |
|||
If you want to send confidential data, you better use an SSH connection. |
|||
SSH can also implement the Telnet protocol, but encrypt it. |
|||
Im Adress-Dropdown eine <code>sftp://</code>-URL einfügen. Der |
|||
SSHconnect-Input on Action [CmdShell - Open SSH Remote Connection] |
|||
Browser-Tab füllt sich wie bei einem lokalen Pfad. |
|||
On windows we are using the plink which is a command-line connection tool similar |
|||
Baum-Ausklappen, Spaltensortierung (Name / Größe / mtime), |
|||
to UNIX (download the PuTTY from Internet). |
|||
Vorschau und Doppelklick zum Öffnen im Editor verhalten sich |
|||
To have a public and private key you can can call the puttygen. |
|||
normal. Der erste Klick auf einen Host dauert ~200–500 ms |
|||
(TCP + KEX + Auth); folgende Klicks nutzen die gepoolte |
|||
Verbindung weiter. |
|||
URL-Syntax: |
|||
Example: (found in the RemoteAccess library) |
|||
CmdShell - Open SSH Remote Connection |
|||
CmdShell - Open SSH Remote Connection and PublicKey |
|||
<pre> |
|||
To run the examples you need the private and public keys. The public key |
|||
sftp://[user[:password]@]host[:port]/remote/path |
|||
should be installed on the remote host. |
|||
</pre> |
|||
Fehlt <code>user</code>, wird der lokale Login-Name verwendet, Port |
|||
ist standardmäßig 22, Pfad standardmäßig <code>/</code>. Das |
|||
optionale <code>:password</code>-Segment ist das RFC-3986-Userinfo-Passwort |
|||
— wann es angebracht ist und welche Sicherheitsabwägungen |
|||
damit verbunden sind, beschreibt [[#Passwort-Authentifizierung]]. |
|||
Wenn vorhanden, dient es als USERAUTH-Fallback nach den üblichen |
|||
Publickey-/Agent-Versuchen und wird '''niemals''' wieder von der |
|||
druckbaren URL-Form ausgegeben — das Protokollieren des |
|||
Dateinamens leakt also nicht das Credential. |
|||
Die Schaltfläche '''Refresh''' in der Symbolleiste |
|||
(Pfeil-Kreis-Symbol zwischen ''Forward'' und ''DirectoryUp'') liest |
|||
Baum und Inhalts-Panel auf Anforderung neu ein. Funktioniert |
|||
einheitlich für lokale und SFTP-Pfade; bei SFTP wird zusätzlich der |
|||
per-Datei-STAT-Cache geleert, sodass Änderungen, die direkt auf |
|||
der Gegenseite gemacht wurden, sofort sichtbar werden — ohne auf |
|||
den Ablauf der 5-Sekunden-Cache-TTL zu warten. |
|||
Der kleine Pfeil neben dem Refresh-Symbol öffnet ein Aufklappmenü |
|||
mit einem einzelnen Kontrollkästchen, '''Automatic Refresh''', das |
|||
den Hintergrund-Task an- bzw. abschaltet, der alle expandierten |
|||
Baumeinträge auf externe Änderungen prüft. Die Vorgabe richtet |
|||
sich nach der aktuellen Wurzel: |
|||
* Lokales Dateisystem → '''an''' (10-Sekunden-Zyklus, entspricht dem bisherigen Verhalten). |
|||
* SFTP → '''aus'''. Jeder Zyklus kostet einen STAT-Roundtrip pro Kind — für eine Handvoll lokaler Verzeichnisse harmlos, über das Netz schmerzhaft. Bei Bedarf manuell auf Refresh klicken, um Änderungen zu sehen. |
|||
Beim Wechsel zwischen lokalen und SFTP-Wurzeln wird der Schalter |
|||
automatisch umgelegt — aber nur, sofern man ihn für die |
|||
vorherige Wurzel nicht selbst verstellt hat. Eine explizite |
|||
Benutzerwahl bleibt über Navigationen hinweg erhalten. |
|||
Das Menü '''Tools''' im FileBrowserV2 bietet vier Aktionen — die |
|||
drei SSH-spezifischen sind nur bei geladener SSH-Bibliothek |
|||
sichtbar: |
|||
* '''Generate SSH Key Pair...''' — öffnet den Schlüsselerzeugungs-Dialog, siehe [[#Einen SSH-Schlüssel erzeugen]] unten. |
|||
* '''SSH Connect...''' — öffnet ein interaktives VT100-Terminal zu einem entfernten Host. |
|||
* '''SFTP Connect...''' — navigiert diesen Browser-Tab über SFTP auf ein entferntes Dateisystem. |
|||
* '''Filesystem Info...''' — zeigt Größe, freien Platz und Belegung des Dateisystems, das das aktuell angezeigte Verzeichnis enthält. Funktioniert einheitlich für lokale und SFTP-Pfade; bei SFTP setzt der Aufruf voraus, daß der Server die Erweiterung |
|||
<code>statvfs@openssh.com</code> ankündigt (jedes moderne OpenSSH |
|||
tut das). Größen werden in IEC-Binäreinheiten ausgegeben (MiB, |
|||
GiB, TiB) — gewählt wird die größte Einheit, die einen Wert ≥ 1 |
|||
liefert, damit ein TB-großes Volume als ''X TiB'' statt |
|||
''10240 GiB'' erscheint. |
|||
== Aus dem Launcher == |
|||
Das Untermenü '''Workspace''' im Launcher enthält zwei eigenständige |
|||
Einträge (nur sichtbar bei geladenem SSH-Paket): |
|||
* '''SSH Terminal''' — fragt nach einem Ziel der Form <code>user[:password]@host[:port]</code> und öffnet ein VT100-Terminal als eigenständiges Fenster. Das ist das Launcher-Pendant zum FileBrowserV2-Eintrag '''Tools → SSH Connect...'''. |
|||
* '''SFTP Connection''' — fragt nach einem SFTP-Ziel (gleiche URL-Grammatik wie in der FileBrowserV2-Adresszeile, siehe [[#Aus dem FileBrowserV2]]) und öffnet einen frischen FileBrowserV2, der bereits dorthin navigiert ist. |
|||
Beide Einträge unterstützen die in [[#Passwort-Authentifizierung]] |
|||
beschriebene URL-Form mit eingebettetem Passwort. |
|||
== Aus expecco-Aktionen == |
|||
Das Expecco-RemoteAccess-Plugin |
|||
([[Expecco::RemoteAccessImportPlugin]]) stellt folgende Testaktionen |
|||
in der expecco-Aktionspalette bereit: |
|||
* '''CmdShell - Open SSH Remote Connection''' — öffnet eine SSH-Sitzung über das plattformeigene <code>ssh</code>-Binary (PuTTYs <code>plink</code> unter Windows). |
|||
* '''CmdShell - Open SSH Remote Connection and PublicKey''' — dasselbe, jedoch mit expliziter Public-Key-Authentifizierung. |
|||
Voraussetzung: ein eingerichtetes Schlüsselpaar (privater |
|||
Schlüssel auf dieser Maschine, öffentlicher Teil in der |
|||
<code>~/.ssh/authorized_keys</code> des Zielhosts). Schlüssel |
|||
erzeugen entweder über den Dialog unten oder über |
|||
<code>ssh-keygen</code>. |
|||
Das Plugin fügt zusätzlich eine Settings-Seite hinzu: |
|||
'''Extras → Settings → Plugins → Remote Access — SSH Keys''' mit |
|||
einer einzelnen Schaltfläche '''Generate SSH Key Pair...''', die |
|||
denselben Dialog öffnet. |
|||
== Einen SSH-Schlüssel erzeugen == |
|||
=== Der Dialog (FileBrowserV2 / Settings-Seite) === |
|||
Der Dialog fragt alle Parameter in einem Formular ab: |
|||
* '''Comment''' — wird in den erzeugten Schlüssel eingebettet (Voreinstellung <code>stx@<hostname></code>). |
|||
* '''Storage''': |
|||
** ''Save to disk file only'' — schreibt |
|||
<code>~/.ssh/id_ed25519_stx</code> (oder wohin man will) samt |
|||
zugehöriger <code>.pub</code>-Datei daneben. |
|||
** ''Save to disk AND load into ssh-agent'' — schreibt die Datei UND übergibt den Schlüssel dem laufenden ssh-agent. |
|||
** ''Load into ssh-agent only'' — der Schlüssel lebt nur im Speicher des Agents; nach Agent-Neustart ist er verloren. |
|||
* '''Private key file''' — vollständiger Pfad; ausgegraut im Agent-only-Modus. |
|||
* '''Passphrase / Confirm''' — leer lässt die On-Disk-Datei unverschlüsselt (Agent-only-Modus ignoriert die Passphrase, da das OpenSSH-Agent-Wire-Protokoll nur den entschlüsselten Schlüssel transportiert). |
|||
Bei '''Generate''' wird die Public-Key-Zeile (dieselbe |
|||
<code>ssh-ed25519 AAAA... comment</code>-Zeichenfolge, die |
|||
ssh-keygen ausgibt) in die System-Zwischenablage kopiert — zum |
|||
direkten Einfügen in die <code>~/.ssh/authorized_keys</code> des |
|||
Zielhosts. |
|||
=== Aus einem Workspace === |
|||
Für Headless-Deployments, Sandbox-Builds oder Skripte stellt |
|||
<code>SSH::Client</code> einen reinen Smalltalk-Schlüsselgenerator |
|||
bereit, dessen Ausgabe bit-kompatibel zu |
|||
<code>ssh-keygen -t ed25519</code> ist: |
|||
<pre> |
|||
| seed comment priv | |
|||
seed := SSH::Client generateEd25519Seed. |
|||
comment := 'stx@', OperatingSystem getHostName. |
|||
"/ Passphrase-verschlüsselt auf Platte speichern" |
|||
priv := (Filename homeDirectory / '.ssh' / 'id_ed25519_stx') pathName. |
|||
SSH::Client |
|||
saveOpenSshEd25519Seed:seed |
|||
toFile:priv |
|||
comment:comment |
|||
passphrase:'choose-something-long'. |
|||
"/ UND in den laufenden Agent laden" |
|||
SSH::Client addEd25519SeedToAgent:seed comment:comment. |
|||
"/ Public-Key-Zeile zum Einfügen in authorized_keys ausgeben" |
|||
Transcript showCR: |
|||
(SSH::Client authorizedKeysLineForEd25519Seed:seed comment:comment). |
|||
</pre> |
|||
Die so erzeugten Schlüssel sind mit den OpenSSH-Werkzeugen voll |
|||
interoperabel (<code>ssh-keygen -y -f ...</code> rekonstruiert den |
|||
öffentlichen Schlüssel, <code>ssh-keygen -p -f ...</code> ändert |
|||
die Passphrase usw.). |
|||
=== Mit den Shell-Werkzeugen === |
|||
Der klassische Weg funktioniert weiterhin: |
|||
<pre> |
|||
ssh-keygen -t ed25519 -C "stx@your.host" |
|||
ssh-copy-id user@remotehost |
|||
ssh-add ~/.ssh/id_ed25519 |
|||
</pre> |
|||
== ssh-agent vorbereiten == |
|||
Der Weg über den Agent ist dem direkten Lesen von Schlüsseldateien |
|||
deutlich vorzuziehen: er hält verschlüsselte private Schlüssel |
|||
einmal pro Sitzung entsperrt und kann Identitäten verwalten |
|||
(hardware-tokengestützte Schlüssel, KeePassXC-Einträge), die ST/X |
|||
nie direkt sehen soll. |
|||
ST/X erkennt den Agent-Pfad automatisch, sobald |
|||
<code>$SSH_AUTH_SOCK</code> '''zum Zeitpunkt des Starts von stx''' |
|||
in der Prozessumgebung gesetzt ist. Eine spätere Zuweisung aus |
|||
einem Workspace nützt nichts. |
|||
=== Linux / macOS === |
|||
Die meisten Desktop-Distributionen starten einen Agent automatisch |
|||
beim Login (gnome-keyring unter GNOME, ssh-agent.service unter |
|||
systemd, KWallet unter KDE). Prüfen im Terminal: |
|||
<pre> |
|||
echo $SSH_AUTH_SOCK # /run/user/1000/keyring/ssh oder ähnlich |
|||
ssh-add -l # listet geladene Identitäten |
|||
ssh-add ~/.ssh/id_ed25519 # eigene laden, falls nicht da |
|||
</pre> |
|||
Läuft gar kein Agent, dieses Snippet in die Shell-rc-Datei |
|||
aufnehmen: |
|||
<pre> |
|||
# ~/.bashrc oder ~/.zshrc |
|||
if [ -z "$SSH_AUTH_SOCK" ]; then |
|||
eval "$(ssh-agent -s)" > /dev/null |
|||
fi |
|||
</pre> |
|||
ST/X muss aus einer Shell gestartet werden, die diese rc bereits |
|||
gelesen hat — ein Desktop-Launcher aus dem Dateimanager erbt die |
|||
Variable nicht. Empfehlung: ein kleines Wrapper-Skript unter |
|||
<code>~/.local/bin/</code>, das die rc sourcet und dann stx |
|||
startet. |
|||
Die Settings-Seite ('''Extras → Settings → Plugins → Remote |
|||
Access — SSH Keys''') zeigt an, ob das laufende Image einen |
|||
Agent sieht. |
|||
==== Permanente Einrichtung via systemd ==== |
|||
Für einen wirklich sitzungsübergreifenden Agent (überlebt Desktop- |
|||
Abmeldung, kommt beim nächsten Login wieder hoch) die bei den |
|||
meisten Distros mit dem Paket <code>openssh-clients</code> |
|||
ausgelieferte Per-User-systemd-Unit aktivieren: |
|||
<pre> |
|||
systemctl --user enable --now ssh-agent.service |
|||
</pre> |
|||
Anschließend <code>SSH_AUTH_SOCK</code> in der Shell-rc auf den |
|||
User-Service-Socket zeigen lassen (ersetzt das |
|||
<code>eval $(ssh-agent -s)</code>-Snippet oben): |
|||
<pre> |
|||
export SSH_AUTH_SOCK="${XDG_RUNTIME_DIR}/ssh-agent.socket" |
|||
</pre> |
|||
==== Schlüssel automatisch beim ersten Einsatz laden ==== |
|||
Um den manuellen <code>ssh-add</code>-Schritt zu sparen, kann |
|||
OpenSSH Schlüssel beim ersten Bedarf selbst in den Agent laden. |
|||
In <code>~/.ssh/config</code> eintragen: |
|||
<pre> |
|||
Host * |
|||
AddKeysToAgent yes |
|||
IdentityFile ~/.ssh/id_ed25519 |
|||
</pre> |
|||
Die erste SSH-Verbindung fragt dann einmal nach der Passphrase und |
|||
übergibt den entsperrten Schlüssel an den Agent; weitere |
|||
Verbindungen nutzen die gespeicherte Identität ohne Prompt. |
|||
=== Windows === |
|||
Windows 10+ bringt das native OpenSSH inklusive Agent-Dienst mit. |
|||
Einmalige Einrichtung: |
|||
# '''Dienste''' (<code>services.msc</code>) als Administrator öffnen. |
|||
# '''OpenSSH Authentication Agent''' suchen, Starttyp auf '''Automatisch''' setzen, '''Starten''' anklicken. |
|||
# In PowerShell: <code>ssh-add $HOME\.ssh\id_ed25519</code>. |
|||
# Prüfen: <code>ssh-add -l</code>. |
|||
Der Windows-OpenSSH-Agent lauscht auf einer Named Pipe |
|||
(<code>\\.\pipe\openssh-ssh-agent</code>), nicht auf einem |
|||
Unix-Socket. ST/X unterstützt beide Transporte, jedoch setzt das |
|||
Windows-ssh-add <code>SSH_AUTH_SOCK</code> '''nicht''' selbst. |
|||
Daher einmalig systemweit setzen: |
|||
# {{Key|Win}} drücken → "Umgebungsvariablen" → „Systemumgebungs- variablen bearbeiten". |
|||
# '''Umgebungsvariablen''' → unter '''Benutzervariablen''', '''Neu''' klicken. |
|||
# Name: <code>SSH_AUTH_SOCK</code> |
|||
# Wert: <code>\\.\pipe\openssh-ssh-agent</code> |
|||
# Ab- und wieder anmelden (oder stx neu starten), damit die neue Umgebung übernommen wird. |
|||
==== PowerShell-Schnelleinrichtung ==== |
|||
Derselbe Aufbau aus einer '''Administrator-PowerShell''' heraus, |
|||
z.B. für Skripte oder unbeaufsichtigte Bereitstellung: |
|||
<pre> |
|||
# Agent jetzt und bei jedem Neustart starten (permanent). |
|||
Set-Service -Name ssh-agent -StartupType Automatic |
|||
Start-Service ssh-agent |
|||
# SSH_AUTH_SOCK dauerhaft für den Benutzer setzen (übersteht Reboots). |
|||
[Environment]::SetEnvironmentVariable( |
|||
'SSH_AUTH_SOCK', |
|||
'\\.\pipe\openssh-ssh-agent', |
|||
'User') |
|||
# Schlüssel laden (fragt nach Passphrase, falls die Datei verschlüsselt ist). |
|||
ssh-add $HOME\.ssh\id_ed25519 |
|||
</pre> |
|||
Für einen einmaligen Agent-Start ohne dauerhafte Aktivierung |
|||
(z.B. Einzelsitzung) die <code>Set-Service</code>-Zeile weglassen |
|||
und nur <code>Start-Service ssh-agent</code> ausführen. Die |
|||
env-var-Zeile lässt sich ebenfalls weglassen, wenn |
|||
<code>SSH_AUTH_SOCK</code> nur in der aktuellen Shell gebraucht |
|||
wird — dann statt der <code>[Environment]</code>-Variante |
|||
<code>$env:SSH_AUTH_SOCK = '...'</code> verwenden. |
|||
Auf stark abgespeckten Windows-Installationen ist der |
|||
ssh-agent-Dienst eventuell nicht vorhanden. Einmalig nachrüsten |
|||
über '''Einstellungen → Apps → Optionale Features → OpenSSH- |
|||
Client'''. |
|||
Alternative Agenten: |
|||
* '''PuTTY pageant''' — eigenes Protokoll; von ST/X's |
|||
<code>SSH::Agent</code> '''nicht''' unterstützt. Schlüssel zu |
|||
OpenSSH migrieren. |
|||
* '''Git für Windows ssh-agent''' — funktioniert; |
|||
<code>SSH_AUTH_SOCK</code> auf den dort veröffentlichten Socket |
|||
zeigen lassen. |
|||
* '''WSL 2''' — ein ST/X innerhalb der WSL sieht den WSL-eigenen Agent normal; ein ST/X auf der Windows-Seite nicht. Eine Brücke per <code>npiperelay</code> + <code>socat</code> ist möglich. |
|||
Prüfung über die Settings-Seite |
|||
('''Extras → Settings → Plugins → Remote Access — SSH Keys''') — |
|||
die Anzeige dort meldet, ob das laufende Image den Agent sieht. |
|||
==== Schlüssel automatisch beim ersten Einsatz laden ==== |
|||
Windows-OpenSSH speichert agent-geladene Schlüssel '''nicht''' |
|||
über Agent-Neustarts hinweg. Um nicht nach jedem Reboot manuell |
|||
<code>ssh-add</code> aufrufen zu müssen, dieselbe Lazy-Load- |
|||
Konfiguration in <code>%USERPROFILE%\.ssh\config</code> |
|||
eintragen: |
|||
<pre> |
|||
Host * |
|||
AddKeysToAgent yes |
|||
IdentityFile ~/.ssh/id_ed25519 |
|||
</pre> |
|||
OpenSSH lädt den Schlüssel dann beim ersten Einsatz in den Agent |
|||
(fragt einmal nach der Passphrase) und nutzt ihn für die übrige |
|||
Sitzung weiter. |
|||
== Passwort-Authentifizierung == |
|||
Empfohlen ist Public-Key-Authentifizierung (mit oder ohne |
|||
ssh-agent). Passwort-Authentifizierung ist als Fallback gedacht, |
|||
wenn keine Schlüssel verfügbar sind: Altsysteme, Ad-hoc-Zugriff |
|||
auf einen Testserver, Skripte gegen ein Konto, dessen Besitzer den |
|||
Public Key nicht hinterlegen möchte. Zu beachten: |
|||
* Das Klartext-Passwort liegt auf ST/X-Seite für die Lebensdauer des <code>SSH::Client</code> im Speicher — entsprechend behandeln wie jedes andere In-Memory-Geheimnis. |
|||
* Der Server entscheidet, welche Methoden er akzeptiert. Steht in <code>sshd_config</code> <code>PasswordAuthentication no</code>, kann keine Smalltalk-seitige Einstellung das überschreiben. |
|||
* Auf Drahtebene entspricht der Vorgang RFC 4252 §8: das Passwort wandert innerhalb der verschlüsselten SSH-Transportschicht, niemals im Klartext über das Netz. |
|||
=== Aus einer URL === |
|||
Sowohl die FileBrowserV2-Adressleiste als auch die Launcher-Dialoge |
|||
'''Workspace → SFTP Connection''' / '''Workspace → SSH |
|||
Terminal''' akzeptieren ein eingebettetes Passwort an der |
|||
standardmäßigen RFC-3986-Userinfo-Position: |
|||
<pre> |
|||
sftp://alice:s3cret@host.example.com/srv/data |
|||
ssh alice:s3cret@host.example.com:2222 |
|||
</pre> |
|||
Der Parser splittet am '''letzten''' <code>@</code>, sodass |
|||
Passwörter mit enthaltenem <code>@</code> dennoch korrekt geparst |
|||
werden; der erste <code>:</code> im Userinfo-Teil trennt Benutzer |
|||
und Passwort. Passwörter, die selbst ein <code>:</code> enthalten, |
|||
werden in dieser Form nicht unterstützt — dafür die |
|||
programmatische API unten verwenden. |
|||
Das Passwort wird aus der druckbaren URL entfernt: jede Stelle, die |
|||
am Ende den Dateinamen ausgibt (Statuszeile, |
|||
<code>printOn:</code>, <code>nameString</code>, die Breadcrumb-Leiste) |
|||
zeigt die credential-freie Form |
|||
<code>sftp://alice@host.example.com/...</code>. |
|||
=== Aus Code === |
|||
Zwei äquivalente Wege, einem <code>SSH::Client</code> ein Passwort |
|||
mitzugeben: |
|||
<pre> |
|||
"/ Literal -- am einfachsten, Passwort ist nur ein Ivar |
|||
client := SSH::Client newToHost:'host.example.com' port:22 user:'alice'. |
|||
client password:'s3cret'. |
|||
client connect. |
|||
</pre> |
|||
<pre> |
|||
"/ Callback -- lazy; das Passwort lebt nie auf dem Client. |
|||
"/ Praktisch für interaktive Abfrage, Keychain-Lookup oder ein |
|||
"/ Vault-gespeichertes Geheimnis, das nicht langlebig im Speicher |
|||
"/ liegen soll. |
|||
client passwordCallback:[ Dialog requestPassword:'SSH-Passwort' ]. |
|||
client connect. |
|||
</pre> |
|||
Sind beide gesetzt, gewinnt der Callback. Beide werden lazy |
|||
während <code>#connect</code> ausgewertet, nachdem die |
|||
Publickey-/Agent-Versuche abgelehnt wurden — ein |
|||
funktionierender Schlüssel schlägt also immer ein parallel |
|||
konfiguriertes Passwort. |
|||
=== Reihenfolge der Authentifizierungsversuche === |
|||
<code>SSH::Client>>authenticate</code> geht jedes verfügbare |
|||
Credential der Reihe nach durch und kehrt beim ersten zurück, das |
|||
der Server akzeptiert: |
|||
# ssh-agent-Identitäten, sofern <code>#useAgent</code> aufgerufen wurde und der Agent Schlüssel geladen hat. |
|||
# ed25519-Privatschlüssel-Seed, sofern <code>#privateKeyFromFile:</code> einen geladen hat. |
|||
# RSA-Privatschlüssel. |
|||
# ECDSA-Privatschlüssel. |
|||
# Passwort, sofern <code>#password:</code> / <code>#passwordCallback:</code> gesetzt ist '''und''' der Server <code>password</code> in seiner USERAUTH_FAILURE-Methodenliste weiterhin anbietet. |
|||
Jeder Schritt wird übersprungen, wenn die letzte |
|||
<code>USERAUTH_FAILURE</code>-Antwort des Servers die jeweilige |
|||
Methode aus der erlaubten Liste gestrichen hat — auf |
|||
<code>publickey</code> wird also nicht weiter herumgehämmert, |
|||
sobald der Server damit aufhört. Der Passwortversuch läuft nur, |
|||
wenn der Server <code>password</code> noch verlangt; ein falsch |
|||
konfiguriertes Passwort gegen einen reinen Schlüssel-Server erzeugt |
|||
also einen sauberen <code>SSH::AuthenticationError</code> ohne |
|||
zusätzlichen nutzlosen Roundtrip. |
|||
== Konfiguration == |
|||
Alle Stellschrauben sind klassenseitig auf |
|||
<code>SSH::SftpFilename</code> erreichbar: |
|||
{| class="wikitable" |
|||
! Accessor !! Voreinstellung !! Steuert |
|||
|- |
|||
| <code>#idleEvictionSeconds:</code> || 240 (4 Min) || Wie lange |
|||
eine gepoolte Verbindung im Leerlauf liegen darf, bevor sie beim |
|||
nächsten Zugriff proaktiv geschlossen und neu geöffnet wird. |
|||
Liegt knapp unter dem typischen |
|||
<code>ClientAliveInterval × ClientAliveCountMax</code> des sshd, |
|||
damit wir uns recyceln, bevor der Server uns mit TCP-RESET |
|||
trennt. <code>nil</code> setzt auf Voreinstellung zurück. |
|||
|- |
|||
| <code>#attrsCacheTtlSeconds:</code> || 5 || Maximales Alter (s) |
|||
eines gecachten STAT, bevor <code>#ensureAttrs</code> neu am |
|||
Server fragt. Eltern-listDir stempelt ohnehin frische Attribute |
|||
auf alle Kinder, daher zahlt das Navigieren im offenen |
|||
Verzeichnis das TTL nicht. <code>0</code> schaltet den Cache |
|||
ab. |
|||
|- |
|||
| <code>#closeAllConnections</code> || (Aktion) || Reißt jede |
|||
gepoolte Verbindung ab. Nützlich nach einem bekannt schlechten |
|||
Netzereignis, vor einem bewussten Identitätswechsel oder zum |
|||
sauberen Image-Shutdown. |
|||
|} |
|||
== Diagnose == |
|||
=== SemaphoreMonitor === |
|||
<code>SemaphoreMonitor</code> über das Untermenü „Status" des |
|||
Launchers öffnen. Der pro-Host-SFTP-Mutex erscheint als |
|||
<code>SFTP/<user@host:port></code>, der pool-weite Mutex als |
|||
<code>SFTP/pool</code>. Per Rechtsklick: |
|||
* '''Copy Waiters Stack to Clipboard''' — schreibt den Walkback des letzten Eigners samt aller Waiter als Text in die Zwischenablage. Unverzichtbar, wenn ein Prozess in |
|||
<code>readWait</code> innerhalb von |
|||
<code>withSftpClientDo:</code> klemmt. |
|||
* '''Copy List to Clipboard''' — die ganze Tabelle, ideal für eine E-Mail-Diagnose. |
|||
* '''Detect Deadlocks''' — DFS über den Wait-for-Graph, meldet Zyklen. |
|||
=== Logger === |
|||
Interessante Ereignisse werden über <code>Logger</code> geloggt: |
|||
* <code>warning:</code> bei automatischem Reconnect nach toter Verbindung. |
|||
* <code>warning:</code> bei Idle-Verdrängung eines Pool-Eintrags. |
|||
* <code>warning:</code> wenn eine SSH-Schlüsseldatei nicht geparst werden konnte — die Datei wird übersprungen. |
|||
== Einschränkungen == |
|||
* '''Nur SFTP v3.''' Kein SETSTAT (kein entferntes chmod / chown / utime), kein SSH_FXP_READLINK exponiert (<code>#isSymbolicLink</code> liefert immer <code>false</code>, |
|||
<code>#linkInfo</code> die normale stat-Info). Einige |
|||
SFTPv5+-Annehmlichkeiten werden dennoch über OpenSSH-spezifische |
|||
SSH_FXP_EXTENDED-Aufrufe nutzbar — siehe |
|||
[[#OpenSSH-SFTP-Erweiterungen]] weiter unten. |
|||
* '''Serialisierung pro Host.''' Zwei gleichzeitige Operationen am selben Host stehen am Host-Mutex an. Siehe [[#Ausblick]]. |
|||
* '''<code>#renameTo:</code>-Fallback hat ein TOCTOU-Fenster.''' Bei Servern, die <code>posix-rename@openssh.com</code> ankündigen (jedes moderne OpenSSH tut das), ist das Überschreiben atomar. Beim seltenen Server, der das nicht tut, wird auf Delete-dann-Rename ausgewichen und ein anderer Prozess kann sich dazwischenschieben. |
|||
* '''<code>#isNonEmptyDirectory</code> ist eine Heuristik.''' Liefert immer <code>#isDirectory</code> (die genaue Antwort würde drei Roundtrips pro Verzeichnis-Symbol kosten, was das ursprüngliche Baum-Ausklappen unerträglich gebremst hatte). |
|||
== Implementierungsdetails == |
|||
Für Leser, die die Architektur verstehen wollen. Fünf Klassen, |
|||
von oben nach unten: |
|||
{| class="wikitable" |
|||
! Klasse !! Aufgabe |
|||
|- |
|||
| <code>SSH::SftpFilename</code> || Filename-Unterklasse, die |
|||
öffentliche API. Bildet <code>sftp://...</code>-URLs auf |
|||
entfernte Dateien ab und stellt <code>directoryContents</code>, |
|||
<code>readingFileDo:</code>, <code>renameTo:</code> usw. bereit. |
|||
|- |
|||
| <code>SSH::SftpClient</code> || SFTP-v3-Protokoll |
|||
(Request/Response-Codec, listDir, stat, open, read, write, mkdir). |
|||
Wird von SftpFilename angesteuert. |
|||
|- |
|||
| <code>SSH::Channel</code> || SSH-Kanal-Multiplexer (CHANNEL_OPEN, |
|||
DATA, EOF, CLOSE, WINDOW_ADJUST). Eine logische Sitzung pro |
|||
Channel-Instanz. |
|||
|- |
|||
| <code>SSH::Client</code> || High-Level-SSH-Client: öffnet den |
|||
Transport, führt KEX, Hostschlüssel-Prüfung und userauth durch und |
|||
verteilt anschließend Kanäle. |
|||
|- |
|||
| <code>SSH::Transport</code> || Drahtschicht. Banner- und |
|||
KEXINIT-Austausch, ChaCha20-Poly1305-Paket-Framing, sendSeq / |
|||
recvSeq, Heartbeat, SSH_MSG_DISCONNECT. |
|||
|} |
|||
=== OpenSSH-SFTP-Erweiterungen === |
|||
SFTP v3 (Entwurf draft-ietf-secsh-filexfer-02) ist bewusst |
|||
minimal gehalten. OpenSSH bringt einen offenen |
|||
Erweiterungsmechanismus mit: der Server listet im |
|||
<code>SSH_FXP_VERSION</code>-Reply die Erweiterungsnamen auf, die |
|||
er versteht, und der Client ruft sie über |
|||
<code>SSH_FXP_EXTENDED(200)</code>-Pakete mit dem |
|||
Erweiterungsnamen als erstem String auf. Jede Erweiterung wird |
|||
über <code>SSH::SftpClient>>supportsExtension:</code> |
|||
feature-detektiert; Aufrufer fallen zurück, wenn der Server sie |
|||
nicht ankündigt. |
|||
Der Stack nutzt heute vier OpenSSH-Erweiterungen: |
|||
* <code>posix-rename@openssh.com</code> — atomares rename-mit-Überschreiben. Wird automatisch von |
|||
<code>SftpFilename>>renameTo:</code> aufgegriffen; die |
|||
Delete-dann-Rename-Fallback-Variante kommt nur bei Servern zum |
|||
Einsatz, die die Erweiterung nicht haben. |
|||
* <code>hardlink@openssh.com</code> — Erzeugt einen POSIX-Hardlink. Verfügbar als <code>SftpFilename>>createHardLinkAs:</code>. |
|||
* <code>statvfs@openssh.com</code> — POSIX- |
|||
<code>statvfs(3)</code>-typische Dateisystem-Statistik. |
|||
Verfügbar als <code>SftpFilename>>fileSystemInfo</code>; |
|||
das Ergebnis ist form-kompatibel zu |
|||
<code>OperatingSystem getDiskInfoOf:</code>, sodass Aufrufer |
|||
lokale und entfernte Pfade einheitlich behandeln können. |
|||
Treibt den Menü-Eintrag '''Tools → Filesystem Info...''' an, |
|||
der am Anfang dieser Seite beschrieben ist. |
|||
* <code>fsync@openssh.com</code> — schreibt den serverseitigen Schreibpuffer eines geöffneten Handles auf Platte. Liegt als |
|||
<code>SftpClient>>fsyncHandle:</code> bereit; noch nicht |
|||
in eine "Durable-Write"-API auf Filename-Ebene eingebunden. |
|||
Die verbleibenden OpenSSH-Erweiterungen |
|||
(<code>lsetstat@openssh.com</code>, <code>fstatvfs@openssh.com</code>) |
|||
werden in der angekündigten Liste erkannt, aber nicht auf |
|||
Filename-Ebene gekapselt — es gibt dafür noch keinen |
|||
Filename-seitigen Aufrufer. |
|||
=== Verbindungs-Pooling === |
|||
Alle <code>SftpFilename</code>-Instanzen, die auf dasselbe Tripel |
|||
<code>user@host:port</code> zeigen, teilen sich einen |
|||
<code>SSH::Client</code> samt einem <code>SSH::SftpClient</code>. |
|||
Der Pool ist klassenseitig und wird von einem einzigen |
|||
<code>ConnectionPoolMutex</code> bewacht: |
|||
* '''Lazy-Aufbau''' — TCP + KEX + userauth + SFTP-INIT laufen erst beim ersten SFTP-Aufruf, nicht in <code>forUrl:</code>. |
|||
* '''Serialisierung pro Host''' — SFTP-Anfragen an einen bestimmten Host werden durch einen <code>RecursionLock</code> mit dem Namen <code>SFTP/<user@host:port></code> serialisiert (sichtbar im SemaphoreMonitor). |
|||
* '''Idle-Verdrängung''' — ein Pool-Eintrag, der länger als |
|||
<code>idleEvictionSeconds</code> ungenutzt liegt, wird beim |
|||
nächsten Zugriff proaktiv geschlossen und neu geöffnet. |
|||
* '''Automatischer Reconnect''' — ein Fehler auf Transportebene (Broken Pipe, EOF, MNU auf nil-Socket) verdrängt den Pool-Eintrag, öffnet einen frischen Client und wiederholt die Anfrage '''einmal'''. Anwendungsfehler aus SFTP-STATUS-Antworten werden sofort durchgereicht. |
|||
== Ausblick == |
|||
Geplant, aber noch nicht umgesetzt: |
|||
* '''Multi-Channel-Parallelität pro Host''' — aktuell bedeutet eine TCP- plus eine SFTP-Verbindung pro Host, dass N gleichzeitige Anfragen serialisieren. Pipelining über mehrere SshClients im Pool (bevorzugt) oder ein transport-seitiger Reader-Prozess, der eingehende Pakete in Pro-Kanal-Postfächer demultiplext, würde es dem Baum-Panel erlauben, weiter aufzulisten, während das Inhalts-Panel eine große Datei liest. |
|||
* '''Genaues <code>#isNonEmptyDirectory</code>''' via OPEN_DIR + READ_DIR (nur erstes Batch) + CLOSE — drei Roundtrips pro Sondierung; lohnt erst, wenn der SftpClient Anfragen pipelinen kann. |
|||
* '''SFTP-v5/v6-Aushandlung''' für erweiterte Attribute und FTP-artige Kanonisierung. (Atomares Überschreibungs-rename ist bereits über die OpenSSH-Erweiterung |
|||
<code>posix-rename@openssh.com</code> abgedeckt; siehe |
|||
[[#OpenSSH-SFTP-Erweiterungen]].) |
|||
= Kommando-Shell = |
|||
Lokale Kommando-Shell auf dieser expecco-Maschine. Typische |
|||
Anwendungen: lokale Kommandozeile, lokales Hilfsprogramm, |
|||
Brücke zwischen entferntem Workflow und lokalem Tool. |
|||
Das RemoteAccess-Plugin stellt bereit: |
|||
* '''CmdShell - Open''' |
|||
* '''CmdShell - Close''' |
|||
Keine Zugangsdaten, kein Netzwerk — läuft als der Benutzer des |
|||
expecco-Prozesses. Ausgaben gehen in das expecco-Log. |
|||
= Telnet = |
|||
[[File:Warning.svg|24px|Warnung]] '''Telnet ist ein veraltetes |
|||
Protokoll ohne Verschlüsselung.''' Passwörter werden im Klartext |
|||
über die Leitung übertragen; jeder im Netzpfad kann sie lesen. |
|||
Telnet NUR einsetzen, wenn die Gegenstelle keine Alternative |
|||
bietet (typisch: alte Industriesteuerungen, Laborgeräte, |
|||
eingebettete Messgeräte ohne SSH-Stack). Für alles andere |
|||
[[#SSH und SFTP]] verwenden. |
|||
Das expecco-Plugin stellt bereit: |
|||
* '''Telnet - Open Remote Connection With Login''' |
|||
* '''Telnet - Execute Remote Command''' |
|||
* '''Example - Remote Device Control via Telnet''' (interne Demo) |
|||
Das Telnet-Protokoll (RFC 854) ist ein bidirektionaler |
|||
8-Bit-Byte-Strom über TCP, mit In-Band-Steuersequenzen für |
|||
Terminal-Optionen. Verbindungsaufbau zum Ziel-Host:Port; nach |
|||
optionalem In-Band-Login können beide Seiten Daten senden. |
|||
= Siehe auch = |
|||
* [[SSH Client|SSH::Client]] — die SSH-Schicht (exec, TTY, Agent-Weiterleitung, ProxyJump). |
|||
* [[FileBrowserV2]] — die Haupt-UI dieses Stacks. |
|||
* [[ClaudeCode plugin|Claude Code]] — nutzt denselben SSH-Stack als HTTPS-Transport. |
|||
* [[Wikipedia:Secure Shell|RFC 4251 (SSH-2 Architecture)]] |
|||
* [[Wikipedia:Telnet|RFC 854 (Telnet Protocol)]] |
|||
[[Category:Plugins]] |
|||
[[Category:Netz]] |
|||
[[Category:SSH]] |
|||
Aktuelle Version vom 8. Juni 2026, 14:26 Uhr
| Language: | Deutsch • English |
|---|
Fernzugriff bezeichnet die Möglichkeit, einen entfernten Rechner oder ein entferntes Netzwerk aus diesem expecco-Image heraus zu bedienen — Shells zu öffnen, Befehle abzusetzen, Dateien zu verschieben oder ein Testgerät anzusteuern. Drei Protokoll-Familien sind unterstützt, in absteigender Empfehlungsreihenfolge:
- SSH und SFTP (empfohlen) — verschlüsselte Shell und sichere Dateiübertragung über einen SSH-2-Tunnel. Reine Smalltalk-Implementierung in
exept:libcrypt/ssh; keine externe Abhängigkeit von OpenSSL oder libssh. Für alles mit Zugangsdaten oder sensiblen Nutzdaten. - Lokale Kommando-Shell — fork + exec auf der lokalen Maschine. Für die Anbindung lokaler Werkzeuge und für die lokale Seite eines hybriden Workflows.
- Telnet (veraltet) — Klartext-Terminalsitzung. Keine Verschlüsselung, Passwörter im Klartext auf der Leitung. Nur einsetzen, wenn die Gegenstelle keine Alternative bietet.
SSH und SFTP
Der SSH-Stack deckt das vollständige SSH-2-Protokoll ab (RFC 4251–4254, RFC 5656, RFC 8709, RFC 8731) inklusive der chacha20-poly1305-Transportchiffrierung von OpenSSH sowie das SFTP-v3-Subsystem (draft-ietf-secsh-filexfer-02). Zwei Schichten:
SSH::Client— programmatischer SSH-Zugriff (entferntesexec, TTY-Shell, Agent-Weiterleitung, ProxyJump-Bastion).SSH::SftpFilename— eine
Filename-Unterklasse, die es dem restlichen ST/X
erlaubt, einen entfernten SFTP-Pfad zu behandeln wie eine lokale
Datei.
Die folgenden Abschnitte sind nutzeraufgaben-zuerst aufgebaut: zuerst das, was der Anwender sieht und tut, darunter die expecco-Bibliotheks-Anbindung, ganz unten Implementierungsdetails für Interessierte.
Aus dem FileBrowserV2
Im Adress-Dropdown eine sftp://-URL einfügen. Der
Browser-Tab füllt sich wie bei einem lokalen Pfad.
Baum-Ausklappen, Spaltensortierung (Name / Größe / mtime),
Vorschau und Doppelklick zum Öffnen im Editor verhalten sich
normal. Der erste Klick auf einen Host dauert ~200–500 ms
(TCP + KEX + Auth); folgende Klicks nutzen die gepoolte
Verbindung weiter.
URL-Syntax:
sftp://[user[:password]@]host[:port]/remote/path
Fehlt user, wird der lokale Login-Name verwendet, Port
ist standardmäßig 22, Pfad standardmäßig /. Das
optionale :password-Segment ist das RFC-3986-Userinfo-Passwort
— wann es angebracht ist und welche Sicherheitsabwägungen
damit verbunden sind, beschreibt #Passwort-Authentifizierung.
Wenn vorhanden, dient es als USERAUTH-Fallback nach den üblichen
Publickey-/Agent-Versuchen und wird niemals wieder von der
druckbaren URL-Form ausgegeben — das Protokollieren des
Dateinamens leakt also nicht das Credential.
Die Schaltfläche Refresh in der Symbolleiste (Pfeil-Kreis-Symbol zwischen Forward und DirectoryUp) liest Baum und Inhalts-Panel auf Anforderung neu ein. Funktioniert einheitlich für lokale und SFTP-Pfade; bei SFTP wird zusätzlich der per-Datei-STAT-Cache geleert, sodass Änderungen, die direkt auf der Gegenseite gemacht wurden, sofort sichtbar werden — ohne auf den Ablauf der 5-Sekunden-Cache-TTL zu warten.
Der kleine Pfeil neben dem Refresh-Symbol öffnet ein Aufklappmenü mit einem einzelnen Kontrollkästchen, Automatic Refresh, das den Hintergrund-Task an- bzw. abschaltet, der alle expandierten Baumeinträge auf externe Änderungen prüft. Die Vorgabe richtet sich nach der aktuellen Wurzel:
- Lokales Dateisystem → an (10-Sekunden-Zyklus, entspricht dem bisherigen Verhalten).
- SFTP → aus. Jeder Zyklus kostet einen STAT-Roundtrip pro Kind — für eine Handvoll lokaler Verzeichnisse harmlos, über das Netz schmerzhaft. Bei Bedarf manuell auf Refresh klicken, um Änderungen zu sehen.
Beim Wechsel zwischen lokalen und SFTP-Wurzeln wird der Schalter automatisch umgelegt — aber nur, sofern man ihn für die vorherige Wurzel nicht selbst verstellt hat. Eine explizite Benutzerwahl bleibt über Navigationen hinweg erhalten.
Das Menü Tools im FileBrowserV2 bietet vier Aktionen — die drei SSH-spezifischen sind nur bei geladener SSH-Bibliothek sichtbar:
- Generate SSH Key Pair... — öffnet den Schlüsselerzeugungs-Dialog, siehe #Einen SSH-Schlüssel erzeugen unten.
- SSH Connect... — öffnet ein interaktives VT100-Terminal zu einem entfernten Host.
- SFTP Connect... — navigiert diesen Browser-Tab über SFTP auf ein entferntes Dateisystem.
- Filesystem Info... — zeigt Größe, freien Platz und Belegung des Dateisystems, das das aktuell angezeigte Verzeichnis enthält. Funktioniert einheitlich für lokale und SFTP-Pfade; bei SFTP setzt der Aufruf voraus, daß der Server die Erweiterung
statvfs@openssh.com ankündigt (jedes moderne OpenSSH
tut das). Größen werden in IEC-Binäreinheiten ausgegeben (MiB,
GiB, TiB) — gewählt wird die größte Einheit, die einen Wert ≥ 1
liefert, damit ein TB-großes Volume als X TiB statt
10240 GiB erscheint.
Aus dem Launcher
Das Untermenü Workspace im Launcher enthält zwei eigenständige Einträge (nur sichtbar bei geladenem SSH-Paket):
- SSH Terminal — fragt nach einem Ziel der Form
user[:password]@host[:port]und öffnet ein VT100-Terminal als eigenständiges Fenster. Das ist das Launcher-Pendant zum FileBrowserV2-Eintrag Tools → SSH Connect.... - SFTP Connection — fragt nach einem SFTP-Ziel (gleiche URL-Grammatik wie in der FileBrowserV2-Adresszeile, siehe #Aus dem FileBrowserV2) und öffnet einen frischen FileBrowserV2, der bereits dorthin navigiert ist.
Beide Einträge unterstützen die in #Passwort-Authentifizierung beschriebene URL-Form mit eingebettetem Passwort.
Aus expecco-Aktionen
Das Expecco-RemoteAccess-Plugin (Expecco::RemoteAccessImportPlugin) stellt folgende Testaktionen in der expecco-Aktionspalette bereit:
- CmdShell - Open SSH Remote Connection — öffnet eine SSH-Sitzung über das plattformeigene
ssh-Binary (PuTTYsplinkunter Windows). - CmdShell - Open SSH Remote Connection and PublicKey — dasselbe, jedoch mit expliziter Public-Key-Authentifizierung.
Voraussetzung: ein eingerichtetes Schlüsselpaar (privater
Schlüssel auf dieser Maschine, öffentlicher Teil in der
~/.ssh/authorized_keys des Zielhosts). Schlüssel
erzeugen entweder über den Dialog unten oder über
ssh-keygen.
Das Plugin fügt zusätzlich eine Settings-Seite hinzu: Extras → Settings → Plugins → Remote Access — SSH Keys mit einer einzelnen Schaltfläche Generate SSH Key Pair..., die denselben Dialog öffnet.
Einen SSH-Schlüssel erzeugen
Der Dialog (FileBrowserV2 / Settings-Seite)
Der Dialog fragt alle Parameter in einem Formular ab:
- Comment — wird in den erzeugten Schlüssel eingebettet (Voreinstellung
stx@<hostname>). - Storage:
- Save to disk file only — schreibt
~/.ssh/id_ed25519_stx (oder wohin man will) samt
zugehöriger .pub-Datei daneben.
- Save to disk AND load into ssh-agent — schreibt die Datei UND übergibt den Schlüssel dem laufenden ssh-agent.
- Load into ssh-agent only — der Schlüssel lebt nur im Speicher des Agents; nach Agent-Neustart ist er verloren.
- Private key file — vollständiger Pfad; ausgegraut im Agent-only-Modus.
- Passphrase / Confirm — leer lässt die On-Disk-Datei unverschlüsselt (Agent-only-Modus ignoriert die Passphrase, da das OpenSSH-Agent-Wire-Protokoll nur den entschlüsselten Schlüssel transportiert).
Bei Generate wird die Public-Key-Zeile (dieselbe
ssh-ed25519 AAAA... comment-Zeichenfolge, die
ssh-keygen ausgibt) in die System-Zwischenablage kopiert — zum
direkten Einfügen in die ~/.ssh/authorized_keys des
Zielhosts.
Aus einem Workspace
Für Headless-Deployments, Sandbox-Builds oder Skripte stellt
SSH::Client einen reinen Smalltalk-Schlüsselgenerator
bereit, dessen Ausgabe bit-kompatibel zu
ssh-keygen -t ed25519 ist:
| seed comment priv |
seed := SSH::Client generateEd25519Seed.
comment := 'stx@', OperatingSystem getHostName.
"/ Passphrase-verschlüsselt auf Platte speichern"
priv := (Filename homeDirectory / '.ssh' / 'id_ed25519_stx') pathName.
SSH::Client
saveOpenSshEd25519Seed:seed
toFile:priv
comment:comment
passphrase:'choose-something-long'.
"/ UND in den laufenden Agent laden"
SSH::Client addEd25519SeedToAgent:seed comment:comment.
"/ Public-Key-Zeile zum Einfügen in authorized_keys ausgeben"
Transcript showCR:
(SSH::Client authorizedKeysLineForEd25519Seed:seed comment:comment).
Die so erzeugten Schlüssel sind mit den OpenSSH-Werkzeugen voll
interoperabel (ssh-keygen -y -f ... rekonstruiert den
öffentlichen Schlüssel, ssh-keygen -p -f ... ändert
die Passphrase usw.).
Mit den Shell-Werkzeugen
Der klassische Weg funktioniert weiterhin:
ssh-keygen -t ed25519 -C "stx@your.host" ssh-copy-id user@remotehost ssh-add ~/.ssh/id_ed25519
ssh-agent vorbereiten
Der Weg über den Agent ist dem direkten Lesen von Schlüsseldateien deutlich vorzuziehen: er hält verschlüsselte private Schlüssel einmal pro Sitzung entsperrt und kann Identitäten verwalten (hardware-tokengestützte Schlüssel, KeePassXC-Einträge), die ST/X nie direkt sehen soll.
ST/X erkennt den Agent-Pfad automatisch, sobald
$SSH_AUTH_SOCK zum Zeitpunkt des Starts von stx
in der Prozessumgebung gesetzt ist. Eine spätere Zuweisung aus
einem Workspace nützt nichts.
Linux / macOS
Die meisten Desktop-Distributionen starten einen Agent automatisch beim Login (gnome-keyring unter GNOME, ssh-agent.service unter systemd, KWallet unter KDE). Prüfen im Terminal:
echo $SSH_AUTH_SOCK # /run/user/1000/keyring/ssh oder ähnlich ssh-add -l # listet geladene Identitäten ssh-add ~/.ssh/id_ed25519 # eigene laden, falls nicht da
Läuft gar kein Agent, dieses Snippet in die Shell-rc-Datei aufnehmen:
# ~/.bashrc oder ~/.zshrc
if [ -z "$SSH_AUTH_SOCK" ]; then
eval "$(ssh-agent -s)" > /dev/null
fi
ST/X muss aus einer Shell gestartet werden, die diese rc bereits
gelesen hat — ein Desktop-Launcher aus dem Dateimanager erbt die
Variable nicht. Empfehlung: ein kleines Wrapper-Skript unter
~/.local/bin/, das die rc sourcet und dann stx
startet.
Die Settings-Seite (Extras → Settings → Plugins → Remote Access — SSH Keys) zeigt an, ob das laufende Image einen Agent sieht.
Permanente Einrichtung via systemd
Für einen wirklich sitzungsübergreifenden Agent (überlebt Desktop-
Abmeldung, kommt beim nächsten Login wieder hoch) die bei den
meisten Distros mit dem Paket openssh-clients
ausgelieferte Per-User-systemd-Unit aktivieren:
systemctl --user enable --now ssh-agent.service
Anschließend SSH_AUTH_SOCK in der Shell-rc auf den
User-Service-Socket zeigen lassen (ersetzt das
eval $(ssh-agent -s)-Snippet oben):
export SSH_AUTH_SOCK="${XDG_RUNTIME_DIR}/ssh-agent.socket"
Schlüssel automatisch beim ersten Einsatz laden
Um den manuellen ssh-add-Schritt zu sparen, kann
OpenSSH Schlüssel beim ersten Bedarf selbst in den Agent laden.
In ~/.ssh/config eintragen:
Host *
AddKeysToAgent yes
IdentityFile ~/.ssh/id_ed25519
Die erste SSH-Verbindung fragt dann einmal nach der Passphrase und übergibt den entsperrten Schlüssel an den Agent; weitere Verbindungen nutzen die gespeicherte Identität ohne Prompt.
Windows
Windows 10+ bringt das native OpenSSH inklusive Agent-Dienst mit. Einmalige Einrichtung:
- Dienste (
services.msc) als Administrator öffnen. - OpenSSH Authentication Agent suchen, Starttyp auf Automatisch setzen, Starten anklicken.
- In PowerShell:
ssh-add $HOME\.ssh\id_ed25519. - Prüfen:
ssh-add -l.
Der Windows-OpenSSH-Agent lauscht auf einer Named Pipe
(\\.\pipe\openssh-ssh-agent), nicht auf einem
Unix-Socket. ST/X unterstützt beide Transporte, jedoch setzt das
Windows-ssh-add SSH_AUTH_SOCK nicht selbst.
Daher einmalig systemweit setzen:
- Vorlage:Key drücken → "Umgebungsvariablen" → „Systemumgebungs- variablen bearbeiten".
- Umgebungsvariablen → unter Benutzervariablen, Neu klicken.
- Name:
SSH_AUTH_SOCK - Wert:
\\.\pipe\openssh-ssh-agent - Ab- und wieder anmelden (oder stx neu starten), damit die neue Umgebung übernommen wird.
PowerShell-Schnelleinrichtung
Derselbe Aufbau aus einer Administrator-PowerShell heraus, z.B. für Skripte oder unbeaufsichtigte Bereitstellung:
# Agent jetzt und bei jedem Neustart starten (permanent).
Set-Service -Name ssh-agent -StartupType Automatic
Start-Service ssh-agent
# SSH_AUTH_SOCK dauerhaft für den Benutzer setzen (übersteht Reboots).
[Environment]::SetEnvironmentVariable(
'SSH_AUTH_SOCK',
'\\.\pipe\openssh-ssh-agent',
'User')
# Schlüssel laden (fragt nach Passphrase, falls die Datei verschlüsselt ist).
ssh-add $HOME\.ssh\id_ed25519
Für einen einmaligen Agent-Start ohne dauerhafte Aktivierung
(z.B. Einzelsitzung) die Set-Service-Zeile weglassen
und nur Start-Service ssh-agent ausführen. Die
env-var-Zeile lässt sich ebenfalls weglassen, wenn
SSH_AUTH_SOCK nur in der aktuellen Shell gebraucht
wird — dann statt der [Environment]-Variante
$env:SSH_AUTH_SOCK = '...' verwenden.
Auf stark abgespeckten Windows-Installationen ist der ssh-agent-Dienst eventuell nicht vorhanden. Einmalig nachrüsten über Einstellungen → Apps → Optionale Features → OpenSSH- Client.
Alternative Agenten:
- PuTTY pageant — eigenes Protokoll; von ST/X's
SSH::Agent nicht unterstützt. Schlüssel zu
OpenSSH migrieren.
- Git für Windows ssh-agent — funktioniert;
SSH_AUTH_SOCK auf den dort veröffentlichten Socket
zeigen lassen.
- WSL 2 — ein ST/X innerhalb der WSL sieht den WSL-eigenen Agent normal; ein ST/X auf der Windows-Seite nicht. Eine Brücke per
npiperelay+socatist möglich.
Prüfung über die Settings-Seite (Extras → Settings → Plugins → Remote Access — SSH Keys) — die Anzeige dort meldet, ob das laufende Image den Agent sieht.
Schlüssel automatisch beim ersten Einsatz laden
Windows-OpenSSH speichert agent-geladene Schlüssel nicht
über Agent-Neustarts hinweg. Um nicht nach jedem Reboot manuell
ssh-add aufrufen zu müssen, dieselbe Lazy-Load-
Konfiguration in %USERPROFILE%\.ssh\config
eintragen:
Host *
AddKeysToAgent yes
IdentityFile ~/.ssh/id_ed25519
OpenSSH lädt den Schlüssel dann beim ersten Einsatz in den Agent (fragt einmal nach der Passphrase) und nutzt ihn für die übrige Sitzung weiter.
Passwort-Authentifizierung
Empfohlen ist Public-Key-Authentifizierung (mit oder ohne ssh-agent). Passwort-Authentifizierung ist als Fallback gedacht, wenn keine Schlüssel verfügbar sind: Altsysteme, Ad-hoc-Zugriff auf einen Testserver, Skripte gegen ein Konto, dessen Besitzer den Public Key nicht hinterlegen möchte. Zu beachten:
- Das Klartext-Passwort liegt auf ST/X-Seite für die Lebensdauer des
SSH::Clientim Speicher — entsprechend behandeln wie jedes andere In-Memory-Geheimnis. - Der Server entscheidet, welche Methoden er akzeptiert. Steht in
sshd_configPasswordAuthentication no, kann keine Smalltalk-seitige Einstellung das überschreiben. - Auf Drahtebene entspricht der Vorgang RFC 4252 §8: das Passwort wandert innerhalb der verschlüsselten SSH-Transportschicht, niemals im Klartext über das Netz.
Aus einer URL
Sowohl die FileBrowserV2-Adressleiste als auch die Launcher-Dialoge Workspace → SFTP Connection / Workspace → SSH Terminal akzeptieren ein eingebettetes Passwort an der standardmäßigen RFC-3986-Userinfo-Position:
sftp://alice:s3cret@host.example.com/srv/data ssh alice:s3cret@host.example.com:2222
Der Parser splittet am letzten @, sodass
Passwörter mit enthaltenem @ dennoch korrekt geparst
werden; der erste : im Userinfo-Teil trennt Benutzer
und Passwort. Passwörter, die selbst ein : enthalten,
werden in dieser Form nicht unterstützt — dafür die
programmatische API unten verwenden.
Das Passwort wird aus der druckbaren URL entfernt: jede Stelle, die
am Ende den Dateinamen ausgibt (Statuszeile,
printOn:, nameString, die Breadcrumb-Leiste)
zeigt die credential-freie Form
sftp://alice@host.example.com/....
Aus Code
Zwei äquivalente Wege, einem SSH::Client ein Passwort
mitzugeben:
"/ Literal -- am einfachsten, Passwort ist nur ein Ivar client := SSH::Client newToHost:'host.example.com' port:22 user:'alice'. client password:'s3cret'. client connect.
"/ Callback -- lazy; das Passwort lebt nie auf dem Client. "/ Praktisch für interaktive Abfrage, Keychain-Lookup oder ein "/ Vault-gespeichertes Geheimnis, das nicht langlebig im Speicher "/ liegen soll. client passwordCallback:[ Dialog requestPassword:'SSH-Passwort' ]. client connect.
Sind beide gesetzt, gewinnt der Callback. Beide werden lazy
während #connect ausgewertet, nachdem die
Publickey-/Agent-Versuche abgelehnt wurden — ein
funktionierender Schlüssel schlägt also immer ein parallel
konfiguriertes Passwort.
Reihenfolge der Authentifizierungsversuche
SSH::Client>>authenticate geht jedes verfügbare
Credential der Reihe nach durch und kehrt beim ersten zurück, das
der Server akzeptiert:
- ssh-agent-Identitäten, sofern
#useAgentaufgerufen wurde und der Agent Schlüssel geladen hat. - ed25519-Privatschlüssel-Seed, sofern
#privateKeyFromFile:einen geladen hat. - RSA-Privatschlüssel.
- ECDSA-Privatschlüssel.
- Passwort, sofern
#password:/#passwordCallback:gesetzt ist und der Serverpasswordin seiner USERAUTH_FAILURE-Methodenliste weiterhin anbietet.
Jeder Schritt wird übersprungen, wenn die letzte
USERAUTH_FAILURE-Antwort des Servers die jeweilige
Methode aus der erlaubten Liste gestrichen hat — auf
publickey wird also nicht weiter herumgehämmert,
sobald der Server damit aufhört. Der Passwortversuch läuft nur,
wenn der Server password noch verlangt; ein falsch
konfiguriertes Passwort gegen einen reinen Schlüssel-Server erzeugt
also einen sauberen SSH::AuthenticationError ohne
zusätzlichen nutzlosen Roundtrip.
Konfiguration
Alle Stellschrauben sind klassenseitig auf
SSH::SftpFilename erreichbar:
| Accessor | Voreinstellung | Steuert |
|---|---|---|
#idleEvictionSeconds: |
240 (4 Min) | Wie lange
eine gepoolte Verbindung im Leerlauf liegen darf, bevor sie beim
nächsten Zugriff proaktiv geschlossen und neu geöffnet wird.
Liegt knapp unter dem typischen
|
#attrsCacheTtlSeconds: |
5 | Maximales Alter (s)
eines gecachten STAT, bevor |
#closeAllConnections |
(Aktion) | Reißt jede
gepoolte Verbindung ab. Nützlich nach einem bekannt schlechten Netzereignis, vor einem bewussten Identitätswechsel oder zum sauberen Image-Shutdown. |
Diagnose
SemaphoreMonitor
SemaphoreMonitor über das Untermenü „Status" des
Launchers öffnen. Der pro-Host-SFTP-Mutex erscheint als
SFTP/<user@host:port>, der pool-weite Mutex als
SFTP/pool. Per Rechtsklick:
- Copy Waiters Stack to Clipboard — schreibt den Walkback des letzten Eigners samt aller Waiter als Text in die Zwischenablage. Unverzichtbar, wenn ein Prozess in
readWait innerhalb von
withSftpClientDo: klemmt.
- Copy List to Clipboard — die ganze Tabelle, ideal für eine E-Mail-Diagnose.
- Detect Deadlocks — DFS über den Wait-for-Graph, meldet Zyklen.
Logger
Interessante Ereignisse werden über Logger geloggt:
warning:bei automatischem Reconnect nach toter Verbindung.warning:bei Idle-Verdrängung eines Pool-Eintrags.warning:wenn eine SSH-Schlüsseldatei nicht geparst werden konnte — die Datei wird übersprungen.
Einschränkungen
- Nur SFTP v3. Kein SETSTAT (kein entferntes chmod / chown / utime), kein SSH_FXP_READLINK exponiert (
#isSymbolicLinkliefert immerfalse,
#linkInfo die normale stat-Info). Einige
SFTPv5+-Annehmlichkeiten werden dennoch über OpenSSH-spezifische
SSH_FXP_EXTENDED-Aufrufe nutzbar — siehe
#OpenSSH-SFTP-Erweiterungen weiter unten.
- Serialisierung pro Host. Zwei gleichzeitige Operationen am selben Host stehen am Host-Mutex an. Siehe #Ausblick.
#renameTo:-Fallback hat ein TOCTOU-Fenster. Bei Servern, dieposix-rename@openssh.comankündigen (jedes moderne OpenSSH tut das), ist das Überschreiben atomar. Beim seltenen Server, der das nicht tut, wird auf Delete-dann-Rename ausgewichen und ein anderer Prozess kann sich dazwischenschieben.#isNonEmptyDirectoryist eine Heuristik. Liefert immer#isDirectory(die genaue Antwort würde drei Roundtrips pro Verzeichnis-Symbol kosten, was das ursprüngliche Baum-Ausklappen unerträglich gebremst hatte).
Implementierungsdetails
Für Leser, die die Architektur verstehen wollen. Fünf Klassen, von oben nach unten:
| Klasse | Aufgabe |
|---|---|
SSH::SftpFilename |
Filename-Unterklasse, die
öffentliche API. Bildet |
SSH::SftpClient |
SFTP-v3-Protokoll
(Request/Response-Codec, listDir, stat, open, read, write, mkdir). Wird von SftpFilename angesteuert. |
SSH::Channel |
SSH-Kanal-Multiplexer (CHANNEL_OPEN,
DATA, EOF, CLOSE, WINDOW_ADJUST). Eine logische Sitzung pro Channel-Instanz. |
SSH::Client |
High-Level-SSH-Client: öffnet den
Transport, führt KEX, Hostschlüssel-Prüfung und userauth durch und verteilt anschließend Kanäle. |
SSH::Transport |
Drahtschicht. Banner- und
KEXINIT-Austausch, ChaCha20-Poly1305-Paket-Framing, sendSeq / recvSeq, Heartbeat, SSH_MSG_DISCONNECT. |
OpenSSH-SFTP-Erweiterungen
SFTP v3 (Entwurf draft-ietf-secsh-filexfer-02) ist bewusst
minimal gehalten. OpenSSH bringt einen offenen
Erweiterungsmechanismus mit: der Server listet im
SSH_FXP_VERSION-Reply die Erweiterungsnamen auf, die
er versteht, und der Client ruft sie über
SSH_FXP_EXTENDED(200)-Pakete mit dem
Erweiterungsnamen als erstem String auf. Jede Erweiterung wird
über SSH::SftpClient>>supportsExtension:
feature-detektiert; Aufrufer fallen zurück, wenn der Server sie
nicht ankündigt.
Der Stack nutzt heute vier OpenSSH-Erweiterungen:
posix-rename@openssh.com— atomares rename-mit-Überschreiben. Wird automatisch von
SftpFilename>>renameTo: aufgegriffen; die
Delete-dann-Rename-Fallback-Variante kommt nur bei Servern zum
Einsatz, die die Erweiterung nicht haben.
hardlink@openssh.com— Erzeugt einen POSIX-Hardlink. Verfügbar alsSftpFilename>>createHardLinkAs:.statvfs@openssh.com— POSIX-
statvfs(3)-typische Dateisystem-Statistik.
Verfügbar als SftpFilename>>fileSystemInfo;
das Ergebnis ist form-kompatibel zu
OperatingSystem getDiskInfoOf:, sodass Aufrufer
lokale und entfernte Pfade einheitlich behandeln können.
Treibt den Menü-Eintrag Tools → Filesystem Info... an,
der am Anfang dieser Seite beschrieben ist.
fsync@openssh.com— schreibt den serverseitigen Schreibpuffer eines geöffneten Handles auf Platte. Liegt als
SftpClient>>fsyncHandle: bereit; noch nicht
in eine "Durable-Write"-API auf Filename-Ebene eingebunden.
Die verbleibenden OpenSSH-Erweiterungen
(lsetstat@openssh.com, fstatvfs@openssh.com)
werden in der angekündigten Liste erkannt, aber nicht auf
Filename-Ebene gekapselt — es gibt dafür noch keinen
Filename-seitigen Aufrufer.
Verbindungs-Pooling
Alle SftpFilename-Instanzen, die auf dasselbe Tripel
user@host:port zeigen, teilen sich einen
SSH::Client samt einem SSH::SftpClient.
Der Pool ist klassenseitig und wird von einem einzigen
ConnectionPoolMutex bewacht:
- Lazy-Aufbau — TCP + KEX + userauth + SFTP-INIT laufen erst beim ersten SFTP-Aufruf, nicht in
forUrl:. - Serialisierung pro Host — SFTP-Anfragen an einen bestimmten Host werden durch einen
RecursionLockmit dem NamenSFTP/<user@host:port>serialisiert (sichtbar im SemaphoreMonitor). - Idle-Verdrängung — ein Pool-Eintrag, der länger als
idleEvictionSeconds ungenutzt liegt, wird beim
nächsten Zugriff proaktiv geschlossen und neu geöffnet.
- Automatischer Reconnect — ein Fehler auf Transportebene (Broken Pipe, EOF, MNU auf nil-Socket) verdrängt den Pool-Eintrag, öffnet einen frischen Client und wiederholt die Anfrage einmal. Anwendungsfehler aus SFTP-STATUS-Antworten werden sofort durchgereicht.
Ausblick
Geplant, aber noch nicht umgesetzt:
- Multi-Channel-Parallelität pro Host — aktuell bedeutet eine TCP- plus eine SFTP-Verbindung pro Host, dass N gleichzeitige Anfragen serialisieren. Pipelining über mehrere SshClients im Pool (bevorzugt) oder ein transport-seitiger Reader-Prozess, der eingehende Pakete in Pro-Kanal-Postfächer demultiplext, würde es dem Baum-Panel erlauben, weiter aufzulisten, während das Inhalts-Panel eine große Datei liest.
- Genaues
#isNonEmptyDirectoryvia OPEN_DIR + READ_DIR (nur erstes Batch) + CLOSE — drei Roundtrips pro Sondierung; lohnt erst, wenn der SftpClient Anfragen pipelinen kann. - SFTP-v5/v6-Aushandlung für erweiterte Attribute und FTP-artige Kanonisierung. (Atomares Überschreibungs-rename ist bereits über die OpenSSH-Erweiterung
posix-rename@openssh.com abgedeckt; siehe
#OpenSSH-SFTP-Erweiterungen.)
Kommando-Shell
Lokale Kommando-Shell auf dieser expecco-Maschine. Typische Anwendungen: lokale Kommandozeile, lokales Hilfsprogramm, Brücke zwischen entferntem Workflow und lokalem Tool.
Das RemoteAccess-Plugin stellt bereit:
- CmdShell - Open
- CmdShell - Close
Keine Zugangsdaten, kein Netzwerk — läuft als der Benutzer des expecco-Prozesses. Ausgaben gehen in das expecco-Log.
Telnet
Warnung Telnet ist ein veraltetes Protokoll ohne Verschlüsselung. Passwörter werden im Klartext über die Leitung übertragen; jeder im Netzpfad kann sie lesen. Telnet NUR einsetzen, wenn die Gegenstelle keine Alternative bietet (typisch: alte Industriesteuerungen, Laborgeräte, eingebettete Messgeräte ohne SSH-Stack). Für alles andere #SSH und SFTP verwenden.
Das expecco-Plugin stellt bereit:
- Telnet - Open Remote Connection With Login
- Telnet - Execute Remote Command
- Example - Remote Device Control via Telnet (interne Demo)
Das Telnet-Protokoll (RFC 854) ist ein bidirektionaler 8-Bit-Byte-Strom über TCP, mit In-Band-Steuersequenzen für Terminal-Optionen. Verbindungsaufbau zum Ziel-Host:Port; nach optionalem In-Band-Login können beide Seiten Daten senden.
Siehe auch
- SSH::Client — die SSH-Schicht (exec, TTY, Agent-Weiterleitung, ProxyJump).
- FileBrowserV2 — die Haupt-UI dieses Stacks.
- Claude Code — nutzt denselben SSH-Stack als HTTPS-Transport.
- RFC 4251 (SSH-2 Architecture)
- RFC 854 (Telnet Protocol)