force nginx to use SSL/TLS alert on invalid client certificate

charlemagnelasse nginx-forum at forum.nginx.org
Tue Mar 2 08:30:02 UTC 2021


If I am using a Apache to verify the client certificate and the client
certificate is invalid (e.g. revoked) than I can get the appropriate SSL/TLS
alert which can be evaluated by the client:


    curl -v --insecure --cert cert.pem --key key.pem --cacert ca.pem
https://127.0.0.1:443/1/config
    * Expire in 0 ms for 6 (transfer 0x5611097bcfb0)
    *   Trying 127.0.0.1...
    * TCP_NODELAY set
    * Expire in 200 ms for 4 (transfer 0x5611097bcfb0)
    * Connected to 127.0.0.1 (127.0.0.1) port 443 (#0)
    * ALPN, offering h2
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    *   CAfile: ca.pem
      CApath: /etc/ssl/certs
    * TLSv1.3 (OUT), TLS handshake, Client hello (1):
    * TLSv1.3 (IN), TLS handshake, Server hello (2):
    * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
    * TLSv1.3 (IN), TLS handshake, Request CERT (13):
    * TLSv1.3 (IN), TLS handshake, Certificate (11):
    * TLSv1.3 (IN), TLS handshake, CERT verify (15):
    * TLSv1.3 (IN), TLS handshake, Finished (20):
    * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
    * TLSv1.3 (OUT), TLS handshake, Certificate (11):
    * TLSv1.3 (OUT), TLS handshake, CERT verify (15):
    * TLSv1.3 (OUT), TLS handshake, Finished (20):
    * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
    * ALPN, server accepted to use http/1.1
    * Server certificate:
    *  subject: C=ZZ; ST=YY; L=Duckburg; O=McDuck LLC.; OU=moneybin;
CN=moneybin.example.com
    *  start date: Jan  1 01:02:03 2021 UTC
    *  expire date: Jan  1 01:02:03 2022 UTC
    *  issuer: C=ZZ; ST=YY; L=Duckburg; O=McDuck LLC.; CN=Scrooge CA
    *  SSL certificate verify result: unable to get local issuer certificate
(20), continuing anyway.
    > GET /1/config HTTP/1.1
    > Host: 127.0.0.1
    > User-Agent: curl/7.64.0
    > Accept: */*
    > 
    * TLSv1.3 (IN), TLS alert, certificate revoked (556):
    * OpenSSL SSL_read: error:14094414:SSL routines:ssl3_read_bytes:sslv3
alert certificate revoked, errno 0
    * Closing connection 0
    curl: (56) OpenSSL SSL_read: error:14094414:SSL
routines:ssl3_read_bytes:sslv3 alert certificate revoked, errno 0



This is awesome because the (API) client can evaluate this information and
start the correct actions based on that information. But for ningx (with the
default configuration), I only get a generic error when the SSL certificate
is revoked:


    curl -v --insecure --cert cert.pem --key key.pem --cacert ca.pem
https://127.0.0.1:443/1/config
    * Expire in 0 ms for 6 (transfer 0x5611097bcfb0)
    *   Trying 127.0.0.1...
    * TCP_NODELAY set
    * Expire in 200 ms for 4 (transfer 0x5611097bcfb0)
    * Connected to 127.0.0.1 (127.0.0.1) port 443 (#0)
    * ALPN, offering h2
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    *   CAfile: ca.pem
      CApath: /etc/ssl/certs
    * TLSv1.3 (OUT), TLS handshake, Client hello (1):
    * TLSv1.3 (IN), TLS handshake, Server hello (2):
    * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
    * TLSv1.3 (IN), TLS handshake, Request CERT (13):
    * TLSv1.3 (IN), TLS handshake, Certificate (11):
    * TLSv1.3 (IN), TLS handshake, CERT verify (15):
    * TLSv1.3 (IN), TLS handshake, Finished (20):
    * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
    * TLSv1.3 (OUT), TLS handshake, Certificate (11):
    * TLSv1.3 (OUT), TLS handshake, CERT verify (15):
    * TLSv1.3 (OUT), TLS handshake, Finished (20):
    * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: C=ZZ; ST=YY; L=Duckburg; O=McDuck LLC.; OU=moneybin;
CN=moneybin.example.com
    *  start date: Jan  1 01:02:03 2021 UTC
    *  expire date: Jan  1 01:02:03 2022 UTC
    *  issuer: C=ZZ; ST=YY; L=Duckburg; O=McDuck LLC.; CN=Scrooge CA
    *  SSL certificate verify result: unable to get local issuer certificate
(20), continuing anyway.
    * Using HTTP2, server supports multi-use
    * Connection state changed (HTTP/2 confirmed)
    * Copying HTTP/2 data in stream buffer to connection buffer after
upgrade: len=0
    * Using Stream ID: 1 (easy handle 0x5611097bcfb0)
    > GET /1/config HTTP/2
    > Host: 127.0.0.1:443
    > User-Agent: curl/7.64.0
    > Accept: */*
    > 
    * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
    * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
    * old SSL session ID is stale, removing
    * Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
    < HTTP/2 400 
    < server: nginx
    < date: Tue, 02 Mar 2021 07:54:36 GMT
    < content-type: text/html
    < content-length: 224
    < strict-transport-security: max-age=63072000; includeSubDomains;
preload
    < 
    <html>
    <head><title>400 The SSL certificate error</title></head>
    <body bgcolor="white">
    <center><h1>400 Bad Request</h1></center>
    <center>The SSL certificate error</center>
    <hr><center>nginx</center>
    </body>
    </html>
    * Connection #0 to host 127.0.0.1 left intact



How can I force nginx also to report the client certificate error via the
TLS alert mechanisms instead of this useless HTML page?

---

Here is the nginx site configuration as reference:

    server {
            listen 443 ssl http2 default_server;
    
            error_log /var/log/nginx/moneybin_error.log;
            access_log /var/log/nginx/moneybin_access.log;
    
            ssl_certificate /some/path/to/certs/fullchain.pem;
            ssl_certificate_key /some/path/to/certs/privkey.pem;
            ssl_client_certificate  /some/path/to/certs/ca.pem;
            ssl_trusted_certificate  /some/path/to/certs/ca.pem;
            ssl_crl     /some/path/to/certs/crl.pem;
            ssl_session_timeout 1d;
            ssl_session_cache off;
            ssl_session_tickets off;
    
            # intermediate configuration
            ssl_protocols TLSv1.2 TLSv1.3;
            ssl_ciphers
ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
            ssl_prefer_server_ciphers off;
            ssl_verify_client optional;
            ssl_verify_depth 2;
    
            root /var/www/moneybin;
    
            server_name _;
    
            location / {
                    fastcgi_param HTTP_PROXY "";
                    fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
                    fastcgi_index index.php;
                    include fastcgi_params;
                    fastcgi_param  SCRIPT_FILENAME  
/var/www/moneybin/index.php;
            }
    }

Posted at Nginx Forum: https://forum.nginx.org/read.php?2,290872,290872#msg-290872



More information about the nginx mailing list