SSH クライアント sgcIndy Delphi コンポーネント

· コンポーネント

リモートサーバー管理・自動デプロイ・設定管理・インフラ監視はすべてセキュアシェルアクセスに依存しています。リモートホストで単一のコマンドを実行する場合でも、対話型ターミナルセッションを開く場合でも、ポートフォワーディングトンネルを設定する場合でも、SSH はそれを可能にするプロトコルです。

sgcIndy パッケージには TIdSSHClient が含まれています。これはコマンド実行・対話型シェル・疑似ターミナル割り当て・ポートフォワーディング・キープアライブ・最新の暗号アルゴリズムを完全サポートする SSH-2 プロトコルを実装したネイティブ Delphi SSH クライアントコンポーネントです。外部の SSH 実行ファイルや DLL ラッパーは不要で、イベント駆動 API を持つ純粋な Delphi コンポーネントアーキテクチャです。

本記事では主要な機能を解説し、最も一般的な SSH ユースケースの Delphi コードサンプルを提供します。

主な機能

コマンド実行
リモートコマンドを実行して stdout・stderr・終了コードをキャプチャします。ワンライン便利メソッドまたはチャンネルベースの完全な制御が可能です。
対話型シェル
疑似ターミナルサポートで対話型シェルセッションを開きます。コマンドの送信・非同期での出力受信・ターミナルリサイズの処理が可能です。
ポートフォワーディング
直接 TCP/IP トンネルとリバースフォワーディングを設定します。暗号化された SSH トンネルを通じてリモートサービスにアクセスします。
最新暗号
Curve25519・ECDH・AES-GCM・Ed25519 鍵。設定可能なアルゴリズムネゴシエーションと安全なデフォルト設定。
複数認証方式
パスワード・公開鍵(RSA・ECDSA・Ed25519)・キーボードインタラクティブ認証。イベントコールバックでホスト鍵検証。
マルチチャンネル
接続ごとに最大 10 の同時チャンネル。単一の SSH セッションで複数のコマンド・シェル・トンネルを同時に実行できます。

クイックスタート — リモートコマンドの実行

最もシンプルなユースケース:接続・コマンド実行・出力取得・切断をわずか数行で実現します。

var
  oSSH: TIdSSHClient;
  vOutput: string;
begin
  oSSH := TIdSSHClient.Create(nil);
  Try
    oSSH.Host := 'server.example.com';
    oSSH.Port := 22;
    oSSH.Authentication.Username := 'admin';
    oSSH.Authentication.Password := 'secret';
    oSSH.Connect;
    // Execute a command and capture the output
    vOutput := oSSH.Execute('df -h');
    WriteLn(vOutput);
    oSSH.Disconnect;
  Finally
    oSSH.Free;
  End;
end;

ワンライナー。Execute メソッドはチャンネルを開いてコマンドを実行し、結果を待って出力を文字列で返します。スクリプト自動化に最適です。

認証

3 つの認証方式がサポートされています。デフォルトで 3 つすべてが有効になっており、クライアントはサーバーと自動的にネゴシエーションします。

パスワード認証

oSSH.Authentication.Username := 'admin';
oSSH.Authentication.Password := 'secret';

公開鍵認証

oSSH.Authentication.Username := 'deploy';
oSSH.Authentication.PrivateKeyFile := 'C:\keys\id_ed25519';
oSSH.Authentication.PublicKeyFile := 'C:\keys\id_ed25519.pub';
oSSH.Authentication.Passphrase := 'keypassphrase';

キーボードインタラクティブ認証

多段階認証プロンプト(MFA・OTP・セキュリティ質問)を OnSSHKeyboardInteractive イベントで処理します。

oSSH.OnSSHKeyboardInteractive := OnKeyboardInteractive;
procedure TForm1.OnKeyboardInteractive(Sender: TObject;
  const aName, aInstruction: string;
  aPrompts: TStrings; aEchos: TList; aResponses: TStrings);
begin
  // Respond to each prompt (e.g., "Password:", "OTP:")
  if aPrompts.Count > 0 then
    aResponses.Add('mypassword');
end;

ホスト鍵検証

