delphi 在TIdCmdTcpServer中建立连接后启动TLS

ppcbkaq5  于 2023-05-22  发布在  其他
关注(0)|答案(1)|浏览(167)

在 Delphi 10.1中,我们使用TIdCmdTCPServerTIdServerIOHandlerSSLOpenSSL服务器端以及TIdTCPClientTIdSSLIOHandlerSocketOpenSSL客户端。
在调用FTCPClient.Connect之前将Passthrough设置为false,我可以成功地建立加密连接,并且

procedure TIndyTcpCommandReceiver.TCPServerConnect(AContext: TIdContext);
begin
  if AContext.Connection.IOHandler is TIdSSLIOHandlerSocketOpenSSL then
    TIdSSLIOHandlerSocketOpenSSL(AContext.Connection.IOHandler).PassThrough := false;
end;

我们将相同的server.exe部署到不同的服务器。其中一些安装了证书,另一些则没有。

如果有证书,我只想建立加密连接。

我按照https://stackoverflow.com/a/46412958/865602的说明修改了我的客户端代码,最初设置为PassThrough := true,一旦建立了连接,设置为PassThrough := false

procedure TTCPConnector.Connect;
begin
  FSSLIOHandler.PassThrough := true;
  FTCPClient.Connect(FServerName, FPort); // succeeds
  FSSLIOHandler.PassThrough := false ; // fails
end;

但是,我找不到关于如何修改服务器端代码的答案。如果不使用TCPServerConnect事件中的代码,我只能建立初始连接。

在客户端将Passthrough设置为false后,我必须在服务器中进行哪些更改才能切换到加密连接?

suzh9iv8

suzh9iv81#

我只想建立一个加密连接,如果有证书的话。
然后,您需要将协议更改为STARTTLS模型,在该模型中,客户端在实际执行此操作之前向服务器请求加密连接的权限。
让客户端在两端与PassThrough=True正常连接。然后,让客户端向服务器发送一个未加密的命令,并让服务器根据是否安装了证书来响应是授予还是拒绝权限。如果被授权,那么双方都可以设置PassThrough=False来加密连接,然后再交换任何进一步的数据。
例如:

procedure TIndyTcpCommandReceiver.TCPServerConnect(AContext: TIdContext);
begin
  if AContext.Connection.IOHandler is TIdSSLIOHandlerSocketBase then
    TIdSSLIOHandlerSocketBase(AContext.Connection.IOHandler).PassThrough := true;
end;

procedure TIndyTcpCommandReceiver.TCPServerSTARTTLSCommand(ASender: TIdCommand);
begin
  if (AContext.Connection.IOHandler is TIdSSLIOHandlerSocketBase) and
     TIdSSLIOHandlerSocketBase(AContext.Connection.IOHandler).PassThrough and
     (Certificate Is Installed) then
  begin
    ASender.Reply.SetReply('OK', 'Send TLS handshake');
    ASender.SendReply;
    TIdSSLIOHandlerSocketBase(AContext.Connection.IOHandler).PassThrough := False;
  end
  else
    ASender.Reply.SetReply('NO', 'Dont send TLS handshake');
end;
procedure TTCPConnector.Connect;
begin
  FSSLIOHandler.PassThrough := true;
  FTCPClient.Connect(FServerName, FPort);
  if FTCPClient.SendCmd('STARTTLS', '') = 'OK' then
    FSSLIOHandler.PassThrough := false;
end;

相关问题