Delphi 将 SSL tcp 数据重定向到其他端口 no ssl

Delphi Redirect SSL tcp data to other port no ssl

我正在使用 D5(这是事实)。我安装了 Indy9。 我正在尝试在端口 8041 (SSL) 上接收 IdMappedPortTCP 的数据,并将数据重定向到端口 8040 上的 Tserversocket。所以我将通过 Tserversocket.[= 支持 SSL 15=]

我使用以下代码:

var
  masterdir:String;
begin
  masterdir:=Extractfilepath(paramstr(0));
  IdMappedPortTCP1.Active:=false;

  datamodule2.IdMappedPortTCP1.MappedHost:='192.168.0.3';
  datamodule2.IdMappedPortTCP1.MappedPort:=8041;
  datamodule2.IdMappedPortTCP1.DefaultPort:=8040;

  IdServerIOHandlerSSL1.SSLOptions.RootCertFile:=masterdir+'mycert.pem';
  IdServerIOHandlerSSL1.SSLOptions.CertFile:=masterdir+'mycert.pem';
  IdServerIOHandlerSSL1.SSLOptions.KeyFile:=masterdir+'key.pem';
  IdMappedPortTCP1.IOHandler:=IdServerIOHandlerSSL1;
  IdMappedPortTCP1.Active:=true;
end;

如果我不使用 SSL,一切都很好。但是当我使用 SSL 时,请求永远不会到达加密的端口 8040,我需要它不加密,所以我可以处理它。

从您的描述中不清楚 TServerSocket 是否在端口 8040 上使用 SSL。它对您设置 TIdMappedPortTCP 的方式有很大影响。但是,根据您的描述,您至少有 MappedPortDefaultPort 属性 分配。 DefaultPortTIdMappedPortTCP监听的端口,所以应该是8041。MappedPortTIdMappedPortTCP连接的端口,所以应该是8040。

在同一个端口上同时存在未加密和加密连接的情况并不常见。大多数协议使用单独的端口。这里是这样吗? 8040端口是否未加密,8041端口是否加密?

如果您希望 TIdMappedPortTCP 在不同的端口上接受加密和未加密的客户端,您需要向 TIdMappedPortTCP.Bindings 集合添加 2 个条目,每个端口一个,而不是使用 DefaultPort 属性 完全没有。在TIdMappedPortTCP.OnConnect事件中,可以检测客户端连接到哪个端口,然后在AThread.OutboundClient连接到TServerSocket.

之前进行相应的配置

将未加密和加密的客户端连接到同一个端口是不明智的。在这种情况下,您必须嗅探前几个字节以了解客户端是否正在发送 SSL 握手,然后采取相应行动。只使用单独的端口更容易。但是,某些协议确实允许客户端连接到未加密的端口,然后在需要时发送命令以激活加密。在这种情况下,您只需要 TIdMappedPortTCP 中的 1 个端口,因此您可以定义 1 Binding 或使用 DefaultPort.

TIdMappedPortTCP 主要用于在客户端和目标服务器之间来回直接传递原始字节。如果 TServerSocket 使用 SSL 并且您希望客户端 正确地 使用 SSL 与 TServerSocket 通信,您根本不应该使用 TIdServerIOHandlerSSL。让 TIdMappedPortTCP 将客户端的原始加密数据按原样传递给 TServerSocket,反之亦然。他们应该彼此建立安全会话,而不是与您建立安全会话。如果其中任何一个执行对等身份验证,这一点尤其重要。

如果您需要处理在客户端和 TServerSocket 之间交换的加密数据,您必须在数据通过 TIdMappedPortTCP 时解密并重新加密(这意味着您是充当中间人攻击者,同行验证旨在防止)。为此,您必须在客户端和 TIdMappedPortTCP 之间以及 TIdMappedPortTCPTServerSocket 之间建立单独的 SSL 会话。将 TIdServerIOHandlerSSL 分配给 TIdMappedPortTCP 只会促进与客户的会话。您必须手动设置与 TServerSocket 的会话。为此,您必须手动将新的 TIdSSLIOHandlerSocket 对象分配给 OnConnect 事件中的 AThread.OutboundClient.IOHandler 属性。 TIdMappedPortTCP 不会为您处理。

但是,如果 TServerSocket 没有使用 SSL,而您使用 TIdMappedPortTCP 作为通向 TServerSocket 的 SSL 网关,那么您可以跳过 OutboundClient.IOHandler 分配,因为您只需要 1 个 SSL 会话,在 TIdMappedPortTCP 和客户端之间。

现在,话虽如此,Indy 9 中存在一些问题。TIdSSLIOHandlerOpenSSL.PassThrough 属性 默认为 False(因此假设加密最初处于活动状态),并且 TIdServerIOHandlerSSL 假设每个 接受的客户端连接都在使用 SSL,即使它确实不是。如果 未加密 客户端连接到 TIdMappedPortTCP 并分配了 TIdServerIOHandlerSSL,则客户端将无法正确处理。这些问题已在 Indy 10 中修复。但在 Indy 9 中,您将无法在同一个 TIdMappedPortTCP 组件中处理加密和未加密的客户端。但是,如果您只处理加密客户端,则不会 运行 成为问题。否则,创建 2 TIdMappedPortTCP 个组件,一个侦听未加密的端口,另一个侦听加密的端口。他们可以共享相同的事件处理程序。如果需要,您可以使用 AThread.Connection.Socket.Binding.Port 属性 来了解客户端连接到哪个端口。