oSSH.OnSSHHostKey := OnHostKey;
procedure TForm1.OnHostKey(Sender: TObject;
  const aHostKeyType, aFingerprint: string;
  var aAction: TIdSSHHostKeyVerification);
begin
  // Accept or reject based on known fingerprint
  aAction := sshHostKeyAccept;
end;

コマンド実行

リモートコマンドの実行方法は 2 つあります:シンプルなケース向けの便利な Execute メソッド、または入力・出力・終了ステータスを完全に制御するチャンネルベース API です。

シンプル:Execute メソッド

// Execute and get output (30-second timeout by default)
vOutput := oSSH.Execute('ls -la /var/log');
// Custom timeout (10 seconds)
vOutput := oSSH.Execute('cat /etc/hostname', 10000);

高度:チャンネルベースの実行

stdout/stderr を分けて処理し終了ステータスを追跡する非同期実行向けです。

// Open a channel and execute a command
var
  vChannelId: Cardinal;
begin
  vChannelId := oSSH.OpenChannel;
  oSSH.RequestExec(vChannelId, 'tar czf /tmp/backup.tar.gz /data');
  // Output arrives via OnSSHChannelData event
  // Exit status arrives via OnSSHChannelExitStatus event
end;
// Handle stdout
procedure TForm1.OnChannelData(Sender: TObject;
  aChannelId: Cardinal; const aData: TIdBytes);
begin
  Memo1.Lines.Add(BytesToString(aData));
end;
// Handle stderr
procedure TForm1.OnChannelExtendedData(Sender: TObject;
  aChannelId: Cardinal; aDataType: Cardinal; const aData: TIdBytes);
begin
  MemoErrors.Lines.Add(BytesToString(aData));
end;
// Handle exit status
procedure TForm1.OnExitStatus(Sender: TObject;
  aChannelId: Cardinal; aExitStatus: Integer);
begin
  WriteLn('Command exited with code: ' + IntToStr(aExitStatus));
end;

対話型シェルセッション

疑似ターミナルを開いてリモートシェルと対話します。SSH ターミナルエミュレーターの構築や対話型 CLI ワークフローの自動化に最適です。

// Open channel, request PTY, then request shell
var
  vChannelId: Cardinal;
