SChannel Indy Server Delphi

· Funkcje

Przez lata deweloperzy Delphi wdrażający serwery z TLS na Windows zmagali się z tym samym wyzwaniem: dołączaniem odpowiednich bibliotek OpenSSL do aplikacji. Niezgodności wersji, brakujące biblioteki DLL w czasie działania i ręczne aktualizacje po poradach bezpieczeństwa były stałym źródłem problemów w środowiskach produkcyjnych.

Począwszy od sgcWebSockets 2026.3.0 komponenty serwera oparte na Indy — TsgcWebSocketServer i TsgcWebSocketHTTPServer — mogą używać Windows SChannel (Secure Channel) jako dostawcy TLS. SChannel to natywna implementacja TLS wbudowana w każdą wersję systemu Windows. Nie wymaga zewnętrznych bibliotek DLL, integruje się bezpośrednio z magazynem certyfikatów systemu Windows i automatycznie otrzymuje poprawki bezpieczeństwa przez Windows Update.

Ten artykuł opisuje, jak konfigurować i wdrażać serwery oparte na SChannel w aplikacjach Delphi.

Dlaczego SChannel po stronie serwera?

SChannel eliminuje najczęstsze problemy wdrożeniowe związane z TLS na serwerach Windows.

Zero zewnętrznych zależności
SChannel jest wbudowany w system Windows. Żadnych libeay32.dll, ssleay32.dll, libcrypto ani libssl. Twój instalator jest mniejszy, a wdrożenie prostsze.
Magazyn certyfikatów Windows
Używaj certyfikatów już zainstalowanych i zarządzanych przez system operacyjny. Nie trzeba kopiować plików PEM — wystarczy odwołać się do certyfikatu przez jego odcisk.
Automatyczne aktualizacje bezpieczeństwa
Ulepszenia TLS i poprawki bezpieczeństwa są stosowane przez Windows Update. Bez ręcznych aktualizacji bibliotek, bez ponownych wdrożeń z powodu CVE OpenSSL.

Szybki start — 5 kroków

Włączenie SChannel na serwerze wymaga jedynie kilku zmian właściwości:

  1. Włącz SSL — ustaw właściwość SSL na True.
  2. Wybierz SChannel jako IOHandler — ustaw SSLOptions.IOHandler na iohSChannel.
  3. Wybierz wersję TLS — ustaw SSLOptions.Version na żądaną wersję. tls1_2 jest zalecane dla większości wdrożeń.
  4. Ustaw port — ustaw SSLOptions.Port i Port na port nasłuchiwania (zazwyczaj 443).
  5. Skonfiguruj certyfikat — podaj certyfikat przez magazyn certyfikatów Windows (odcisk) lub plik PFX.

Metoda 1: certyfikat z magazynu Windows

Jeśli certyfikat jest już zainstalowany w magazynie certyfikatów Windows, wystarczy podać jego odcisk (thumbprint). Jest to zalecane podejście dla serwerów produkcyjnych i usług Windows.

Znajdź odcisk certyfikatu

Otwórz PowerShell i wylistuj certyfikaty w osobistym magazynie komputera lokalnego:

PS C:\> dir cert:\localmachine\my
Directory: Microsoft.PowerShell.Security\Certificate::localmachine\my
Thumbprint                                Subject
----------                                -------
C12A8FC8AE668F866B48F23E753C93D357E9BE10  CN=*.mydomain.com
A7F3D2E1B9C84A6D5E0F123456789ABCDEF01234  CN=api.mydomain.com

Skopiuj 40-znakowy szesnastkowy odcisk certyfikatu, którego chcesz użyć.

Konfiguruj serwer

var
  oServer: TsgcWebSocketHTTPServer;
begin
  oServer := TsgcWebSocketHTTPServer.Create(nil);
  // Enable TLS with SChannel
  oServer.SSL := True;
  oServer.SSLOptions.IOHandler := iohSChannel;
  oServer.SSLOptions.Version := tls1_2;
  oServer.SSLOptions.Port := 443;
  oServer.Port := 443;
  // Point to the certificate in the Windows Store
  oServer.SSLOptions.SChannel_Options.CertHash :=
    'C12A8FC8AE668F866B48F23E753C93D357E9BE10';
  oServer.SSLOptions.SChannel_Options.CertStoreName := scsnMY;
  oServer.SSLOptions.SChannel_Options.CertStorePath := scspStoreLocalMachine;
  // Start listening
  oServer.Active := True;
