SSH Client sgcIndy Delphi Component

· Komponenten

Remote-Server-Administration, automatisierte Deployments, Konfigurationsmanagement und Infrastruktur-Monitoring — all das setzt auf sicheren Shell-Zugriff. Egal, ob du einen einzelnen Befehl auf einem Remote-Host ausführen, eine interaktive Terminal-Sitzung öffnen oder einen Port-Forwarding-Tunnel aufbauen willst — SSH ist das Protokoll, das das möglich macht.

Das Paket sgcIndy enthält TIdSSHClient — eine native Delphi-SSH-Client-Komponente, die das SSH-2-Protokoll implementiert und Befehlsausführung, interaktive Shells, Pseudo-Terminal-Zuweisung, Port-Forwarding, Keep-Alive und moderne kryptographische Algorithmen vollständig unterstützt. Keine externen SSH-Programme, keine DLL-Wrapper — reine Delphi-Komponenten-Architektur mit einer ereignisgesteuerten API.

Dieser Artikel führt dich durch die wichtigsten Funktionen und liefert Delphi-Code-Beispiele für die häufigsten SSH-Anwendungsfälle.

Wichtige Funktionen

Befehlsausführung
Führe Remote-Befehle aus und erfasse stdout, stderr und Exit-Codes. Komfortmethode in einer Zeile oder volle kanalbasierte Kontrolle.
Interaktive Shell
Öffne interaktive Shell-Sitzungen mit Pseudo-Terminal-Unterstützung. Sende Befehle, empfange Ausgabe asynchron und behandle Terminal-Größenänderungen.
Port-Forwarding
Richte direkte TCP/IP-Tunnel und Reverse-Forwarding ein. Greife über verschlüsselte SSH-Tunnel auf Remote-Dienste zu.
Moderne Kryptographie
Curve25519, ECDH, AES-GCM, Ed25519-Schlüssel. Konfigurierbare Algorithmus-Aushandlung mit sicheren Standardwerten ab Werk.
Mehrere Auth-Methoden
Passwort, Public-Key (RSA, ECDSA, Ed25519) und Keyboard-Interactive-Authentifizierung. Host-Key-Verifikation per Ereignis-Callback.
Multi-Channel
Bis zu 10 gleichzeitige Kanäle pro Verbindung. Führe mehrere Befehle, Shells oder Tunnel gleichzeitig über eine einzige SSH-Sitzung aus.

Schnellstart — Einen Remote-Befehl ausführen

Der einfachste Anwendungsfall: verbinden, einen Befehl ausführen, die Ausgabe holen und trennen — alles in wenigen Zeilen.

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;

Einzeiler. Die Methode Execute öffnet einen Kanal, führt den Befehl aus, wartet auf das Ergebnis und gibt die Ausgabe als String zurück — perfekt für skriptgesteuerte Automatisierung.

Authentifizierung

Drei Authentifizierungsmethoden werden unterstützt. Alle drei sind standardmäßig aktiviert, und der Client handelt sie automatisch mit dem Server aus.

Passwort

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

Public Key

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

Keyboard-Interactive

Verarbeite mehrstufige Authentifizierungs-Aufforderungen (MFA, OTP, Sicherheitsfragen) über das Ereignis 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;

Host-Key-Verifikation

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;

Befehlsausführung

Zwei Ansätze zum Ausführen von Remote-Befehlen: die Komfortmethode Execute für einfache Fälle oder die kanalbasierte API für volle Kontrolle über Eingabe, Ausgabe und Exit-Status.

Einfach: Execute-Methode

// 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);

Fortgeschritten: Kanalbasierte Ausführung

Für asynchrone Ausführung mit getrennter stdout/stderr-Behandlung und Exit-Status-Tracking.

// 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;

Interaktive Shell-Sitzungen

Öffne ein Pseudo-Terminal und interagiere mit einer Remote-Shell — ideal, um SSH-Terminal-Emulatoren zu bauen oder interaktive CLI-Workflows zu automatisieren.

// 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;

Terminal-Größenänderung & Signale

// 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);

Port-Forwarding (SSH-Tunnel)

Erstelle verschlüsselte Tunnel, um auf Remote-Dienste so zuzugreifen, als wären sie lokal. Nützlich, um sicher auf Datenbanken, Admin-Oberflächen oder interne APIs hinter Firewalls zuzugreifen.

Direktes TCP/IP-Tunneling (Local Forward)

// 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;

Reverse Forwarding (Remote Forward)

// 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);

Keep-Alive & Verbindungsoptionen

Verhindere, dass inaktive Verbindungen von Firewalls oder Load Balancern getrennt werden, mit dem eingebauten Keep-Alive-Mechanismus.

// 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

Konfiguration kryptographischer Algorithmen

Die Standardwerte sind sicher und modern. Passe die Algorithmus-Aushandlung an, wenn Compliance-Vorgaben oder Kompatibilität mit Altsystemen das erfordern.

Kategorie Unterstützte Algorithmen
Key Exchange Curve25519, ECDH (P-256, P-384, P-521), DH Group14/16
Host Keys Ed25519, ECDSA (P-256, P-384, P-521), RSA (SHA2-256, SHA2-512)
Ciphers AES-256/192/128-CTR, AES-256/128-GCM
MACs 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;

Ereignis-Referenz

Die Komponente stellt feingranulare Ereignis-Callbacks für jede Phase des SSH-Lebenszyklus bereit.

Ereignis Ausgelöst, wenn
OnSSHConnectSSH-Verbindung hergestellt
OnSSHDisconnectSSH-Verbindung wird geschlossen (mit Grund und Code)
OnSSHErrorSSH-Fehler tritt auf
OnSSHAuthSuccess / OnSSHAuthFailureAuthentifizierung erfolgreich oder fehlgeschlagen
OnSSHHostKeyHost-Key muss verifiziert werden (akzeptieren/ablehnen)
OnSSHChannelDataDaten (stdout) auf einem Kanal empfangen
OnSSHChannelExtendedDataExtended-Daten (stderr) auf einem Kanal empfangen
OnSSHChannelExitStatusExit-Code des Remote-Befehls empfangen
OnSSHChannelExitSignalRemote-Prozess durch Signal beendet (mit Signalname)
OnSSHKeyboardInteractiveServer fordert Keyboard-Interactive-Antworten an
OnSSHAuthBannerServer sendet eine Authentifizierungs-Banner-Nachricht

Vollständiges Beispiel: Automatisiertes Deployment-Skript

Ein vollständig konfigurierter SSH-Client, der sich mit Key-Authentifizierung verbindet, Deployment-Befehle ausführt und den Exit-Status erfasst.

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;