SSH-client sgcIndy Delphi-component

· Componenten

Beheer van externe servers, geautomatiseerde implementaties, configuratiebeheer en infrastructuurmonitoring — allemaal afhankelijk van veilige shell-toegang. Of je nu één commando op een externe host wilt uitvoeren, een interactieve terminalsessie wilt openen of een port-forwarding-tunnel wilt opzetten: SSH is het protocol dat dit mogelijk maakt.

Het sgcIndy-package bevat TIdSSHClient — een native Delphi SSH-clientcomponent dat het SSH-2-protocol implementeert met volledige ondersteuning voor commando-uitvoering, interactieve shells, pseudo-terminal-allocatie, port forwarding, keep-alive en moderne cryptografische algoritmen. Geen externe SSH-executables, geen DLL-wrappers — pure Delphi-componentarchitectuur met een event-gedreven API.

Dit artikel loopt door de belangrijkste functies en biedt Delphi-codevoorbeelden voor de meest voorkomende SSH-use cases.

Belangrijkste functies

Commando-uitvoering
Voer externe commando's uit en leg stdout, stderr en exit-codes vast. Eenregelige convenience-methode of volledige channel-gebaseerde controle.
Interactieve shell
Open interactieve shell-sessies met pseudo-terminal-ondersteuning. Verstuur commando's, ontvang output asynchroon en verwerk terminal-resize.
Port forwarding
Zet directe TCP/IP-tunnels en reverse forwarding op. Krijg toegang tot externe diensten via versleutelde SSH-tunnels.
Moderne cryptografie
Curve25519, ECDH, AES-GCM, Ed25519-sleutels. Configureerbare algoritmeonderhandeling met veilige standaardinstellingen direct beschikbaar.
Meerdere auth-methoden
Wachtwoord, public key (RSA, ECDSA, Ed25519) en keyboard-interactive authenticatie. Host key-verificatie via event-callback.
Multi-channel
Tot 10 gelijktijdige channels per verbinding. Voer meerdere commando's, shells of tunnels gelijktijdig uit over één SSH-sessie.

Snelstart — voer een extern commando uit

De eenvoudigste use case: verbinden, een commando uitvoeren, de output ophalen en verbinding verbreken — allemaal in een paar regels.

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;

One-liner. De Execute-methode opent een channel, voert het commando uit, wacht op het resultaat en retourneert de output als string — perfect voor scripted automation.

Authenticatie

Drie authenticatiemethoden worden ondersteund. Alle drie zijn standaard ingeschakeld en de client onderhandelt automatisch met de server.

Wachtwoord

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

Verwerk authenticatieprompts in meerdere stappen (MFA, OTP, beveiligingsvragen) via het OnSSHKeyboardInteractive-event.

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

Host key-verificatie

oSSH.OnSSHHostKey := OnHostKey;
procedure TForm1.OnHostKey(Sender: TObject;
  const aHostKeyType, aFingerprint: string;
  var aAction: TIdSSHHostKeyVerification);
begin
  // Accepteren of weigeren op basis van bekende fingerprint
  aAction := sshHostKeyAccept;
end;

Commando-uitvoering

Twee benaderingen voor het uitvoeren van externe commando's: de convenience-methode Execute voor eenvoudige gevallen, of de channel-gebaseerde API voor volledige controle over invoer, output en exit-status.

Eenvoudig: Execute-methode

// Voer uit en haal output op (standaard 30-seconden time-out)
vOutput := oSSH.Execute('ls -la /var/log');
// Aangepaste time-out (10 seconden)
vOutput := oSSH.Execute('cat /etc/hostname', 10000);

Geavanceerd: channel-gebaseerde uitvoering

Voor asynchrone uitvoering met aparte stdout/stderr-afhandeling en 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 komt binnen via het OnSSHChannelData-event
  // Exit-status komt binnen via het OnSSHChannelExitStatus-event
end;
// stdout verwerken
procedure TForm1.OnChannelData(Sender: TObject;
  aChannelId: Cardinal; const aData: TIdBytes);
begin
  Memo1.Lines.Add(BytesToString(aData));
end;
// stderr verwerken
procedure TForm1.OnChannelExtendedData(Sender: TObject;
  aChannelId: Cardinal; aDataType: Cardinal; const aData: TIdBytes);
begin
  MemoErrors.Lines.Add(BytesToString(aData));
end;
// Exit-status verwerken
procedure TForm1.OnExitStatus(Sender: TObject;
  aChannelId: Cardinal; aExitStatus: Integer);
begin
  WriteLn('Command exited with code: ' + IntToStr(aExitStatus));
end;

Interactieve shell-sessies

Open een pseudo-terminal en interageer met een externe shell — ideaal voor het bouwen van SSH-terminalemulators of het automatiseren van interactieve CLI-workflows.

// Open channel, vraag PTY aan, vraag daarna de shell aan
var
  vChannelId: Cardinal;