end;

Wskazówka produkcyjna. Zawsze używaj scspStoreLocalMachine dla serwerów wdrożonych jako usługi Windows. Magazyn komputera lokalnego jest dostępny niezależnie od konta użytkownika uruchamiającego usługę, podczas gdy scspStoreCurrentUser jest powiązany z profilem zalogowanego użytkownika.

Opcje magazynu certyfikatów

Nazwa magazynu Stała Zawartość
Osobisty (MY) scsnMY Certyfikaty serwera z kluczami prywatnymi
Główny scsnRoot Zaufane główne urzędy certyfikacji
Zaufany scsnTrust Zaufane certyfikaty
CA scsnCA Pośrednie urzędy certyfikacji

Metoda 2: certyfikat z pliku PFX

Jeśli masz plik certyfikatu PFX (.pfx lub .p12), możesz go załadować bezpośrednio bez instalowania w magazynie certyfikatów Windows. SChannel zaimportuje certyfikat przy uruchamianiu serwera.

var
  oServer: TsgcWebSocketHTTPServer;
begin
  oServer := TsgcWebSocketHTTPServer.Create(nil);
  // Enable TLS with SChannel
  oServer.SSL := True;
  oServer.SSLOptions.IOHandler := iohSChannel;
  oServer.SSLOptions.Version := tls1_2;
  oServer.SSLOptions.Port := 443;
  oServer.Port := 443;
  // Load certificate from a PFX file
  oServer.SSLOptions.CertFile := 'c:\certificates\server.pfx';
  oServer.SSLOptions.Password := 'mypassword';
  // Start listening
  oServer.Active := True;
end;

Masz pliki PEM? SChannel akceptuje wyłącznie format PFX. Przekonwertuj certyfikat PEM i klucz prywatny jednym poleceniem:

openssl pkcs12 -inkey server.key -in server.crt -export -out server.pfx

Dokumentacja SChannel_Options

Właściwość podrzędna SSLOptions.SChannel_Options udostępnia wszystkie ustawienia serwera specyficzne dla SChannel.

Właściwość Typ Opis
CertHash String 40-znakowy szesnastkowy odcisk certyfikatu zainstalowanego w magazynie certyfikatów Windows.
CertStoreName Enum Magazyn do przeszukania: scsnMY (osobisty), scsnRoot, scsnTrust, scsnCA.
CertStorePath Enum Lokalizacja magazynu: scspStoreLocalMachine (zalecane) lub scspStoreCurrentUser.
CipherList String Lista dozwolonych algorytmów szyfrowania oddzielonych dwukropkiem (np. CALG_AES_256:CALG_AES_128). Pozostaw puste, aby użyć wartości domyślnych systemu Windows.
UseLegacyCredentials Boolean Gdy True, używa starszej struktury SCHANNEL_CRED. Włącz dla Windows Server 2019 i wcześniejszych.

Konfiguracja wersji TLS

Kontroluj, którą wersję protokołu TLS serwer akceptuje, za pomocą właściwości SSLOptions.Version.

Wartość Protokół Zalecenie
tls1_3 TLS 1.3 Najwyższe bezpieczeństwo. Używaj, gdy wszystkie klienty go obsługują.
tls1_2 TLS 1.2 Zalecane dla większości wdrożeń produkcyjnych.
tls1_1 TLS 1.1 Starszy. Unikaj, chyba że wymagają go stare klienty.
tls1_0 TLS 1.0 Przestarzały. Niezalecany.
tlsUndefined TLS 1.0 – 1.2 Akceptuje TLS 1.0, 1.1 lub 1.2.
// Enforce TLS 1.2 minimum for modern security
oServer.SSLOptions.Version := tls1_2;
// Or use TLS 1.3 for the strongest encryption
oServer.SSLOptions.Version := tls1_3;

Konfiguracja zestawów szyfrów

Domyślnie SChannel używa ogólnosystemowej konfiguracji szyfrów zarządzanej przez system Windows. W środowiskach wymagających ściślejszej kontroli możesz ograniczyć dozwolone algorytmy.

// Restrict to AES-256 and AES-128 only
oServer.SSLOptions.SChannel_Options.CipherList :=
  'CALG_AES_256:CALG_AES_128';

