支持方
Web 浏览器
SSL 支持基于 Indy 实现,因此需要部署 openssl 库才能使用此功能。
TsgcWebSocketClient 支持 Microsoft SChannel,因此在 WebSocket 客户端中选择 SChannel 选项后,无需为 Windows 32 位和 64 位部署 openssl 库。
服务器端
要启用此功能,您需要启用以下属性:
SSL/ 启用
还有其他需要定义的属性:
SSLOptions/ CertFile/ KeyFile/ RootCertFile:您需要一个 .PEM 格式的证书来加密 WebSocket 通信。
SSLOptions/ Password:此项为可选,仅在证书有密码时需要。
SSLOptions/ Port:SSL 连接使用的端口。
客户端
要启用此功能,您需要启用以下属性:
TLS / 启用
OpenSSL
默认情况下,基于 Indy 的客户端和服务器组件在连接到安全 WebSocket 服务器时使用 OpenSSL 库。
Indy 仅支持 1.0.2 OpenSSL API,因此不支持 API 1.1。若您使用我们的自定义 Indy 库编译 sgcWebSockets,则可使用 API 1.1 并选择 TLS 1.3 版本。只需在 OpenSSL_Options 属性中选择您希望使用的 OpenSSL API 即可:
oslAPI_1_0: 这是默认的 Indy API,您可以使用带有 openssl 1.0.2 库的标准 Indy 包。
oslAPI_1_1:仅在使用我们的自定义 Indy 库(企业版)编译 sgcWebSockets 时选择。将使用 openssl 1.1.1 库。
oslAPI_3_0:仅在使用我们的自定义 Indy 库(Enterprise Edition)编译 sgcWebSockets 时才选择此选项。将使用 openssl 3.0.0 库。
ECDHE: 允许您为 TLS 1.2 启用 ECDHE(更安全的连接)。
事件
有两个事件可用于自定义 SSL 设置:
此事件在创建 SSL 处理程序之前引发,您可以在此创建自己的 SSL 处理程序(需要继承自 TIdServerIOHandlerSSLBase 或 TIdIOHandlerSSLBase)并设置所需的属性。
procedure OnServerSSLGetHandler(Sender: TObject; aType: TwsSSLHandler; var aSSLHandler:
TIdServerIOHandlerSSLBase);
begin
aSSLHandler := TCustomSSLHandler.Create(nil);
...
end;
如果未创建自定义 SSL 对象,则默认使用 OpenSSL 处理程序创建一个。您可以根据需要访问 SSL 处理程序属性并进行修改。
procedure OnSSLAfterCreateHandler(Sender: TObject; aType: TwsSSLHandler; aSSLHandler:
TIdServerIOHandlerSSLBase);
begin
TIdServerIOHandlerSSLOpenSSL(aSSLHandler).SSLOptions.Method := sslvTLSv1_2;
end;
Microsoft SChannel
从 sgcWebSockets 4.2.6 起,您可以使用 SChannel 代替 openssl(仅适用于 Windows 7 及以上版本的 Windows)。这意味着 无需部署 openssl 库。Windows 7 支持 TLS 1.0,但如果您需要 在 Windows 7 上使用 TLS 1.2 等更现代的实现, 必须在 Windows 注册表中启用 TLS 1.1 和 TLS 1.2。
需要 Delphi 2010 Professional 版(Delphi 7、2007 和 2009 需要 Enterprise 版)。
无需重启即可重新加载证书
当服务器证书续期时(例如由 ACME 或 Let's Encrypt 客户端续期),请调用 ReloadCertificates 方法,而不是停止服务器。新的 TLS 握手使用新证书,已经打开的连接在关闭之前继续使用旧证书正常工作。该方法适用于 TsgcWebSocketServer、TsgcWebSocketHTTPServer、TsgcWebSocketProxyServer 和 TsgcWebSocketServer_HTTPAPI。
请原地覆盖证书和密钥文件,或者为 SSLOptions.CertFile、KeyFile、RootCertFile 和 Password 赋新值(在 http.sys 服务器上则为 SSLOptions.Hash 和 CertStoreName),然后调用 ReloadCertificates。服务器处于激活状态时可以从任意线程调用它;如果服务器未激活或 SSL 已禁用,则不执行任何操作。新证书和私钥会在任何更改发生之前先加载并检查,因此如果两者不匹配,将引发异常,服务器继续使用之前的证书。仅重新加载证书:其他 SSLOptions(密码套件列表、TLS 版本等)以及在 OnSSLAfterCreateHandler 中所做的更改保持其运行时的值,更改这些内容仍需重启。
基于 Indy 的服务器使用 OpenSSL(每连接一个线程、Windows 上的 IOCP 和 Linux 上的 EPOLL)、SChannel 以及 sgc 原生 TLS(线程以及 IOCP/EPOLL)重新加载证书。接入 IOCP/EPOLL 引擎的自定义 TLS 提供程序(TLS Provider)通过其 DoCreateTLSContext 重新加载。使用原版 Indy(而非 sgc Indy 分支)时,经典 OpenSSL 处理程序无法重新加载,ReloadCertificates 会引发 "not supported" 异常。使用原生 TLS 时,重新加载之前签发的 TLS 会话票据在重新加载之后不会被恢复,因此客户端只需执行一次完整握手。
在 http.sys 服务器(TsgcWebSocketServer_HTTPAPI)上,当 BindingOptions.ConfigureSSLCertificate 为 True(默认值)时,ReloadCertificates 会在 Windows 支持的情况下以原子方式重新绑定每个 SSL 绑定的证书。它需要与启动带 SSL 的服务器相同的管理员权限,已建立的连接不受影响。当 ConfigureSSLCertificate 为 False 时,绑定由组件之外(netsh)管理,因此 ReloadCertificates 会引发异常,必须使用 netsh 更新绑定。在 .NET 中,http.sys 服务器运行在无法重新绑定证书的 HttpListener 之上,绑定始终通过 netsh 管理,因此当服务器以 https 处于活动状态时,ReloadCertificates 会引发 NotSupportedException,必须使用 netsh http update sslcert 更新证书。
// uses sgcWebSocket, Dialogs, SysUtils; field: oServer: TsgcWebSocketHTTPServer;
procedure TForm1.FormCreate(Sender: TObject);
begin
oServer := TsgcWebSocketHTTPServer.Create(Self);
oServer.Port := 80;
oServer.SSL := True;
oServer.SSLOptions.Port := 443;
oServer.SSLOptions.CertFile := 'C:\certs\fullchain.pem';
oServer.SSLOptions.KeyFile := 'C:\certs\privkey.pem';
oServer.Active := True;
end;
procedure TForm1.btnReloadClick(Sender: TObject);
begin
try
oServer.SSLOptions.CertFile := 'C:\certs\renewed\fullchain.pem';
oServer.SSLOptions.KeyFile := 'C:\certs\renewed\privkey.pem';
oServer.ReloadCertificates;
except
on E: Exception do
ShowMessage('Certificate reload failed: ' + E.Message);
end;
end;
另请参阅 ReloadCertificates 方法。