begin
  vChannelId := oSSH.OpenChannel;
  // Vraag een pseudo-terminal aan (xterm, 80x24)
  oSSH.RequestPTY(vChannelId, 'xterm', 80, 24);
  // Start de shell
  oSSH.RequestShell(vChannelId);
  // Verstuur commando's naar de shell
  oSSH.SendChannelData(vChannelId, 'cd /var/log' + #13#10);
  oSSH.SendChannelData(vChannelId, 'tail -f syslog' + #13#10);
end;

Terminal-resize & signalen

// Meld terminal-resize aan de server
oSSH.SendWindowChange(vChannelId, 120, 40, 0, 0);
// Verstuur Ctrl+C (interrupt-signaal)
oSSH.SendSignal(vChannelId, 'INT');
// Stel een environment-variabele in voor het uitvoeren van commando's
oSSH.SetEnvironmentVariable(vChannelId, 'LANG', 'en_US.UTF-8');
// Signaleer einde van invoer
oSSH.SendEOF(vChannelId);

Port forwarding (SSH-tunnels)

Maak versleutelde tunnels om toegang te krijgen tot externe diensten alsof ze lokaal zijn. Handig voor het veilig benaderen van databases, beheerpanelen of interne API's achter firewalls.

Directe TCP/IP-tunneling (local forward)

// Tunnel naar een externe database via SSH
var
  vTunnelId: Cardinal;
begin
  vTunnelId := oSSH.OpenDirectTCPIP(
    'db-internal.example.com',  // Externe host
    5432,                        // Externe poort (PostgreSQL)
    '127.0.0.1',                 // Originator-IP
    0);                           // Originator-poort
  // Data versturen/ontvangen via de tunnel
  oSSH.SendChannelData(vTunnelId, vDatabaseQuery);
end;

Reverse forwarding (remote forward)

// Vraag de server om een externe poort naar ons door te sturen
oSSH.RequestForwarding('0.0.0.0', 8080);
// Annuleer de forwarding
oSSH.CancelForwarding('0.0.0.0', 8080);

Keep-alive & verbindingsopties

Voorkom dat inactieve verbindingen worden verbroken door firewalls of load balancers met het ingebouwde keep-alive-mechanisme.

// Verstuur elke 30 seconden keep-alive, verbreek na 3 mislukkingen
oSSH.KeepAlive.Enabled := True;
oSSH.KeepAlive.Interval := 30;
oSSH.KeepAlive.MaxCount := 3;
// Verbindingsopties
oSSH.SSHOptions.ConnectTimeout := 10000;  // 10 seconden
oSSH.SSHOptions.ReadTimeout := 30000;     // 30 seconden
oSSH.SSHOptions.MaxChannels := 10;       // Gelijktijdige channels

Configuratie van cryptografische algoritmen

De standaardinstellingen zijn veilig en modern. Pas algoritmeonderhandeling aan wanneer compliance-beleid of compatibiliteit met oudere servers dit vereist.

Categorie Ondersteunde algoritmen
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
// Algoritmevoorkeuren aanpassen
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';
// Forceer re-keying om de versleuteling te vernieuwen
oSSH.Rekey;

Events-overzicht

Het component biedt fijnmazige event-callbacks voor elke fase van de SSH-levenscyclus.

Event Wordt geactiveerd wanneer
OnSSHConnectSSH-verbinding tot stand gebracht
OnSSHDisconnectSSH-verbinding sluit (met reden en code)
OnSSHErrorEr treedt een SSH-fout op
OnSSHAuthSuccess / OnSSHAuthFailureAuthenticatie slaagt of mislukt
OnSSHHostKeyHost key moet worden geverifieerd (accepteren/weigeren)
OnSSHChannelDataData (stdout) ontvangen op een channel
OnSSHChannelExtendedDataExtended data (stderr) ontvangen op een channel
OnSSHChannelExitStatusExit-code van extern commando ontvangen
OnSSHChannelExitSignalExtern proces beëindigd door signaal (met signaalnaam)
OnSSHKeyboardInteractiveServer vraagt om keyboard-interactive-reacties
OnSSHAuthBannerServer stuurt een authenticatie-bannerbericht

Compleet voorbeeld: geautomatiseerd deployment-script

Een volledig geconfigureerde SSH-client die verbindt met key-authenticatie, deployment-commando's uitvoert en exit-status vastlegt.

uses
  IdSSHClient, IdSSHClasses;
var
  oSSH: TIdSSHClient;
  vOutput: string;
begin
  oSSH := TIdSSHClient.Create(nil);
  Try
    // Verbinding
    oSSH.Host := 'production.example.com';
    oSSH.Port := 22;
    // Key-gebaseerde authenticatie
    oSSH.Authentication.Username := 'deploy';
    oSSH.Authentication.PrivateKeyFile := 'C:\keys\deploy_ed25519';
    // Houd de verbinding actief door firewalls heen
    oSSH.KeepAlive.Enabled := True;
    oSSH.KeepAlive.Interval := 30;
    // Events
    oSSH.OnSSHHostKey := OnHostKey;
    oSSH.OnSSHError := OnError;
    // Verbinden
    oSSH.Connect;
    // Voer deployment-commando's uit
    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);
    // Verbinding verbreken
    oSSH.Disconnect;
  Finally
    oSSH.Free;
  End;
end;