ES

Tutorial: una conexión a través de SSH, paso a paso

El proyecto de ejemplo apps/hello-ssh llega a un servidor Redis al que solo puede acceder un servidor SSH (un bastión): ssh -W host:port, el flujo de la conexión es el flujo hacia Redis. En el ordenador es el ssh del sistema; en el navegador, el cliente OpenSSH real compilado a WebAssembly, conectado a tu PHP mediante una tubería.

1. Crear la aplicación

bin/jumphp gui:new mon-ssh "Mon SSH" && bin/jumphp install mon-ssh

2. La ventana

forms/MainForm.form.yaml (copia apps/hello-ssh/forms/MainForm.form.yaml): el servidor SSH (sshHost, sshPort, sshUser), un botón « Choose a key file… » (chooseKey), la frase de paso de la clave (passphrase), el destino visto desde el bastión (host, port), un botón ping, status, result.

3. La clave: el selector de archivos

Un navegador no tiene carpeta ~/.ssh: se le pide el archivo a la persona. FilePicker::open() funciona en el ordenador Y en el navegador (llámalo desde un clic); el archivo elegido llega a una ruta que se lee y luego se borra. Se guarda en el llavero de la aplicación ($this->engine->sshKeyring(): el papel de un agente, que el navegador no tiene).

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());
    });
}

La clave permanece en el almacenamiento de la aplicación (var/ssh_keyring.json: IndexedDB en el navegador, la carpeta de datos en el ordenador) y nunca se envía al servidor: va a la memoria del cliente SSH. Cada conexión ofrece todas las claves del llavero, como un agente.

4. Conectarse

$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

Los mismos eventos que con tcp(). Para código que recibe un Tcp (como el cliente MySQL de apps/jumphpsql): $this->engine->ssh()->via($options) tiene el mismo connect($host, $port, $timeout). Las opciones: docs/ssh-wasm.md.

5. Probar

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. El navegador: dos derechos

bin/jumphp build mon-ssh && bin/jumphp serve mon-ssh

En el navegador, dos etapas pasan por el puente TCP de jumphp.net, que solo acepta las aplicaciones autorizadas: el cliente SSH (WebAssembly) se conecta al bastión (puerto 22 u otro) → hace falta el derecho SSH. (Un cliente SQL que habla directamente con una base de datos necesita el derecho TCP.) Studio → el proyecto → Accès SSH → « Demander l'accès SSH »; el administrador lo autoriza para el commit publicado.

El derecho SSH es más amplio (cualquier puerto de una dirección pública, nunca una dirección privada): el administrador solo lo concede a código que ha revisado. Estadísticas, registro, corte y bloqueo: Administration → Pont TCP.

7. Verificar en el navegador

Página del proyecto en jumphp.net: elige tu clave (se abre el selector de archivos de tu ordenador), indica el bastión y el destino, haz clic en « Send PING through SSH »: The server answered: +PONG. Los primeros segundos muestran « The SSH session is starting… »: el cliente SSH arranca en un Web Worker (un archivo de 3,8 MB cargado bajo demanda).

Cómo funciona (dos wasm conectados por una tubería), la seguridad y la compilación de OpenSSH: docs/ssh-wasm.md. El primer tutorial: docs/tuto-tcp.md.