Jump to content
Sid D

TidTCPServer and TidTCPClient withh SSL/TLS enabled

Recommended Posts

Hi,

 

I’ve a question about TIdTCPServer and TIdTCPClient.

Can the same TIdTCPServer with SSL/TLS (implemented using TIdServerIOHandlerSSLOpenSSL) support both SSL and non-SSL TIdTCPClients.

By non-SSL TIdTCPClient, I mean that do not support SSL/TLS and do not use TIdSSLIOHandlerSocketOpenSSL component. This is for backwards compatibility.

 

I'm using Delphi 10.3 and 10.1.

 

Thanks!

Share this post


Link to post
Posted (edited)
7 hours ago, Sid D said:

Can the same TIdTCPServer with SSL/TLS (implemented using TIdServerIOHandlerSSLOpenSSL) support both SSL and non-SSL TIdTCPClients.

Yes. Define 2 separate ports in the server's Bindings collection, and then in the server's OnConnect event you can cast the AContext.Connection.IOHandler property to TIdSSLIOHandlerSocketBase and set its PassThrough property to True (SSL/TLS disabled) or False (SSL/TLS enabled) based on which port the client connected to, which you can get from the AContext.Binding.Port property.

 

Edited by Remy Lebeau
  • Thanks 1

Share this post


Link to post

Hmm, TLS handshake starts from constant prefix, in theory it should be possible to autodetect plain data or do TLS first

Share this post


Link to post

Hi Remy,

 

If there is no TIdSSLIOHandlerSocketOpenSSL component assigned on the TIdTCPClient side, setting the PassThrough  property to True on the Server side (per you explained above) throws the following error:

First chance exception at $76A6C3A2. Exception class EIdOSSLUnderlyingCryptoError with message
'Error accepting connection with SSL.
error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number'.

 

What can be the reason?

 

Thanks!

 

 

Share this post


Link to post
7 hours ago, Remy Lebeau said:

Yes. Define 2 separate ports in the server's Bindings collection, and then in the server's OnConnect event you can cast the AContext.Connection.IOHandler property to TIdSSLIOHandlerSocketBase and set its PassThrough property to True (SSL/TLS disabled) or False (SSL/TLS enabled) based on which port the client connected to, which you can get from the AContext.Binding.Port property.

 

Hi Remy,

 

If there is no TIdSSLIOHandlerSocketOpenSSL component assigned on the TIdTCPClient side, setting the PassThrough  property to True on the Server side (per you explained above) throws the following error:

First chance exception at $76A6C3A2. Exception class EIdOSSLUnderlyingCryptoError with message
'Error accepting connection with SSL.
error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number'.

 

What can be the reason?

 

Thanks!

Share this post


Link to post
1 hour ago, Sid D said:

If there is no TIdSSLIOHandlerSocketOpenSSL component assigned on the TIdTCPClient side, setting the PassThrough  property to True on the Server side (per you explained above) throws the following error:

That is simply not possible the way you describe.  The ONLY way you can get that error is during an SSL/TLS handshake, which is NOT performed when PassThrough is set to True (ie, pass-through raw data as-is) thus disabling SSL/TLS.  So, you MUST be setting PassThrough to False (ie, intercept data for SSL/TLS processing) in order to get that error.

 

Which version of Indy are you using?  IIRC, there was a bug in old versions where a server would set PassThrough to false for all clients, causing an SSL/TLS handshake for non-SSL/TLS clients.  But that was fixed a LONG time ago.

 

Share this post


Link to post
1 hour ago, Remy Lebeau said:

That is simply not possible the way you describe.  The ONLY way you can get that error is during an SSL/TLS handshake, which is NOT performed when PassThrough is set to True (ie, pass-through raw data as-is) thus disabling SSL/TLS.  So, you MUST be setting PassThrough to False (ie, intercept data for SSL/TLS processing) in order to get that error.

 

Which version of Indy are you using?  IIRC, there was a bug in old versions where a server would set PassThrough to false for all clients, causing an SSL/TLS handshake for non-SSL/TLS clients.  But that was fixed a LONG time ago.

 

