Jump to content
uso

Reverse TIcsProxy with client authentication using SSL certs ("sslCliCertRequire")

Recommended Posts

Hello Delphians,

 

following scenario:

A server w/o support for encryption needs to be "guarded" by a encrypting reverse proxy (server <=> proxy - no encryption; proxy <=> client - encrypted)

Each valid client should authenticate against the proxy with a specific SSL certificate ("sslCliCertRequire") configured using IcsHosts.


For testing purposes I generated a root CA cert and one "child" certificate signed by this CA.

 

Now I set up proxy and client (for the sake of simplicity the client is "Firefox") to connect a demo SOAP service (client => proxy => SOAP-Service).

Firefox is asking for a certificate to authenticate against the proxy but connection is always closed with "SSL_ERROR_HANDSHAKE_FAILED".

 

openssl c_client -connect localhost:4711 gives the following:

CONNECTED(000000FC)
Can't use SSL_get_servername
depth=0 CN = localhost, OU = Child OU, ST = Some State, O = "Some Company", C = DE, L = City, emailAddress = info@contoso.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = localhost, OU = Child OU, ST = Some State, O = "Some Company", C = DE, L = City, emailAddress = info@contoso.com
verify error:num=21:unable to verify the first certificate
verify return:1
depth=0 CN = localhost, OU = Child OU, ST = Some State, O = "Some Company", C = DE, L = City, emailAddress = info@contoso.com
verify return:1
---
Certificate chain
 0 s:CN = localhost, OU = Child OU, ST = Some State, O = "Some Company", C = DE, L = City, emailAddress = info@contoso.com
   i:CN = Personal Root CA, OU = Personal Root CA, ST = Some State, O = "Some Company", C = DE, L = City, emailAddress = info@contoso.com
   a:PKEY: id-ecPublicKey, 521 (bit); sigalg: ecdsa-with-SHA512
   v:NotBefore: Apr 24 12:29:14 2023 GMT; NotAfter: Apr 25 12:29:14 2033 GMT
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
---
Server certificate
subject=CN = localhost, OU = Child OU, ST = Some State, O = "Some Company", C = DE, L = City, emailAddress = info@contoso.com
issuer=CN = Personal Root CA, OU = Personal Root CA, ST = Some State, O = "Some Company", C = DE, L = City, emailAddress = info@contoso.com
---
No client certificate CA names sent
Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224
Shared Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512
Peer signing digest: SHA512
Peer signature type: ECDSA
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 1334 bytes and written 403 bytes
Verification error: unable to verify the first certificate
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 521 bit
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 21 (unable to verify the first certificate)
---
read:errno=10054

What I'm doing wrong, what am I missing to get such a simple setup up and running?!

 

Thanks!

Edited by uso

Share this post


Link to post

From your description, I'm not sure how anything is set-up here, or why you are using an OpenSSL tool for testing.

 

The proxy server needs it's own SSL/TLS certificate matching the host name localhost which you seem to have created, but this will fail validation by clients unless those clients have the root certificate installed, Personal Root CA  in your case.

 

But this is unrelated to the client certificate which should be installed in the Firefox certificate store, and then validated by the proxy server.  Your openssl c_client command line does not have a client certificate which is the reason for the errors.

 

Angus

Share this post


Link to post

The ICS web server supports client certificates, but this scenario seems to be using an old SOAP server that does not support SSL/TLS.

 

Angus

 

Share this post


Link to post
On 4/27/2023 at 5:24 PM, Fr0sT.Brutal said:

Won't already implemented Apache/Nginx be better?

No. We are developing against customer specifications and a full-fledged web server is not on the "wishlist".

 

On 4/27/2023 at 5:45 PM, Angus Robertson said:

The ICS web server supports client certificates, but this scenario seems to be using an old SOAP server that does not support SSL/TLS.

 

Angus

 

The backend is using std. SOAP components from Delphi - yes.

But one of the requirements is a state of the art encryption so we are stuck with the SOAP components and I tried to handle the encryption by a proxy in front of the main service.

 

The proxy is working so far - encryption too.

 

Last thing, I couldn't figure out, is how to get the proxy to deny client connections, if the client does not send the right certificate.
At the moment the proxy processes every client request, even if the client sends a cert that is not signed by "my" CA.

I set TIcsProxy.RootCA to my own root certificate and I cleared TIcsProxy.SourceServer.RootCAList - but no success.

 

