TROSocketOpenSSL slow

As a follow-on to SSL and Delphi server I have another issue. I’m using the ROSuperHttpServer, loading the certificate in the OnBeforeServerActivate event. It works perfectly well, when I do it on my Mac (or any apple device it seems) using Chrome, but as soon as someone tries to use a browser on a PC or Android device, it times out.

After investigating, I can see that it spends a huge amount of time in TROSocketOpenSSL.Read, because the call to SSL_read comes back as -1which it can do for several minutes and at the same time locking up the server (CPU usage goes to 99%) so the browser will time out. If I run it from a Mac, it comes back first time with a positive value (817 if that means anything) so the logic below the if result>0 then break line never happens.

Any idea what may cause this, or more importantly what I can do to fix it?

The Chrome on the Mac is Version 103.0.5060.53, and the one on the PC I tried is Version 109.0.5414.120, although the same thing seems to happen to any of the PCs we’ve tried using Edge as well.

Thanks

Hi,

What certificate you are using? self-signed or issued by trusted CA?
Does your certificate contain Subject Alt Name property?

if you are using self-signed certificate, it may hang at validation such certificates.
I can recommend to install .1557 (should be available on this week) and retest after putting auto-generated CA to trusted store.

check feature: Generation of self-signed certificates was improved in native RO servers topic for details.

It is a trusted (Let’s Encrypt) one, and yes is has a Subject alt name property (two, including a wildcard one).

I’m trying to get a sample to replicate it using the mega demo, but have yet to replicate it exactly. I’m using the MegaClientJS for that.

I have found that it hangs my app, after the service call, and it’s trying to send the result. TROPooledThread.IntExecute is the point it stops (if fOwner.fSemaphore.WaitFor) whilst it waits for the socket to read the ssl.

Hi,

Can you reproduce this issue with plain HTTP server too or is it reproduced with super HTTP server only?

I can, yes, I’ve been trying to track down which bit has the issue. I have modified the JS client for the mega demo, as attached, to include the option for SSL.
MegaDemoJSClient.html.zip (1.9 KB)
(though my version has the localhost replaced with my domain version). One problem with no changes to the server other than adding the certificate load, is this, maybe you could see if you get the same?

  1. Activate the Http Server (RO Socket), no SSL.
  2. Connect (JSON), call sum, see result.
  3. Deactivate server.
  4. Tick SSL, and the server activate again.
  5. Tick use SSL on client, connect, call sum, see result.
  6. Deactivate server. Just hangs the server in TROSocketOpenSSL.Shutdown

If you then change to the super Http server, and repeat the above, it does connect (step 2 above) as I can see the server events (I’ve added logging on the TROSocketOpenSSL class so can see it checks if SSL is enabled) but then if I try any of the methods, it doesn’t seem to do anything.

Hi,

I can reproduce this step. Looks like client-side doesn’t send close_notify shutdown alert as it should be according to /docs/man3.1/man3/SSL_shutdown.html

as a result, server-side sends close_notify shutdown alert to client in a loop

Logged as bugs://D19323.

I’ve spotted the update and am just playing with it. There’s an issue in the mega demo client. The line fCurrentTargetUri.URI := cbTargetUrl.Text; is in the wrong place (it tries this before it’s created), I moved it after the fCurrentTargetUri := TROUri.Create; line.

If that’s an easy fix, let me know and I’ll try it out.

You may want to add the SSL option to the JS client sample as attached above as well, that’s what I’m about to test.

Hi,

temporary workaround: allow only 10 attempts like

procedure TROSocketOpenSSL.Shutdown;
..
  l_cnt: Integer;//<-----------------added
..
      l_cnt := 0;  //<-----------------added
      repeat
..
          if l_cnt < 10 then //<-----------------added
            case SSL_get_error(fSSL, l_ret) of
              SSL_ERROR_WANT_READ,
              SSL_ERROR_WANT_WRITE,
              SSL_ERROR_WANT_ASYNC,
              SSL_ERROR_WANT_ASYNC_JOB: begin
                inc(l_cnt);  //<-----------------added
                Continue; // We just do busy waiting. Nothing clever
              end;

Thanks, yes that’s resolved that. I still have the original problem though. If I use the new self-certification stuff, it works great with the Delphi client as per the mega demo, but not with the JS client (it doesn’t accept the certificate - ERR_CERT_AUTHORITY_INVALID ).

Although in the browser, I can get past it to see as per:

The actual JS client doesn’t work.

I have tried my original certificate with the same result (running a client from chrome on a Mac works fine, but on windows or android, it locks the server as above).

Hi,

try to add RO CA certificate to trusted CA. it can be received via https://localhost:8099/ca.crt

untitled

after adding, autogenerated certificate will be valid:
untitled

OK, that does work on the mega demo and the JS client works with or without the SSL, but only on the Http Server, not the Super Http Server.

I have also done the same on my bespoke server, though I’m in a worse situation there really, as it now will only work if I add the CA on each computer I want someone testing. I could ask our testers to add this to their PCs for the moment, but it’s not going to work for production of course. The good news is the locking up for that slowness is resolved if I do add this CA file and run it on the PCs.

However, I’m now unclear how to load my original Let’s Encrypt file. If I turn off the four new OpenSSL Options, and load the certificate to CertFile as before, then nothing happens.

I have just tried this on my server on the PC that I noticed the original issue, and it works perfectly, without the slow speed. So, the question is, what is the solution for using another certificate (Let’s Encrypt in my case)?

Hi,

Just specify CertFile and optionally CAFile

your certificate should include private key like

-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN ENCRYPTED PRIVATE KEY-----
...
-----END ENCRYPTED PRIVATE KEY-----

Yes, I’ve done that, but it takes me back to the start of this case (it works fine but on a windows PC it kills the server).

Hi,

weird.
self signed certificate works w/o issues but Let’s Encrypt does not work at all?

It works, but when connecting with a JS (React) client from a windows PC, the server gets stuck in the loop as per the original post above!

Hi,

Can you retest your Let’s Encrypt certificate with Indy- and WinHttp-based servers, pls?
Will it work as expected with JS client?

With Indy, my certificate works fine with the both the mega demo Delphi client, and the JS client.

With WinHttp, it doesn’t even start, you can see this by just dropping one on a new form and trying to activate it at design time. Error is ‘uROHttpAPI: Access is denied’. This is Delphi XE8. I’ve never used one of those before so don’t know if it’s known, but it is repeatable on another Dephi XE8 pc. Also, not clear how to use the certificates (I see the isHttps property but that’s all).

I will now try my React JS client with the indy one.