Remote Access: Unterschied zwischen den Versionen

Aus expecco Wiki (Version 25.x)
Zur Navigation springen Zur Suche springen
Inhalt gelöscht Inhalt hinzugefügt
Sv (Diskussion | Beiträge)
Fold bullet continuation lines onto a single physical line so MediaWiki keeps them inside <li>
Sv (Diskussion | Beiträge)
password authentication: URL form, code API, auth order; launcher menu entries
 
(3 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 42: Zeile 42:


<pre>
<pre>
sftp://[user@]host[:port]/remote/path
sftp://[user[:password]@]host[:port]/remote/path
</pre>
</pre>


Fehlt <code>user</code>, wird der lokale Login-Name verwendet, Port
Fehlt <code>user</code>, wird der lokale Login-Name verwendet, Port
ist standardmäßig 22, Pfad standardmäßig <code>/</code>.
ist standardmäßig 22, Pfad standardmäßig <code>/</code>. Das
optionale <code>:password</code>-Segment ist das RFC-3986-Userinfo-Passwort
&mdash; 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 &mdash; 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 &rarr; '''an''' (10-Sekunden-Zyklus, entspricht dem bisherigen Verhalten).
* SFTP &rarr; '''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 &mdash; 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
Das Menü '''Tools''' im FileBrowserV2 bietet vier Aktionen — die
Zeile 61: Zeile 90:
liefert, damit ein TB-großes Volume als ''X TiB'' statt
liefert, damit ein TB-großes Volume als ''X TiB'' statt
''10240 GiB'' erscheint.
''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''' &mdash; 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 &rarr; SSH Connect...'''.
* '''SFTP Connection''' &mdash; 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 ==
== Aus expecco-Aktionen ==
Zeile 313: Zeile 353:
(fragt einmal nach der Passphrase) und nutzt ihn für die übrige
(fragt einmal nach der Passphrase) und nutzt ihn für die übrige
Sitzung weiter.
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 &mdash; 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 &rarr; SFTP Connection''' / '''Workspace &rarr; 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 &mdash; 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 &mdash; ein
funktionierender Schlüssel schlägt also immer ein parallel
konfiguriertes Passwort.

=== Reihenfolge der Authentifizierungsversuche ===

<code>SSH::Client&gt;&gt;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 &mdash; 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 ==
== Konfiguration ==

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 (entferntes exec, 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 (PuTTYs plink 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 ~/.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:

  1. Dienste (services.msc) als Administrator öffnen.
  2. OpenSSH Authentication Agent suchen, Starttyp auf Automatisch setzen, Starten anklicken.
  3. In PowerShell: ssh-add $HOME\.ssh\id_ed25519.
  4. 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:

  1. Vorlage:Key drücken → "Umgebungsvariablen" → „Systemumgebungs- variablen bearbeiten".
  2. Umgebungsvariablen → unter Benutzervariablen, Neu klicken.
  3. Name: SSH_AUTH_SOCK
  4. Wert: \\.\pipe\openssh-ssh-agent
  5. 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 + socat 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 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::Client im Speicher — entsprechend behandeln wie jedes andere In-Memory-Geheimnis.
  • Der Server entscheidet, welche Methoden er akzeptiert. Steht in sshd_config PasswordAuthentication 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:

  1. ssh-agent-Identitäten, sofern #useAgent aufgerufen wurde und der Agent Schlüssel geladen hat.
  2. ed25519-Privatschlüssel-Seed, sofern #privateKeyFromFile: einen geladen hat.
  3. RSA-Privatschlüssel.
  4. ECDSA-Privatschlüssel.
  5. Passwort, sofern #password: / #passwordCallback: gesetzt ist und der Server password in 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 ClientAliveInterval × ClientAliveCountMax des sshd, damit wir uns recyceln, bevor der Server uns mit TCP-RESET trennt. nil setzt auf Voreinstellung zurück.

#attrsCacheTtlSeconds: 5 Maximales Alter (s)

eines gecachten STAT, bevor #ensureAttrs neu am Server fragt. Eltern-listDir stempelt ohnehin frische Attribute auf alle Kinder, daher zahlt das Navigieren im offenen Verzeichnis das TTL nicht. 0 schaltet den Cache ab.

#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 (#isSymbolicLink liefert immer false,

#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, die posix-rename@openssh.com 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.
  • #isNonEmptyDirectory ist 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 sftp://...-URLs auf entfernte Dateien ab und stellt directoryContents, readingFileDo:, renameTo: usw. bereit.

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 als SftpFilename>>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 RecursionLock mit dem Namen SFTP/<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 #isNonEmptyDirectory 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

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