SSH Client sgcIndy Delphi Component

· Composants

Remote server administration, automated deployments, configuration management, et infrastructure monitoring — tous reposent tous sur un accès shell sécurisé. Que tu doives exécuter une seule commande sur un hôte distant, ouvrir une session terminal interactive, ou mettre en place un tunnel de redirection de port, SSH est le protocole qui rend cela possible.

Le sgcIndy package inclut TIdSSHClient — un composant Delphi natif de client SSH qui implémente le protocole SSH-2 avec une prise en charge complète de l'exécution de commandes, les shells interactifs, l'allocation de pseudo-terminal, la redirection de port, keep-alive, et les algorithmes cryptographiques modernes. Aucun exécutable SSH externe, aucun wrapper DLL — architecture de composant 100% Delphi avec une API basée sur les événements.

Cet article parcourt les fonctionnalités clés et et fournit des exemples de code Delphi pour les cas d'usage SSH les plus courants.

Fonctionnalités clés

Exécution de commandes
Exécute des commandes distantes et capture stdout, stderr et les codes de sortie. Méthode de commodité en une ligne ou contrôle complet par canal.
Shell interactif
Ouvre des sessions shell interactives avec prise en charge du pseudo-terminal. Envoie des commandes, reçois la sortie de manière asynchrone, et gère le redimensionnement du terminal.
Redirection de port
Mets en place des tunnels TCP/IP directs et de la redirection inverse. Accède aux services distants via des tunnels SSH chiffrés.
Cryptographie moderne
Clés Curve25519, ECDH, AES-GCM, Ed25519. Négociation d'algorithme configurable avec des valeurs par défaut sécurisées.
Méthodes d'authentification multiples
Mot de passe, clé publique (RSA, ECDSA, Ed25519), et et authentification interactive au clavier. Vérification de clé d'hôte via callback d'événement.
Multi-canal
Jusqu'à 10 canaux concurrents par connexion. Exécute plusieurs commandes, shells ou tunnels simultanément sur une seule session SSH.

Démarrage rapide — Exécuter une commande distante

Le cas d'usage le plus simple: connect, run a command, obtenir le output, et disconnect — tous dans un few lines.

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;

En une ligne. Le Execute méthode opens un canal, exécute la commande, attend le résultat, et et renvoie la sortie sous forme de chaîne — parfait pour l'automatisation par script.

Authentification

Trois méthodes d'authentification sont prises en charge. Les trois sont activées par défaut et le client négocie automatiquement avec le serveur.

Password

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

Clé publique

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

Interactif au clavier

Gère les prompts d'authentification multi-étapes (MFA, OTP, questions de sécurité) through le OnSSHKeyboardInteractive event.

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;

Vérification de clé d'hôte

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;

Exécution de commandes

Deux approches pour exécuter des commandes distantes: le convenience Execute méthode for simple cases, ou le canal-based API for full control over input, output, et exit status.

Simple: Execute Method

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

Advanced: Channel-Based Execution

For asynchronous execution avec separate stdout/stderr gestion d'unnd 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;

Shell interactif Sessions

Open a pseudo-terminal et interact avec un remote shell — ideal for building SSH terminal emulators ou automating interactive CLI workflows.

// 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 Resize & Signals

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

Redirection de port (SSH Tunnels)

Create encrypted tunnels to access remote services as si ils were local. Useful for securely accessing databases, admin panels, ou internal APIs behind firewalls.

Direct 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 & Connection Options

Prevent idle connections depuis being dropped by firewalls ou load balancers avec le built-in keep-alive mechanism.

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

Cryptographic Algorithm Configuration

Le defaults are secure et modern. Customize algorithm negotiation lorsque compliance policies ou legacy server compatibility demand it.

Category Supported Algorithms
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;

Events Reference

Le component fournit granular événement callbacks for every stage de la SSH lifecycle.

Event Fired When
OnSSHConnectSSH connection established
OnSSHDisconnectSSH connection closes (with reason et code)
OnSSHErrorSSH erreur occurs
OnSSHAuthSuccess / OnSSHAuthFailureAuthentification succeeds ou fails
OnSSHHostKeyHost key needs verification (accept/reject)
OnSSHChannelDataData (stdout) received on un canal
OnSSHChannelExtendedDataExtended data (stderr) received on un canal
OnSSHChannelExitStatusRemote command exit code received
OnSSHChannelExitSignalRemote process terminated by signal (with signal name)
OnSSHKeyboardInteractiveServer requests keyboard-interactive responses
OnSSHAuthBannerServer sends an authentification banner message

Complete Exemple : Automated Deployment Script

A fully configured client SSH que connects avec key authentification, runs deployment commands, et captures exit status.

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;