Universal SSL & Client Certificate (PFX) Authentication Config (NGINX)

Domain: Nimbusphere.com
Problem Summary: Config problem(s) with Cloudflare Client Certs / nginx
Primary Error Condition Seen: “Verification error: unable to get local issuer certificate”

I am very new to the nuts and bolts of setting up SSL on a web server (but have decades of experience in Linux, software development, etc…) - Sorry if I confuse you experts here! :slight_smile:


I am currently successfully using Cloudflare’s Universal SSL to provide EDGE SSL to this website, having installed the origin server crt/keys and testing by going to https://nimbusphere.com successfully. [ NOTE: Nothing “production” is yet located on this server ] My problem with is understanding how to configure Cloudflare’s Client Certificates to work on the site.

The intent here is to authenticate only users using a browser configured with a properly issued User Certificate (e.g. as a PFX in Firefox that I send to the user). I have read several articles (noted below) which discuss the details of getting the individual certs and settings right, but I think perhaps the issue I am having is related to not fully understanding what to put into a “FULL” chain PEM to get this to work. The articles seem to pass over this topic.

In searching, I have found partial answers but am still not getting this to work.

I think I need to start with understanding what a FULL CHAIN PEM file is in this context - Which /etc/ssl file(s) need to be concatenated, and what is the source of each cert (in this context, using Cloudflare for the Client signing CA), etc.

nginx version: nginx/1.14.2
OpenSSL 1.1.1n  15 Mar 2022

Oddly (to me, anyway), opening the website in Firefox with a PFX installed and this config returns the “404” error from my nginx config for the proxied url.

Running this command to test returns “Verification error: unable to get local issuer certificate” as you can see below.

openssl s_client -cert user.crt -key user.key \
        -CAfile cloudflare_ca.crt -connect `nimbusphere.com:443` \
        -state -debug
write to 0x557989ec20 [0x55798b40e0] (307 bytes => 307 (0x133))
0000 - 16 03 01 01 2e 01 00 01-2a 03 03 b7 ef a0 90 3d   ........*......=
0010 - 47 cf 3c 6a 97 0e 0c f5-b4 01 5a 7b 18 12 fd f7   G.<j......Z{....


10d0 - d9 87 46 74 2e 27 d1 3c-b8 23 53 93 00 c1 67 23   ..Ft.'.<.#S...g#
10e0 - 05 fe b7                                          ...
write to 0x557989ec20 [0x55798b40e0] (80 bytes => 80 (0x50))
0000 - 14 03 03 00 01 01 17 03-03 00 45 c0 3b ee ef ca   ..........E.;...
0010 - 1c 20 3c 05 5f ce 4b 7a-90 1a bd 79 ea d8 42 d0   . <._.Kz...y..B.
0020 - 45 c6 3e 78 69 ec c5 70-a5 7f 95 18 33 dd f9 c9   E.>xi..p....3...
0030 - 11 c2 68 ee 6d 8b c2 5e-02 26 b3 c1 61 82 c6 42   ..h.m..^.&..a..B
0040 - b0 f0 11 63 8b 51 c5 92-30 81 2d 91 3a 61 bf da   ...c.Q..0.-.:a..
Certificate chain
 0 s:CN = `nimbusphere.com`
   i:C = US, O = Let's Encrypt, CN = E1
 1 s:C = US, O = Let's Encrypt, CN = E1
   i:C = US, O = Internet Security Research Group, CN = ISRG Root X2
 2 s:C = US, O = Internet Security Research Group, CN = ISRG Root X2
   i:C = US, O = Internet Security Research Group, CN = ISRG Root X1
 3 s:C = US, O = Internet Security Research Group, CN = ISRG Root X1
   i:O = Digital Signature Trust Co., CN = DST Root CA X3
Server certificate
subject=CN = `nimbusphere.com`

issuer=C = US, O = Let's Encrypt, CN = E1

No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: ECDSA
Server Temp Key: X25519, 253 bits
SSL handshake has read 4461 bytes and written 387 bytes
Verification error: unable to get local issuer certificate
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 256 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 20 (unable to get local issuer certificate)

NGINX Configuration:

server {

    listen 83 ;
    listen [::]:83 ;

    # This causes a REDIRECT (301 - Permanent redirect)
    return 301                  `https://$host$request_uri` ;

server {
    listen                      443 ssl default_server ;
    listen                      [::]:443 ssl default_server ;

    server_name                 `nimbusphere.com` `www.nimbusphere.com` ;

    ssl_protocols               TLSv1.1 TLSv1.2 TLSv1.3 ;
    ssl_certificate             /etc/ssl/certs/nimbusphere.com.crt ;
    ssl_certificate_key         `/etc/ssl/private/nimbusphere.com.key` ;

    ssl                         on ;

    # Cloudflare TLS Certificate
    ssl_client_certificate      /etc/ssl/certs/cloudflare.crt ;

    # This is optional so we can get to the ssl_client_verify and return
    # a proper 4XX to the user
    ssl_verify_client           optional ;

    location / {

        if ($ssl_client_verify != SUCCESS) {
            return 403;

        proxy_set_header        Host $host ;
        proxy_set_header        X-Real-IP $remote_addr ;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for ;
        proxy_set_header        X-Forwarded-Proto $scheme ;
        proxy_set_header        Upgrade $http_upgrade ;

        proxy_http_version      1.1 ;
        proxy_read_timeout      90 ;
        proxy_ssl_verify_depth  2 ;

        proxy_pass              `https://localhost/auth` ;
        proxy_redirect          `https://localhost/auth https://localhost/auth` ;


    location /auth {

        if ($ssl_client_verify != SUCCESS) {
            return 404 ;
        root /data/www/templatemo_491_flat ;

Can anyone send me in the right direction here? TIA to all, much appreciated. I have been banging my head on the desk over this!

[Please ignore the random “back ticks” in the above - The site kept telling me I had embedded URLs and needed to put “back ticks” around them. I thought I did, but… So sorry for the resulting formatting of the original post ]

NOTE: All browsers, regardless of PFX files installed, return 404 (from my proxied configuration).

Edited for readability.

1 Like

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.