TIcsProxy Settings:

  MProxy := TIcsProxy.Create(nil);
  MProxy.Name := 'xxx';

  MLogger := TIcsLogger.Create(MProxy);
  if Assigned(MProxy.FIcsLog) then
  begin
    FreeAndNil(MProxy.FIcsLog);
  end;

  MLogger.LogOptions := [
    TLogOption.loDestEvent, TLogOption.loDestFile,
    TLogOption.loAddStamp,
    TLogOption.loWsockErr, TLogOption.loWsockInfo, TLogOption.loWsockDump,
    TLogOption.loSslErr, TLogOption.loSslInfo, TLogOption.loSslDevel, TLogOption.loSslDump,
    TLogOption.loProtSpecErr, TLogOption.loProtSpecInfo, TLogOption.loProtSpecDump, TLogOption.loProgress];
  MLogger.LogFileName := GetLogfilePath();
{$IFDEF DEBUG}
  MLogger.OnIcsLogEvent := OnOnIcsLogEvent;
{$ENDIF}
  MLogger.OpenLogFile;
  MLogger.DoDebugLog(MLogger, TLogOption.loProgress, Format(RSTR_LOGGER_CREATED_s, [MLogger.LogFileName]));

  MProxy.FIcsLog := MLogger;
  MProxy.onProxyProg := MLogger.DoDebugLog;
  MProxy.SourceServer.RootCAList.Clear;
  MProxy.RootCA := 'xxx';
  LIcsHost := MProxy.IcsHosts.Add() as TIcsHost;
  LIcsHost.HostNames.Add('*');
  LIcsHost.HostEnabled := True;
  LIcsHost.BindIpAddr := '0.0.0.0';
  LIcsHost.BindSslPort := 8080;
  LIcsHost.BindNonPort := 0;
  LIcsHost.HostTag := '<Your host tag>';
  LIcsHost.ForwardProxy := False;
  LIcsHost.WebLogDir := '';
  LIcsHost.WebLogIdx := 0;
  LIcsHost.SslCert := {$DEFINE SSL_CERT}{$INCLUDE 'SslSettings.inc'};
  LIcsHost.SslKey := {$DEFINE SSL_PRIV_KEY}{$INCLUDE 'SslSettings.inc'};
  LIcsHost.SslInter := {$DEFINE SSL_INTER_CERT}{$INCLUDE 'SslSettings.inc'};
  LIcsHost.SslPassword := {$DEFINE SSL_PASSWORD}{$INCLUDE 'SslSettings.inc'};
  LIcsHost.SslSrvSecurity := sslSrvSecHigh;
  LIcsHost.WebRedirectStat := 0;
  LIcsHost.CliCertMethod := sslCliCertRequire;
  LIcsHost.CertSupplierProto := SuppProtoNone;
  LIcsHost.CertChallenge := ChallNone;
  LIcsHost.CertPKeyType := PrivKeyECsecp512;
  LIcsHost.CertSignDigest := Digest_sha3_512;
  LIcsHost.AuthForceSsl := True;
  LIcsHost.AuthSslCmd:= True;

  LIcsTarget := MProxy.ProxyTargets.Add() as TProxyTarget;
  LIcsTarget.TarHost := 'localhost';
  LIcsTarget.TarPort := 8081;
  LIcsTarget.TarSsl := False;
  LIcsTarget.HostTag := '<Your host tag>';
  LIcsTarget.HostEnabled := True;

 

Edited by uso

Share this post


Link to post

Sorry, a quick scan of the TIcsProxy code suggests that client certificate checking is not yet supported. 

 

It should be happening in TIcsProxy.ServerHandshakeDone which needs a new event onServerHandshakeDone which passes PeerCert to the application where you can check it and cause the client to be disconnected for an invalid certificate (see the web server).  

 

I'll try and do it next week.

 

Angus

 

Share this post


Link to post

This is working now, the proxy log says:

 

Http > 443/443 (3) Source 17 - Client SSL Connected OK with TLSv1.3, cipher TLS_AES_128_GCM_SHA256, encryption AESGCM(128), message auth AEAD
Client certificate received, should we trust client?
CN: angus@magsys.co.uk, Issuer: Self Signed, Expires: 09/04/2030

 

and the event can be adjusted to either check a common name or an issuer name for corporate certificates. 

 

The hardest part was testing, I had to correct PemTool to properly create client certificates before Firefox would send one, I'll include a new test client certificate with the samples since this keeps coming up.

 

Will be in SVN in a day or so.

 

Angus

 

Share this post


Link to post
1 hour ago, Angus Robertson said:

This is working now, the proxy log says:

 

Http > 443/443 (3) Source 17 - Client SSL Connected OK with TLSv1.3, cipher TLS_AES_128_GCM_SHA256, encryption AESGCM(128), message auth AEAD
Client certificate received, should we trust client?
CN: angus@magsys.co.uk, Issuer: Self Signed, Expires: 09/04/2030

 

and the event can be adjusted to either check a common name or an issuer name for corporate certificates. 

 

The hardest part was testing, I had to correct PemTool to properly create client certificates before Firefox would send one, I'll include a new test client certificate with the samples since this keeps coming up.

 

Will be in SVN in a day or so.

 

Angus

 

Hi Angus,
 

thanks for your effort! We are going to test internally - too.


PemTool: Same here - had to fiddle arround with it to get it to work.
But ultimately I switched to XCA for creating my certs.

Share this post


Link to post

PemTool used to work for client certificates, but I broke it when adding international domain support, where spaces and @ are illegal.

 

Angus

 

Share this post


Link to post

There was a large SVN update yesterday, including SSL client certificate support in the proxy server, and improved logging in the REST client, so you know if a client certificates was requested by the server. 

 

Available from SVN and the overnight zip.

 

Angus

 

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
×