Tutorial: eine Verbindung über SSH, Schritt für Schritt
Das Beispielprojekt apps/hello-ssh erreicht einen Redis-Server, den nur ein SSH-Server (ein Bastion-Host) erreichen kann: ssh -W host:port, der Datenstrom der Verbindung ist der
Strom zu Redis. Auf dem Computer ist es das ssh des Systems; im Browser der echte OpenSSH-Client, kompiliert zu WebAssembly, über eine Pipe mit deinem PHP verbunden.
1. Die Anwendung erstellen
bin/jumphp gui:new mon-ssh "Mon SSH" && bin/jumphp install mon-ssh
2. Das Fenster
forms/MainForm.form.yaml (kopiere apps/hello-ssh/forms/MainForm.form.yaml): der SSH-Server (sshHost, sshPort, sshUser), eine Schaltfläche « Choose a key file… » (chooseKey), die Passphrase
des Schlüssels (passphrase), das Ziel aus Sicht des Bastion-Hosts (host, port), eine Schaltfläche ping, status, result.
3. Der Schlüssel: die Dateiauswahl
Ein Browser hat kein Verzeichnis ~/.ssh: Man bittet die Person um die Datei. FilePicker::open() funktioniert auf dem Computer UND im Browser (rufe es aus einem Klick auf); die
gewählte Datei landet an einem Pfad, den man liest und dann löscht. Man bewahrt sie im Schlüsselbund der Anwendung auf ($this->engine->sshKeyring(): die Rolle eines Agenten, den der Browser nicht hat).
public function onChooseKey(Button $sender): void
{
FilePicker::open(['title' => 'SSH private key'])->then(function (?string $file): void {
if ($file === null) { return; } // annulé
$text = (string)file_get_contents($file);
unlink($file);
$this->engine->sshKeyring()->add(basename($file), $text, $this->passphrase->text); // nom, clé, phrase secrète
$this->keyState->text = 'Keys: ' . implode(', ', $this->engine->sshKeyring()->names());
});
}
Der Schlüssel bleibt im Speicher der Anwendung (var/ssh_keyring.json: IndexedDB im Browser, der Datenordner auf dem Computer) und wird nie an den Server gesendet: Er geht in den
Speicher des SSH-Clients. Jede Verbindung bietet alle Schlüssel des Schlüsselbunds an, wie ein Agent.
4. Sich verbinden
$options = ['sshHost' => 'bastion.exemple.com', 'sshPort' => 22, 'sshUser' => 'moi', 'sshKeys' => $this->engine->sshKeyring()->all()];
$connection = $this->engine->ssh()->connect('127.0.0.1', 6379, $options); // 127.0.0.1:6379 vu depuis le bastion
$connection->on('open', fn () => $connection->write("PING\r\n"));
$connection->on('data', fn (string $bytes) => $this->result->text = trim($bytes));
$connection->on('error', fn (string $m) => $this->result->text = $m); // « Permission denied (publickey) », « Could not resolve hostname »...
$connection->on('knownHosts', fn (string $text) => $this->engine->storage->writeJson('known_hosts.json', ['text' => $text])); // l'empreinte du serveur, gardée
Dieselben Ereignisse wie bei tcp(). Für Code, der ein Tcp entgegennimmt (wie der MySQL-Client von apps/jumphpsql): $this->engine->ssh()->via($options) hat dasselbe connect($host, $port, $timeout).
Die Optionen: docs/ssh-wasm.md.
5. Testen
bin/jumphp test mon-ssh # le trousseau, les champs manquants, un ssh qui n'atteint pas son serveur (le message dit pourquoi)
bin/jumphp shot mon-ssh
bin/jumphp run mon-ssh # sur l'ordinateur : le ssh du système (votre agent et ~/.ssh marchent aussi)
6. Der Browser: zwei Rechte
bin/jumphp build mon-ssh && bin/jumphp serve mon-ssh
Im Browser laufen zwei Stufen über die TCP-Bridge von jumphp.net, die nur autorisierte Anwendungen akzeptiert: Der SSH-Client (WebAssembly) verbindet sich mit dem Bastion-Host (Port 22 oder ein anderer) → dafür wird das Recht SSH benötigt. (Ein SQL-Client, der direkt mit einer Datenbank spricht, braucht das Recht TCP.) Studio → das Projekt → Accès SSH → « Demander l'accès SSH »; der Administrator genehmigt es für den veröffentlichten Commit.
Das SSH-Recht ist weiter gefasst (jeder Port einer öffentlichen Adresse, nie eine private Adresse): Der Administrator erteilt es nur Code, den er sich angesehen hat. Statistiken, Protokoll, Trennen und Sperren: Administration → Pont TCP.
7. Im Browser prüfen
Projektseite auf jumphp.net: Wähle deinen Schlüssel (die Dateiauswahl deines Computers öffnet sich), gib Bastion-Host und Ziel an, klicke « Send PING through SSH »: The server answered: +PONG.
In den ersten Sekunden erscheint « The SSH session is starting… »: Der SSH-Client startet in einem Web Worker (eine 3,8 MB große Datei, die bei Bedarf geladen wird).
Wie es funktioniert (zwei über eine Pipe verbundene wasm), die Sicherheit und die Kompilierung von OpenSSH: docs/ssh-wasm.md. Das erste Tutorial: docs/tuto-tcp.md.