Sid D 4 Posted June 1, 2022 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
Remy Lebeau 1393 Posted June 2, 2022 (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 June 2, 2022 by Remy Lebeau 1 Share this post Link to post
Fr0sT.Brutal 900 Posted June 2, 2022 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
Sid D 4 Posted June 2, 2022 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
Sid D 4 Posted June 2, 2022 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
Remy Lebeau 1393 Posted June 2, 2022 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
Sid D 4 Posted June 2, 2022 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
Remy Lebeau 1393 Posted June 3, 2022 (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 June 3, 2022 by Remy Lebeau Share this post Link to post
Sid D 4 Posted June 3, 2022 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
Sid D 4 Posted June 3, 2022 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
Remy Lebeau 1393 Posted June 4, 2022 (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 June 4, 2022 by Remy Lebeau Share this post Link to post