远程服务器管理、自动化部署、配置管理和基础设施监控——所有这些都依赖于安全 Shell 访问。无论您需要在远程主机上执行单个命令、打开交互式终端会话还是设置端口转发隧道,SSH 都是实现这一切的协议。
sgcIndy 包含 TIdSSHClient——这是一个原生 Delphi SSH 客户端组件,实现了 SSH-2 协议,全面支持命令执行、交互式 Shell、伪终端分配、端口转发、保活以及现代加密算法。无需外部 SSH 可执行文件,无需 DLL 封装——纯 Delphi 组件架构,配备事件驱动 API。
本文将介绍主要功能,并为最常见的 SSH 使用场景提供 Delphi 代码示例。
主要功能
|
命令执行 执行远程命令并捕获标准输出、标准错误和退出代码。提供单行便捷方法或完整的基于通道的控制。 |
交互式 Shell 打开支持伪终端的交互式 Shell 会话。发送命令、异步接收输出并处理终端大小调整。 |
端口转发 建立直接 TCP/IP 隧道和反向转发。通过加密的 SSH 隧道访问远程服务。 |
|
现代密码学 支持 Curve25519、ECDH、AES-GCM、Ed25519 密钥。可配置算法协商,开箱即用的安全默认设置。 |
多种认证方式 支持密码、公钥(RSA、ECDSA、Ed25519)和键盘交互式认证。通过事件回调进行主机密钥验证。 |
多通道 每个连接最多支持 10 个并发通道。在单个 SSH 会话上同时运行多个命令、Shell 或隧道。 |
快速入门 — 执行远程命令
最简单的使用场景:连接、运行命令、获取输出并断开连接——仅需几行代码。
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 方法打开通道、运行命令、等待结果并以字符串形式返回输出——非常适合脚本自动化。
身份验证
支持三种认证方式。三种方式均默认启用,客户端会自动与服务器协商。
密码认证
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';
键盘交互式认证
通过 OnSSHKeyboardInteractive 事件处理多步认证提示(MFA、OTP、安全问题)。
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;
命令执行
运行远程命令有两种方式:简单场景使用便捷的 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);
高级方式:基于通道的执行
用于异步执行,可分别处理标准输出/标准错误并跟踪退出状态。
// 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 会话
打开伪终端并与远程 Shell 交互——非常适合构建 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 |
| 消息认证码 | 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 生命周期的每个阶段提供精细的事件回调。
| 事件 | 触发时机 |
|---|---|
OnSSHConnect | SSH 连接已建立 |
OnSSHDisconnect | SSH 连接关闭(含原因和代码) |
OnSSHError | 发生 SSH 错误 |
OnSSHAuthSuccess / OnSSHAuthFailure | 身份验证成功或失败 |
OnSSHHostKey | 需要验证主机密钥(接受/拒绝) |
OnSSHChannelData | 通道上接收到数据(标准输出) |
OnSSHChannelExtendedData | 通道上接收到扩展数据(标准错误) |
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;
