Suportado por
Navegadores Web
O suporte a SSL é baseado na implementação do Indy, portanto você precisa implantar as bibliotecas openssl para utilizar este recurso.
O TsgcWebSocketClient suporta o Microsoft SChannel, então não há necessidade de implantar as bibliotecas openssl para windows 32 e 64 bits se a opção SChannel for selecionada no WebSocket Client.
Server Side
Para habilitar este recurso, você precisa habilitar a seguinte propriedade:
SSL/ Enable
Há outras propriedades que você precisa definir:
SSLOptions/ CertFile/ KeyFile/ RootCertFile: você precisa de um certificado no formato .PEM para criptografar as comunicações websocket.
SSLOptions/ Password: isto é opcional e só é necessário se o certificado tiver uma senha.
SSLOptions/ Port: porta usada em conexões SSL.
Lado do Cliente
Para habilitar este recurso, você precisa habilitar a seguinte propriedade:
TLS/ Enable
OpenSSL
Por padrão, os componentes de cliente e servidor baseados em Indy utilizam as bibliotecas openSSL ao conectar a servidores websocket seguros.
O Indy suporta apenas a API OpenSSL 1.0.2, então a API 1.1 não é suportada. Se você compilar o sgcWebSockets com nossa biblioteca Indy personalizada, você pode fazer uso da API 1.1 e selecionar a versão TLS 1.3. Basta selecionar nas propriedades OpenSSL_Options qual API OpenSSL você gostaria de usar:
oslAPI_1_0: esta é a API Indy padrão, você pode usar o pacote Indy padrão com as bibliotecas openssl 1.0.2.
oslAPI_1_1: selecione apenas se você estiver compilando o sgcWebSockets com nossa biblioteca Indy personalizada (Enterprise Edition). Usará as bibliotecas openssl 1.1.1.
oslAPI_3_0: selecione apenas se você estiver compilando o sgcWebSockets com nossa biblioteca Indy personalizada (Enterprise Edition). Utilizará as bibliotecas openssl 3.0.0.
ECDHE: permite que você habilite o ECDHE para TLS 1.2 (conexões mais seguras).
Eventos
Há 2 eventos que podem ser usados para personalizar suas configurações SSL:
Este evento é gerado antes do handler SSL ser criado; você pode criar aqui seu próprio SSL Handler (precisa ser herdado de TIdServerIOHandlerSSLBase ou TIdIOHandlerSSLBase) e definir as propriedades necessárias
procedure OnServerSSLGetHandler(Sender: TObject; aType: TwsSSLHandler; var aSSLHandler:
TIdServerIOHandlerSSLBase);
begin
aSSLHandler := TCustomSSLHandler.Create(nil);
...
end;
Se nenhum objeto SSL personalizado tiver sido criado, um é criado por padrão usando o handler OpenSSL. Você pode acessar as propriedades do SSL Handler e modificá-las se necessário.
procedure OnSSLAfterCreateHandler(Sender: TObject; aType: TwsSSLHandler; aSSLHandler:
TIdServerIOHandlerSSLBase);
begin
TIdServerIOHandlerSSLOpenSSL(aSSLHandler).SSLOptions.Method := sslvTLSv1_2;
end;
Microsoft SChannel
A partir do sgcWebSockets 4.2.6 você pode usar SChannel em vez do openssl (apenas para windows a partir do Windows 7+). Isso significa que não há necessidade de implantar as bibliotecas openssl. O TLS 1.0 é suportado a partir do windows 7, mas se você precisar de implementações mais modernas como TLS 1.2 no Windows 7, deve habilitar TLS 1.1 e TLS 1.2 no Registro do Windows.
Requer a Edição Professional do Delphi 2010 (ou a Edição Enterprise para Delphi 7, 2007 e 2009).
Recarregando o certificado sem reiniciar
Quando o certificado do servidor é renovado (por exemplo, por um cliente ACME ou Let's Encrypt), chame o método ReloadCertificates em vez de parar o servidor. Os novos handshakes TLS usam o novo certificado, e as conexões que já estão abertas continuam funcionando com o antigo até serem fechadas. Está disponível em TsgcWebSocketServer, TsgcWebSocketHTTPServer, TsgcWebSocketProxyServer e TsgcWebSocketServer_HTTPAPI.
Sobrescreva os arquivos de certificado e de chave no próprio local, ou atribua novos valores a SSLOptions.CertFile, KeyFile, RootCertFile e Password (no servidor http.sys, SSLOptions.Hash e CertStoreName) e, em seguida, chame ReloadCertificates. Ele pode ser chamado a partir de qualquer thread enquanto o servidor estiver ativo, e não faz nada se o servidor não estiver ativo ou se o SSL estiver desabilitado. O novo certificado e a chave privada são carregados e verificados antes de qualquer alteração; se não corresponderem, uma exceção é gerada e o servidor continua servindo o certificado anterior. Somente o certificado é recarregado: as demais SSLOptions (lista de cifras, versões do TLS e assim por diante) e as alterações feitas em OnSSLAfterCreateHandler mantêm seus valores em execução, e alterá-las ainda exige uma reinicialização.
Os servidores baseados em Indy recarregam o certificado com OpenSSL (uma thread por conexão, IOCP no Windows e EPOLL no Linux), com SChannel e com o Native TLS do sgc (thread e IOCP/EPOLL). Um TLS Provider personalizado conectado aos motores IOCP/EPOLL recarrega por meio de seu DoCreateTLSContext. Com o Indy original (e não o fork Indy do sgc), o handler OpenSSL clássico não consegue recarregar e ReloadCertificates gera uma exceção "not supported". Com o Native TLS, os tickets de sessão TLS emitidos antes do recarregamento não são retomados depois dele, de modo que os clientes simplesmente fazem um handshake completo.
No servidor http.sys (TsgcWebSocketServer_HTTPAPI), quando BindingOptions.ConfigureSSLCertificate é True (o padrão), ReloadCertificates refaz o binding do certificado de cada binding SSL de forma atômica nos casos em que o Windows oferece suporte. Ele exige os mesmos direitos de administrador necessários para iniciar o servidor com SSL, e as conexões estabelecidas não são afetadas. Quando ConfigureSSLCertificate é False, o binding é gerenciado fora do componente (netsh); portanto, ReloadCertificates gera uma exceção e o binding deve ser atualizado com netsh. No .NET, o servidor http.sys é executado sobre HttpListener, que não pode revincular o certificado: o binding é sempre gerenciado com netsh, portanto, enquanto o servidor estiver ativo com https, ReloadCertificates gera NotSupportedException e o certificado deve ser renovado com 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;
Veja também o método ReloadCertificates.