Pozostaw właściwość CipherList pustą, aby przyjąć domyślną konfigurację szyfrów systemu Windows. Jest to odpowiednie dla większości wdrożeń, ponieważ Windows utrzymuje bezpieczny domyślny zestaw aktualizowany przez Windows Update.

Uwaga. Zbyt agresywne ograniczanie szyfrów może uniemożliwić połączenie niektórym klientom. Przetestuj dokładnie na oczekiwanych klientach przed wdrożeniem niestandardowych list szyfrów w środowisku produkcyjnym.

Zgodność ze starszymi wersjami systemu Windows

Komponent domyślnie używa nowoczesnego API SCH_CREDENTIALS. Na starszych wersjach systemu Windows (Server 2019 i wcześniejsze), które nie obsługują tego API, możesz przełączyć się na starszą strukturę poświadczeń.

// Enable legacy mode for Windows Server 2019 and earlier
oServer.SSLOptions.SChannel_Options.UseLegacyCredentials := True;

W większości przypadków komponent automatycznie wykrywa wersję systemu Windows i wybiera odpowiednie API. Używaj właściwości UseLegacyCredentials tylko wtedy, gdy serwer nie uruchamia się na starszej wersji systemu Windows.

SChannel kontra OpenSSL — kiedy używać którego

Obaj dostawcy TLS są w pełni obsługiwani. Właściwy wybór zależy od platformy wdrożeniowej i wymagań operacyjnych.

Feature SChannel OpenSSL
Wymagane zewnętrzne DLL Nie Tak
Magazyn certyfikatów Windows Natywny Nieobsługiwany
Automatyczne aktualizacje bezpieczeństwa Tak (Windows Update) Ręczna aktualizacja biblioteki
Wieloplatformowość Tylko Windows Windows, Linux, macOS
Formaty certyfikatów PFX + magazyn Windows PEM, PFX
TLS 1.0 – 1.3 Yes Yes

Podsumowanie. Jeśli serwer działa wyłącznie na Windows, SChannel jest prostszym i łatwiejszym w utrzymaniu wyborem. Jeśli potrzebujesz wsparcia wieloplatformowego, używaj iohOpenSSL. Przełączenie między nimi wymaga zmiany tylko właściwości IOHandler — żadne inne zmiany kodu nie są potrzebne.

Kompletny przykład: bezpieczny serwer WebSocket

W pełni skonfigurowany serwer WebSocket używający SChannel z certyfikatem z magazynu certyfikatów Windows.

uses
  sgcWebSocket_Server, sgcWebSocket_Classes;
var
  oServer: TsgcWebSocketHTTPServer;
begin
  oServer := TsgcWebSocketHTTPServer.Create(nil);
  Try
    // Server configuration
    oServer.Port := 443;
    // TLS configuration with SChannel
    oServer.SSL := True;
    oServer.SSLOptions.IOHandler := iohSChannel;
    oServer.SSLOptions.Version := tls1_2;
    oServer.SSLOptions.Port := 443;
    // Certificate from Windows Certificate Store
    oServer.SSLOptions.SChannel_Options.CertHash :=
      'C12A8FC8AE668F866B48F23E753C93D357E9BE10';
    oServer.SSLOptions.SChannel_Options.CertStoreName := scsnMY;
    oServer.SSLOptions.SChannel_Options.CertStorePath := scspStoreLocalMachine;
    // Assign WebSocket event handlers
    oServer.OnConnect := OnClientConnect;
    oServer.OnDisconnect := OnClientDisconnect;
    oServer.OnMessage := OnClientMessage;
    // Start the server
    oServer.Active := True;
    WriteLn('Secure WebSocket server listening on port 443 (SChannel TLS 1.2)');
    WriteLn('Press Enter to stop...');
    ReadLn;
  Finally
    oServer.Active := False;
    oServer.Free;
  End;
end;

Działa z oboma komponentami serwera

SChannel jest dostępny w obu komponentach serwera opartych na Indy. Konfiguracja jest identyczna.

Component Opis
TsgcWebSocketHTTPServer Serwer WebSocket ze wbudowanym serwerem HTTP. Idealny do połączonych API WebSocket + REST.
TsgcWebSocketServer Czysty serwer WebSocket oparty na Indy TCP. Najlepszy do dedykowanych punktów końcowych WebSocket.

Ważne uwagi