Remote server administration, automated deployments, configuration management, and infrastructure monitoring — all of these rely on secure shell access. Whether you need to execute a single command on a remote host, open an interactive terminal session, or set up a port-forwarding tunnel, SSH is the protocol that makes it possible.
The sgcIndy package includes TIdSSHClient — a native Delphi SSH client component that implements the SSH-2 protocol with full support for command execution, interactive shells, pseudo-terminal allocation, port forwarding, keep-alive, and modern cryptographic algorithms. No external SSH executables, no DLL wrappers — pure Delphi component architecture with an event-driven API.
This article walks through the key features and provides Delphi code examples for the most common SSH use cases.
Key Features
|
Command Execution Execute remote commands and capture stdout, stderr, and exit codes. One-line convenience method or full channel-based control. |
Interactive Shell Open interactive shell sessions with pseudo-terminal support. Send commands, receive output asynchronously, and handle terminal resize. |
Port Forwarding Set up direct TCP/IP tunnels and reverse forwarding. Access remote services through encrypted SSH tunnels. |
|
Modern Cryptography Curve25519, ECDH, AES-GCM, Ed25519 keys. Configurable algorithm negotiation with secure defaults out of the box. |
Multiple Auth Methods Password, public key (RSA, ECDSA, Ed25519), and keyboard-interactive authentication. Host key verification via event callback. |
Multi-Channel Up to 10 concurrent channels per connection. Run multiple commands, shells, or tunnels simultaneously over a single SSH session. |
Quick Start — Execute a Remote Command
The simplest use case: connect, run a command, get the output, and disconnect — all in a 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;
One-liner. The Execute method opens a channel, runs the command, waits for the result, and returns the output as a string — perfect for scripted automation.
Authentication
Three authentication methods are supported. All three are enabled by default and the client negotiates automatically with the server.
Password
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
Handle multi-step authentication prompts (MFA, OTP, security questions) through the 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;
Host Key Verification
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;
Command Execution
Two approaches for running remote commands: the convenience Execute method for simple cases, or the channel-based API for full control over input, output, and 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 with separate stdout/stderr handling and 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;
Interactive Shell Sessions
Open a pseudo-terminal and interact with a remote shell — ideal for building SSH terminal emulators or 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);
Port Forwarding (SSH Tunnels)
Create encrypted tunnels to access remote services as if they were local. Useful for securely accessing databases, admin panels, or 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 from being dropped by firewalls or load balancers with the 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
The defaults are secure and modern. Customize algorithm negotiation when compliance policies or 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 := This email address is being protected from spambots. You need JavaScript enabled to view it.,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
The component provides granular event callbacks for every stage of the SSH lifecycle.
| Event | Fired When |
|---|---|
OnSSHConnect | SSH connection established |
OnSSHDisconnect | SSH connection closes (with reason and code) |
OnSSHError | SSH error occurs |
OnSSHAuthSuccess / OnSSHAuthFailure | Authentication succeeds or fails |
OnSSHHostKey | Host key needs verification (accept/reject) |
OnSSHChannelData | Data (stdout) received on a channel |
OnSSHChannelExtendedData | Extended data (stderr) received on a channel |
OnSSHChannelExitStatus | Remote command exit code received |
OnSSHChannelExitSignal | Remote process terminated by signal (with signal name) |
OnSSHKeyboardInteractive | Server requests keyboard-interactive responses |
OnSSHAuthBanner | Server sends an authentication banner message |
Complete Example: Automated Deployment Script
A fully configured SSH client that connects with key authentication, runs deployment commands, and 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;