Reputation: 123
I am working with D5 ( thats a fact ). I have Indy9 installed.
I'm trying to receive data of IdMappedPortTCP
on port 8041 (SSL) and redirect the data to a Tserversocket
on port 8040. So I will have support of SSL over Tserversocket
.
I use the following code:
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;
If I don't use SSL everything is fine. But when I use SSL teh request never comes to the port 8040 encrypted and I need it not encrypted so I can proccess it.
Upvotes: 1
Views: 863
Reputation: 598424
It is not clear from your description whether TServerSocket
is using SSL on port 8040 or not. It makes a big difference in how you set up TIdMappedPortTCP
. However, from your description, you have the MappedPort
and DefaultPort
property assignments backwards, at least. DefaultPort
is the port that TIdMappedPortTCP
listens on, so it should be 8041. MappedPort
is the port that TIdMappedPortTCP
connects to, so it should be 8040.
It is not common to have unencrypted and encrypted connections on the same port. Most protocols use separate ports. Is that the case here? Is port 8040 unencrypted, and port 8041 encrypted?
If you want TIdMappedPortTCP
to accept encrypted and unencrypted clients on separate ports, you need to add 2 entries to the TIdMappedPortTCP.Bindings
collection, one for each port, and not use the DefaultPort
property at all. In the TIdMappedPortTCP.OnConnect
event, you can detect which port the client connected to, and then configure the AThread.OutboundClient
accordingly before it connects to TServerSocket
.
It is not wise to have unencrypted and encrypted clients connect to the same port. In that scenario, you have to sniff the first few bytes to know if the client is sending an SSL handshake or not, and then act accordingly. It is easier to just use separate ports instead. However, some protocols do allow a client to connect to an unencrypted port and then send a command to activate encryption when needed. In that scenario, you would only need 1 port in TIdMappedPortTCP
, so you can either define 1 Binding
or use DefaultPort
.
TIdMappedPortTCP
is primarily intended to be a straight passthrough of raw bytes back and forth between the client and the target server. If TServerSocket
is using SSL and you want the client to talk to TServerSocket
using SSL properly, you should not be using TIdServerIOHandlerSSL
at all. Let TIdMappedPortTCP
pass the client's raw encrypted data as-is to TServerSocket
, and vice versa. They should establish a secure session with each other, not with you. This is especially important if either one of them performs peer identity validation.
If you need to process encrypted data that is being exchanged between the client and TServerSocket
, you have to decrypt and re-encrypt the data as it passes through TIdMappedPortTCP
(which means you are acting as a man-in-the-middle attacker, which peer validation is meant to prevent). To do that, you have to establish separate SSL sessions between the client and TIdMappedPortTCP
, and between TIdMappedPortTCP
and TServerSocket
. Assigning a TIdServerIOHandlerSSL
to TIdMappedPortTCP
only facilitates the session with the client. You have to manually setup a session with TServerSocket
. To do that, you have to manually assign a new TIdSSLIOHandlerSocket
object to the AThread.OutboundClient.IOHandler
property in the OnConnect
event. TIdMappedPortTCP
will not handle that for you.
If, however, TServerSocket
is not using SSL, and you are using TIdMappedPortTCP
as an SSL gateway into TServerSocket
, then you can skip the OutboundClient.IOHandler
assignment, since you would only need 1 SSL session, between TIdMappedPortTCP
and the client.
Now, with that said, there are some problems in Indy 9. The TIdSSLIOHandlerOpenSSL.PassThrough
property is False by default (thus assuming encryption is initially active), and TIdServerIOHandlerSSL
assumes that every accepted client connection is using SSL, even if it really is not. If an unencrypted client connects to TIdMappedPortTCP
with TIdServerIOHandlerSSL
assigned, the client will not be handled correctly. These issues were fixed in Indy 10. But in Indy 9, you will not be able to handle encrypted and unencrypted clients in the same TIdMappedPortTCP
component. If you are only dealing with encrypted clients though, you won't run into a problem. Otherwise, create 2 TIdMappedPortTCP
components, one listening on an unencrypted port, the other listening on an encrypted port. They can share the same event handlers. If needed, you can use the AThread.Connection.Socket.Binding.Port
property to know which port the client is connected to.
Upvotes: 0