JA

チュートリアル:SSH経由の接続をステップごとに

サンプルプロジェクトapps/hello-sshは、SSHサーバー(踏み台サーバー)からしか到達できないRedisサーバーに接続します。ssh -W host:portで、接続のストリームがそのまま Redisへのストリームになります。コンピューターではシステムのssh、ブラウザではWebAssemblyにコンパイルした本物のOpenSSHクライアントが、パイプでPHPにつながります。

1. アプリケーションを作る

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

2. ウィンドウ

forms/MainForm.form.yaml(apps/hello-ssh/forms/MainForm.form.yamlをコピーします):SSHサーバー(sshHost、sshPort、sshUser)、「Choose a key file…」ボタン(chooseKey)、鍵の パスフレーズ(passphrase)、踏み台から見た接続先(host、port)、pingボタン、status、result。

3. 鍵:ファイル選択

ブラウザには~/.sshフォルダーがないため、ファイルはユーザーに選んでもらいます。FilePicker::open()はコンピューターでもブラウザでも動作します(クリックの中から呼び出してください)。選ばれた ファイルはあるパスに届くので、それを読み込んでから削除します。鍵はアプリケーションのキーリングに保管します($this->engine->sshKeyring():ブラウザにはないエージェントの役割)。

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

鍵はアプリケーションのストレージ(var/ssh_keyring.json:ブラウザではIndexedDB、コンピューターではデータフォルダー)に残り、サーバーには決して送信されません。SSHクライアントの メモリに渡されます。各接続は、エージェントのように、キーリングのすべての鍵を提示します。

4. 接続する

$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

tcp()と同じイベントです。Tcpを受け取るコード(apps/jumphpsqlのMySQLクライアントなど)には、$this->engine->ssh()->via($options)が同じconnect($host, $port, $timeout)を提供します。 オプション:docs/ssh-wasm.md。

5. テストする

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. ブラウザ:2つの権利

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

ブラウザでは、2つの段階がjumphp.netのTCPブリッジを通ります。ブリッジは許可されたアプリケーションしか受け付けません。SSHクライアント(WebAssembly)が踏み台(ポート22またはその他)に接続するため、 SSHの権利が必要です。(データベースと直接やり取りするSQLクライアントにはTCPの権利が必要です。)Studio → プロジェクト → Accès SSH → « Demander l'accès SSH »。管理者が、公開したコミットについて許可します。

SSHの権利はより広範です(公開アドレスの任意のポート。プライベートアドレスは不可)。管理者は、自分が確認したコードにしかこれを付与しません。統計、ログ、切断、ブロック: Administration → Pont TCP。

7. ブラウザで確認する

jumphp.netのプロジェクトページ:鍵を選び(コンピューターのファイル選択ダイアログが開きます)、踏み台と接続先を入力して、「Send PING through SSH」をクリックします:The server answered: +PONG。 最初の数秒は「The SSH session is starting…」と表示されます。SSHクライアントはWeb Workerの中で起動します(必要になったときに読み込まれる3.8 MBのファイル)。

仕組み(パイプでつながれた2つのwasm)、セキュリティ、OpenSSHのコンパイル:docs/ssh-wasm.md。最初のチュートリアル:docs/tuto-tcp.md。