我正在使用D5 (这是事实)。我安装了Indy9。我试图在端口8041 (SSL)上接收IdMappedPortTCP的数据,并将数据重定向到端口8040上的Tserversocket。因此,我将在Tserversocket上支持SSL。
我使用以下代码:
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,而且我需要它没有加密,所以我可以处理它。
发布于 2015-10-09 18:18:42
从您的描述中不清楚TServerSocket是否在端口8040上使用SSL。这对您设置TIdMappedPortTCP的方式有很大的不同。但是,根据您的描述,至少可以向后分配MappedPort和DefaultPort属性。DefaultPort是TIdMappedPortTCP监听的端口,所以应该是8041。MappedPort是TIdMappedPortTCP连接到的端口,所以应该是8040。
在同一个端口上有未加密和加密的连接并不常见。大多数协议使用单独的端口。这里就是这样吗?端口8040未加密,端口8041加密吗?
如果希望TIdMappedPortTCP在单独的端口上接受加密和未加密的客户端,则需要向TIdMappedPortTCP.Bindings集合中添加2个条目,每个端口一个条目,而根本不使用DefaultPort属性。在TIdMappedPortTCP.OnConnect事件中,您可以检测到客户端连接到哪个端口,然后在AThread.OutboundClient连接到TServerSocket之前相应地配置它。
让未加密和加密的客户端连接到同一个端口是不明智的。在这种情况下,您必须嗅探前几个字节,才能知道客户端是否正在发送SSL握手,然后采取相应的行动。只使用单独的端口就更容易了。但是,有些协议确实允许客户端连接到未加密的端口,然后在需要时发送命令以激活加密。在这种情况下,您只需要TIdMappedPortTCP中的一个端口,所以您可以定义一个Binding或使用DefaultPort。
TIdMappedPortTCP的主要目的是在客户机和目标服务器之间来回传递原始字节。如果TServerSocket正在使用SSL,并且希望客户端正确地使用SSL与TServerSocket对话,则根本不应该使用TIdServerIOHandlerSSL。让TIdMappedPortTCP将客户机的原始加密数据以原样传递给TServerSocket,反之亦然。他们应该建立一个安全的会话彼此,而不是与你。如果其中任何一个执行对等身份验证,则这一点尤为重要。
如果您需要处理客户端和TServerSocket之间正在交换的加密数据,则必须在数据通过TIdMappedPortTCP时解密和重新加密数据(这意味着您正在充当中间人攻击者,这是对等验证的目的所在)。为此,您必须在客户端和TIdMappedPortTCP之间以及TIdMappedPortTCP和TServerSocket之间建立单独的SSL会话。将TIdServerIOHandlerSSL分配给TIdMappedPortTCP只会促进与客户端的会话。您必须使用TServerSocket手动设置会话。要做到这一点,您必须手动将一个新的TIdSSLIOHandlerSocket对象分配给OnConnect事件中的AThread.OutboundClient.IOHandler属性。TIdMappedPortTCP不会帮你处理这件事。
但是,如果TServerSocket没有使用SSL,并且使用TIdMappedPortTCP作为进入TServerSocket的SSL网关,那么您可以跳过OutboundClient.IOHandler分配,因为在TIdMappedPortTCP和客户端之间只需要一个SSL会话。
现在,尽管如此,Indy 9中还是存在一些问题。默认情况下,TIdSSLIOHandlerOpenSSL.PassThrough属性是假的(因此假设加密最初是活动的),而TIdServerIOHandlerSSL假设每个可接受的客户端连接都在使用SSL,即使它确实不是。如果未加密的客户端连接到TIdMappedPortTCP并分配了TIdServerIOHandlerSSL,则客户端将无法正确处理。这些问题在Indy 10中得到了解决,但是在Indy 9中,您将无法在同一个TIdMappedPortTCP组件中处理加密和未加密的客户端。但是,如果您只处理加密的客户端,则不会遇到问题。否则,创建2个TIdMappedPortTCP组件,一个侦听未加密端口,另一个侦听加密端口。它们可以共享相同的事件处理程序。如果需要,您可以使用AThread.Connection.Socket.Binding.Port属性来知道客户端连接到哪个端口。
https://stackoverflow.com/questions/33037054
复制相似问题