Indy version is 10.6.2.5366. I checked on the Server side, PassThrough is True by default. 

Share this post


Link to post
Posted (edited)
22 hours ago, Sid D said:

I checked on the Server side, PassThrough is True by default. 

You should double-check that, since you clearly do have an SSL/TLS handshake being performed. TIdServerIOHandlerSSLOpenSSL.Accept() should be creating a new TIdSSLIOHandlerSocketOpenSSL whose PassThrough is True, so the server can then decide when it is best to set it to False (ie, when the client is connected to an implicit SSL port, or after receiving a STARTTLS-style command, etc).

 

Note that there was a bug where PassThrough was initialized as False in TIdSSLIOHandlerSocketBase, that was fixed a few years ago, I think that might have been after 10.6.2.5366.  You might consider upgrading to the latest version from Indy's GitHub repo and see if the problem continues, just to make sure you have all of the latest fixes.

Edited by Remy Lebeau

Share this post


Link to post
1 hour ago, Remy Lebeau said:

You should double-check that, since you clearly do have an SSL/TLS handshake being performed. TIdServerIOHandlerSSLOpenSSL.Accept() should be creating a new TIdSSLIOHandlerSocketOpenSSL whose PassThrough is True, so the server can then decide when it is best to set it to False (ie, when the client is connected to an implicit SSL port, or after receiving a STARTTLS-style command, etc).

 

Note that there was a bug where PassThrough was initialized as False in TIdSSLIOHandlerSocketBase, that was fixed a few years ago, I think that might have been after 10.6.2.5366.  You might consider upgrading to the latest version from Indy's GitHub repo and see if the problem continues, just to make sure you have all of the latest fixes.

Upon further testing with the following versions:

 

The error is thrown in the following combination:

Delphi 10.3 Update 3 and Indy version 10.6.2.5366

 

It works fine with the following versions:

Delphi 10.1 Berlin Update 1 and Indy Version 10.6.2.5341

 

So, definitely something wrong or bug in Delphi 10.3.3 or Indy version 10.6.2.5366.

 

Share this post


Link to post

Hi Remy - I have one other question. In the 'OnConnect' event of TIdTCPServer, is it possible to figure out from the incoming data if the handshake requested is on TLS or plain text? I was wondering if it is possible, then PassThrough = True/False can be set based on that and there will be no need to use the second port.

 

If possible, can you please provide an example?

 

Thanks!  

Share this post


Link to post
Posted (edited)
8 hours ago, Sid D said:

Upon further testing with the following versions:

 

The error is thrown in the following combination:

Delphi 10.3 Update 3 and Indy version 10.6.2.5366

 

It works fine with the following versions:

Delphi 10.1 Berlin Update 1 and Indy Version 10.6.2.5341

 

So, definitely something wrong or bug in Delphi 10.3.3 or Indy version 10.6.2.5366.

Unfortunately, those version numbers predate Indy's switch from SVN to GIT, when build number versioning was lost.  So I can't diff those versions to see what changed between them (unless you have dates on them, at least).  But the behavior should have improved from older to newer, not degraded.

5 hours ago, Sid D said:

In the 'OnConnect' event of TIdTCPServer, is it possible to figure out from the incoming data if the handshake requested is on TLS or plain text?

It is technically possible (you would have to peek - not read - the first handful of bytes to detect whether a SSL/TLS header is present, and if so then set PassThrough=False.

Quote

I was wondering if it is possible, then PassThrough = True/False can be set based on that and there will be no need to use the second port.

I do not recommend this approach.  You should use separate ports, one port with SSL/TLS enabled, and one port without.  It is just easier, safer, and more reliable that way.

Quote

If possible, can you please provide an example?

I posted an example in Indy's AToZed forum a few years ago (it was written for TIdHTTPServer, but you can adapt it for TIdTCPServer):

https://www.atozed.com/forums/thread-367-post-834.html#pid834

Edited by Remy Lebeau

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×