begin
  vChannelId := oSSH.OpenChannel;
  // Request a pseudo-terminal (xterm, 80x24)
  oSSH.RequestPTY(vChannelId, 'xterm', 80, 24);
  // Start the shell
  oSSH.RequestShell(vChannelId);
  // Send commands to the shell
  oSSH.SendChannelData(vChannelId, 'cd /var/log' + #13#10);
  oSSH.SendChannelData(vChannelId, 'tail -f syslog' + #13#10);
end;

ターミナルリサイズとシグナル

// Notify the server of terminal resize
oSSH.SendWindowChange(vChannelId, 120, 40, 0, 0);
// Send Ctrl+C (interrupt signal)
oSSH.SendSignal(vChannelId, 'INT');
// Set an environment variable before running commands
oSSH.SetEnvironmentVariable(vChannelId, 'LANG', 'en_US.UTF-8');
// Signal end of input
oSSH.SendEOF(vChannelId);

ポートフォワーディング(SSH トンネル)

暗号化されたトンネルを作成してリモートサービスにローカルのようにアクセスします。ファイアウォール背後のデータベース・管理パネル・内部 API に安全にアクセスするのに役立ちます。

直接 TCP/IP トンネリング(ローカルフォワード)

// Tunnel to a remote database through SSH
var
  vTunnelId: Cardinal;
begin
  vTunnelId := oSSH.OpenDirectTCPIP(
    'db-internal.example.com',  // Remote host
    5432,                        // Remote port (PostgreSQL)
    '127.0.0.1',                 // Originator IP
    0);                           // Originator port
  // Send/receive data through the tunnel
  oSSH.SendChannelData(vTunnelId, vDatabaseQuery);
end;

リバースフォワーディング(リモートフォワード)

// Ask the server to forward a remote port to us
oSSH.RequestForwarding('0.0.0.0', 8080);
// Cancel the forwarding
oSSH.CancelForwarding('0.0.0.0', 8080);

キープアライブと接続オプション

組み込みのキープアライブメカニズムでアイドル接続がファイアウォールやロードバランサーに切断されるのを防ぎます。

// Send keep-alive every 30 seconds, disconnect after 3 failures
oSSH.KeepAlive.Enabled := True;
oSSH.KeepAlive.Interval := 30;
oSSH.KeepAlive.MaxCount := 3;
// Connection options
oSSH.SSHOptions.ConnectTimeout := 10000;  // 10 seconds
oSSH.SSHOptions.ReadTimeout := 30000;     // 30 seconds
oSSH.SSHOptions.MaxChannels := 10;       // Concurrent channels

暗号アルゴリズムの設定

デフォルトは安全かつ最新です。コンプライアンスポリシーやレガシーサーバーとの互換性が必要な場合はアルゴリズムネゴシエーションをカスタマイズできます。

カテゴリ サポートされるアルゴリズム
鍵交換 Curve25519, ECDH (P-256, P-384, P-521), DH Group14/16
ホスト鍵 Ed25519, ECDSA (P-256, P-384, P-521), RSA (SHA2-256, SHA2-512)
暗号 AES-256/192/128-CTR, AES-256/128-GCM
MAC HMAC-SHA2-256, HMAC-SHA2-512, HMAC-SHA1
// Customize algorithm preferences
oSSH.Algorithms.KexAlgorithms := 'curve25519-sha256';
oSSH.Algorithms.Ciphers := 'aes256-gcm@openssh.com'
		,aes256-ctr';
oSSH.Algorithms.HostKeyAlgorithms := 'ssh-ed25519,rsa-sha2-256';
oSSH.Algorithms.MACs := 'hmac-sha2-256';
// Force re-keying to refresh encryption
oSSH.Rekey;

イベントリファレンス

コンポーネントは SSH ライフサイクルのすべての段階で詳細なイベントコールバックを提供します。

イベント 発火タイミング
OnSSHConnectSSH 接続が確立されたとき
OnSSHDisconnectSSH 接続がクローズされたとき(理由とコード付き)
OnSSHErrorSSH エラーが発生したとき
OnSSHAuthSuccess / OnSSHAuthFailure認証が成功または失敗したとき
OnSSHHostKeyホスト鍵の検証が必要なとき(承認/拒否)
OnSSHChannelDataチャンネルでデータ(stdout)を受信したとき
OnSSHChannelExtendedDataチャンネルで拡張データ(stderr)を受信したとき
OnSSHChannelExitStatusリモートコマンドの終了コードを受信したとき
OnSSHChannelExitSignalリモートプロセスがシグナルで終了したとき(シグナル名付き)
OnSSHKeyboardInteractiveサーバーがキーボードインタラクティブ応答を要求したとき
OnSSHAuthBannerサーバーが認証バナーメッセージを送信したとき

完全なサンプル:自動デプロイスクリプト

鍵認証で接続してデプロイコマンドを実行し終了ステータスをキャプチャする完全設定済みの SSH クライアントです。

uses
  IdSSHClient, IdSSHClasses;
var
  oSSH: TIdSSHClient;
  vOutput: string;
begin
  oSSH := TIdSSHClient.Create(nil);
  Try
    // Connection
    oSSH.Host := 'production.example.com';
    oSSH.Port := 22;
    // Key-based authentication
    oSSH.Authentication.Username := 'deploy';
    oSSH.Authentication.PrivateKeyFile := 'C:\keys\deploy_ed25519';
    // Keep connection alive through firewalls
    oSSH.KeepAlive.Enabled := True;
    oSSH.KeepAlive.Interval := 30;
    // Events
    oSSH.OnSSHHostKey := OnHostKey;
    oSSH.OnSSHError := OnError;
    // Connect
    oSSH.Connect;
    // Run deployment commands
    vOutput := oSSH.Execute('cd /opt/app && git pull origin main');
    WriteLn(vOutput);
    vOutput := oSSH.Execute('systemctl restart myapp');
    WriteLn(vOutput);
    vOutput := oSSH.Execute('systemctl status myapp');
    WriteLn(vOutput);
    // Disconnect
    oSSH.Disconnect;
  Finally
    oSSH.Free;
  End;
end;