Administracja zdalna serwerami, automatyczne wdrożenia, zarządzanie konfiguracją i monitorowanie infrastruktury — wszystkie te zadania opierają się na bezpiecznym dostępie do powłoki. Czy potrzebujesz wykonać pojedyncze polecenie na zdalnym hoście, otworzyć interaktywną sesję terminala czy skonfigurować tunel przekazywania portów — SSH to protokół, który to umożliwia.
Pakiet sgcIndy zawiera TIdSSHClient — natywny komponent klienta SSH dla Delphi implementujący protokół SSH-2 z pełną obsługą wykonywania poleceń, interaktywnych powłok, alokacji pseudoterminala, przekazywania portów, mechanizmu keep-alive oraz nowoczesnych algorytmów kryptograficznych. Bez zewnętrznych plików wykonywalnych SSH, bez wrapperów DLL — czysta architektura komponentów Delphi z API opartym na zdarzeniach.
Ten artykuł omawia kluczowe funkcje i zawiera przykłady kodu Delphi dla najczęstszych zastosowań SSH.
Kluczowe funkcje
|
Wykonywanie poleceń Wykonuj zdalne polecenia i przechwytuj stdout, stderr oraz kody wyjścia. Wygodna metoda jednolinijkowa lub pełna kontrola oparta na kanałach. |
Interaktywna powłoka Otwieraj interaktywne sesje powłoki z obsługą pseudoterminala. Wysyłaj polecenia, asynchronicznie odbieraj dane wyjściowe i obsługuj zmianę rozmiaru terminala. |
Przekazywanie portów Konfiguruj bezpośrednie tunele TCP/IP i odwrócone przekazywanie. Uzyskuj dostęp do zdalnych usług przez szyfrowane tunele SSH. |
|
Nowoczesna kryptografia Klucze Curve25519, ECDH, AES-GCM, Ed25519. Konfigurowalna negocjacja algorytmów z bezpiecznymi wartościami domyślnymi. |
Wiele metod uwierzytelniania Hasło, klucz publiczny (RSA, ECDSA, Ed25519) i uwierzytelnianie keyboard-interactive. Weryfikacja klucza hosta przez callback zdarzenia. |
Wiele kanałów Do 10 współbieżnych kanałów na połączenie. Uruchamiaj wiele poleceń, powłok lub tuneli jednocześnie w jednej sesji SSH. |
Szybki start — wykonanie zdalnego polecenia
Najprostsze zastosowanie: połącz się, uruchom polecenie, pobierz dane wyjściowe i rozłącz się — wszystko w kilku linijkach.
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;
Jednolinijkowo. Metoda Execute otwiera kanał, uruchamia polecenie, czeka na wynik i zwraca dane wyjściowe jako ciąg znaków — idealne do zautomatyzowanych skryptów.
Uwierzytelnianie
Obsługiwane są trzy metody uwierzytelniania. Wszystkie trzy są domyślnie włączone, a klient negocjuje automatycznie z serwerem.
Hasło
oSSH.Authentication.Username := 'admin';
oSSH.Authentication.Password := 'secret';
Klucz publiczny
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
Obsługuj wieloetapowe monity uwierzytelniania (MFA, OTP, pytania zabezpieczające) przez zdarzenie 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;
Weryfikacja klucza hosta
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;
Wykonywanie poleceń
Dwa podejścia do uruchamiania zdalnych poleceń: wygodna metoda Execute dla prostych przypadków lub API oparte na kanałach zapewniające pełną kontrolę nad wejściem, wyjściem i statusem zakończenia.
Prosto: metoda 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);
Zaawansowane: wykonanie oparte na kanałach
Do asynchronicznego wykonywania z oddzielną obsługą stdout/stderr i śledzeniem statusu zakończenia.
// 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;
Interaktywne sesje powłoki
Otwórz pseudoterminal i wejdź w interakcję ze zdalną powłoką — idealne do budowania emulatorów terminala SSH lub automatyzowania interaktywnych przepływów 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;
Zmiana rozmiaru terminala i sygnały
// 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);
Przekazywanie portów (tunele SSH)
Twórz szyfrowane tunele umożliwiające dostęp do zdalnych usług tak, jakby były lokalne. Przydatne do bezpiecznego dostępu do baz danych, paneli administracyjnych lub wewnętrznych API za zaporami sieciowymi.
Bezpośrednie tunelowanie TCP/IP (przekazywanie lokalne)
// 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;
Odwrócone przekazywanie (przekazywanie zdalne)
// 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 i opcje połączenia
Zapobiegaj przerywaniu bezczynnych połączeń przez zapory sieciowe lub load balancery dzięki wbudowanemu mechanizmowi keep-alive.
// 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
Konfiguracja algorytmów kryptograficznych
Wartości domyślne są bezpieczne i nowoczesne. Dostosuj negocjację algorytmów, gdy wymagają tego polityki zgodności lub kompatybilność z starszymi serwerami.
| Kategoria | Obsługiwane algorytmy |
|---|---|
| Wymiana kluczy | Curve25519, ECDH (P-256, P-384, P-521), DH Group14/16 |
| Klucze hosta | Ed25519, ECDSA (P-256, P-384, P-521), RSA (SHA2-256, SHA2-512) |
| Szyfry | AES-256/192/128-CTR, AES-256/128-GCM |
| MAC-e | 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;
Informacje o zdarzeniach
Komponent udostępnia szczegółowe callbacki zdarzeń dla każdego etapu cyklu życia SSH.
| Zdarzenie | Wywoływane gdy |
|---|---|
OnSSHConnect | połączenie SSH zostało nawiązane |
OnSSHDisconnect | połączenie SSH zostaje zamknięte (z powodem i kodem) |
OnSSHError | wystąpił błąd SSH |
OnSSHAuthSuccess / OnSSHAuthFailure | uwierzytelnianie zakończyło się sukcesem lub niepowodzeniem |
OnSSHHostKey | klucz hosta wymaga weryfikacji (akceptuj/odrzuć) |
OnSSHChannelData | odebrano dane (stdout) na kanale |
OnSSHChannelExtendedData | odebrano rozszerzone dane (stderr) na kanale |
OnSSHChannelExitStatus | odebrano kod wyjścia zdalnego polecenia |
OnSSHChannelExitSignal | zdalny proces zakończony sygnałem (z nazwą sygnału) |
OnSSHKeyboardInteractive | serwer żąda odpowiedzi keyboard-interactive |
OnSSHAuthBanner | serwer wysyła wiadomość banera uwierzytelniania |
Pełny przykład: skrypt automatycznego wdrożenia
W pełni skonfigurowany klient SSH, który łączy się z uwierzytelnianiem kluczem, uruchamia polecenia wdrożeniowe i przechwytuje status wyjścia.
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;
