I am using Nginx to create a secure connection; when I revoked the client certificate, I also can connect to Nginx by https, I know I should config the ssl_crl directives, but I want to use OCSP to verify the client certificate, How should I do? I found Nginx use OpenSSL library to establish ssl connection, Is there something I should do with openssl.cnf file?
Client certificate validation with OCSP feature has been added to nginx 1.19.0+.
For example:
ssl_verify_client on;
ssl_ocsp on;
resolver 192.0.2.1;
ssl_ocsp enables OCSP validation of the client certificate chain.
ssl_ocsp leaf; enables validation of the client certificate only. By default ssl_ocsp is set to off.
ssl_verify_client directive should be set to on or optional for the OCSP validation to work
resolver should be specified to resolve the OCSP responder hostname.
Update
Nginx added support for client certificate validation with OCSP in version 1.19.0, released 26 May 2020. See ssl_ocsp and related directives.
Original answer
Nginx does not support OCSP validation of client certificates. The only option of validating client certificates is to use CRLs, update them and reload Nginx to apply the changes.
In this thread one of the leading Nginx developers confirms that and says that nobody is working on it as of 2014:
https://forum.nginx.org/read.php?2,238506,245962
Prerequirements:
running pki with OCSP configured
NginX Server config
# Specifies a file with trusted CA certificates in the PEM format used to verify client certificates and OCSP responses if ssl_stapling is enabled.
# The list of certificates will be sent to clients. If this is not desired, the ssl_trusted_certificate directive can be used.
ssl_client_certificate /etc/nginx/client_certs/ca.crt;
ssl_verify_client on;
ssl_stapling on; #Yes this has to be configured to use OCSP
resolver 192.0.2.1;
information on ssl_verify_client
informations on ssl_client_certificate
This is just a sample of how the code should look like in your server block:
server {
# Listen on port 443
listen 443 default_server;
server_name example.com;
root /path/to/site-content/;
index index.html index.htm;
# Turn on SSL; Specify certificate & keys
ssl on;
ssl_certificate /etc/nginx/ssl/example.com/my_certificate.crt;
ssl_certificate_key /etc/nginx/ssl/example.com/example.key;
# Enable OCSP Stapling, point to certificate chain
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/full_chain.pem;
}
make sure the certificates match your paths, and then Save your work.
Test your configuration before reloading...
and last, restart or reload Nginx by either of the following commands:
sudo service nginx reload
or
sudo service nginx restart
Final step, test your OCSP Stapling through this link to make sure your SSL is working or not:
OCSP Stapling SSL Checker
Related
I have created my own ca certificates with openssl. I have four files :
ca.key (private ca key)
ca.crt (public ca certificate)
server.key (private key)
server.crt (public certificate signed by the ca files)
I use nginx with ssl configuration.
ssl_certificate server.crt;
ssl_certificate_key server.key;
If I install the ca public certificate on my computer, my browser let me go on the website without adding exception which is good. But if I have not the ca certificate installed on my computer, I have to add exception to pass. I want to avoid adding exception and force user to have the ca certificate installed on their computer.
I configure nginx with hsts (http strict transport security) :
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate ca.crt;
Unfortunately I have again the possibility to add an exception to pass.
I'm wondering if it is possible to do this ?
I realize that my certificates doesn't work with chrome missing_subjectAltName. So I fixed it with this link. And now I have this message with chrome if my ca certificate is not installed on my computer :
You cannot visit localhost right now because the website uses HSTS. Network errors and attacks are usually temporary, so this page will probably work later.
This is exactly what I want. However it doesn't work on firefox et let me the possibility to add an exception.
Why chrome block it and not firefox ? How can I do that on firefox too ?
I want to secure a collection of web APIs I'm writing. The access to those APIs must be granted to subscribers until the subscription expires; the APIs are consumed by remote web services. So I thought that Mutual SSL is the best
way to do that.
I'm trying to set up my own CA to issue x509 certificates to clients.
This is the first time I'm doing this; so, naturally, nothing works.
This is what I want to get as end-result: I deploy my APIs using Nginx as a reverse-proxy; if the client sends a valid certificate to Nginx, the reverse proxy accepts the connection and it forwards the requests; the connection is closed otherwise. Whenever a new client signs a subscription, I generate a new certificate and send it to him/her.
So I followed this guide, that seemed to me to be more complete than others I read, and I put a self-signed ca.crt in /etc/ssl/ca/cert for signing the CSRs received from clients and I set up nginx as
server {
listen *:443 ssl;
server_name api.example.com;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_certificate /etc/ssl/certs/server.pem; #certificate from an actual CA
ssl_certificate_key /etc/ssl/private/server.key; #PK of server.pem
ssl_client_certificate /etc/ssl/ca/certs/ca.crt;
ssl_crl /etc/ssl/ca/crl/ca.crl;
ssl_verify_client on;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on; #ensure your cert is capable
ssl_stapling_verify on; #ensure your cert is capable
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
#Redirects all traffic
location / {
proxy_pass http://mysecuredserver/api$request_uri;
limit_req zone=one burst=10;
}
}
But when I consume a Test api (it always responds with a 200 OK) using
curl -k -v --key key.pem --cert cert.pem https://api.example.com/Test
I always get the following error:
< HTTP/1.1 400 Bad Request
* Server nginx is not blacklisted
< Server: nginx
< Date: Fri, 29 Sep 2017 18:00:16 GMT
< Content-Type: text/html
< Content-Length: 224
< Connection: close
<
<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>
* Closing connection 0
* SSLv3, TLS alert, Client hello (1):
Could anybody explain to me what's wrong?
Second question: in ssl_certificate I put the cert I bought from a valid CA: is that right or should I put a cert generated using the ca.crt instead?
As discussed when you don't get much logs in Nginx you should add
debug_connection <IP>;
It will generate more logs. Which showed
2017/09/29 20:27:55 [info] 28783#0: *72 client SSL certificate verify error: (3:unable to get certificate CRL) while reading client request headers
This error occurs when you don't provide CRL for every certificate in the ssl_client_certificate chain.
Below are similar thread showing the same issue
https://serverfault.com/questions/501912/nginx-proxy-ssl-clr-400-bad-request-error
Nginx unable to get certificate CRL
You need to specify the directive ssl_crl and give it the CRL file
ssl_crl /etc/ssl/certs/crl/ca.crl;
Additionally, you should verify that ssl_certificate refers to the certificate created by your CA for your server:
ssl_certificate /etc/ssl/ca/certs/server.pem; #signed by your CA
ssl_certificate_key /etc/ssl/ca/private/server.key; #PK used to generate
#server.pem
ssl_client_certificate /etc/ssl/ca/certs/ca.crt;
ssl_crl /etc/ssl/ca/crl/ca.crl; #CRL of the
#ssl_client_certificate and
#its chain
OCSP Stapling does not work for Thawte certificates on Nginx, what could be the problem?
Configured Nginx to work with OCSP Stapling.
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /ssl/ssl_trusted_certificate.crt;
The ssl_trusted_certificate.crt certificate includes the stitched root.crt and intermediate.crt.
The verification request indicates that OCSP Stapling is still off:
Openssl s_client -connect xxx.xxx:443 -tls1 -tlsextdebug -status
Result:
OCSP Response: No response sent
Who knows this problem?
As it turned out, the problem was not in the certificate and server settings. In order for OCSP Stapling to work, you need to go through a couple of pages of the site. On the first request, the server will request data from the certification center servers, and then go to OCSP.
I´m trying to use nginx as a reverse proxy to an internal webserver running Tomcat, which hosts a front-end to our ERP system.
It is already working fine: I can perfectly connect to the nginx server (which is locked up on our network, different VLAN, firewall, etc etc etc) and then reverse proxy to my ERP server.
However, I want do add an extra layer of protection, by requiring users to have a digital certificate on their computer, so they can access the first (nginx) server. The certificate is not used/necessary to the back-end server.
I´ve been through this tutorial
http://nategood.com/client-side-certificate-authentication-in-ngi
which allowed me to generate my self-signed certificates and everything else.
When using ssl_verify_client optional on nginx configuration, I can connect normally to my back-end server, but no certificate is asked/required.
When I switch it to ssl_verify_client on , all access are then blocked by a
400 Bad Request
No required SSL certificate was sent
No matter which browser I am using (Chrome, IE, Edge, Firefox). Of course I´ve put all certificates/chain on my client computer, but no certificate is asked on any browsers. What I am missing?
Here is my full nginx config:
server {
listen 443;
ssl on;
server_name 103vportal;
ssl_password_file /etc/nginx/certs/senha.txt;
ssl_certificate /etc/nginx/certs/server.crt;
ssl_certificate_key /etc/nginx/certs/server.key;
ssl_client_certificate /etc/nginx/certs/ca.crt;
ssl_verify_client on;
location / {
proxy_pass http://10.3.0.244:16030;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300;
proxy_send_timeout 300;
}
}
Assuming you have generated a private key and a certificate request for your user and signed it with your client CA. You need to get the private key and the signed certificate into the list of personal certificates in the browser.
I have found that the best way is to create a password protected PKCS#12 (as some browsers insist on password protection). I use the following OpenSSL command:
cat user.key user.crt | openssl pkcs12 -export -out user.p12
I have the following in my configuration file:
## verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /path/to/intermediate_ca;
My certificate is issuing unsecure warnings to the browser and I think it might just be because I am missing the file that presents the intermediate chain to the server. Even so, I'm using comodo positivessl and can't find this file after searching for it endlessly on ssls.com and google. Does anyone have any idea on how I should go with this? A cipherscan in my server issues "Certificate: untrusted" and "OCSP stapling: not supported" although I have ssl_stapling on; ssl_stapling_verify on; on the file.
You can download the Comodo intermediate certificates from this page. Depending on when your certificate was issued, you should download either the SHA2 or SHA1.
Be sure to scroll the list and download the files associated with the PositiveSSL row in the table.
Once downloaded, combine all the files in a single .pem file:
- the server certificate (then one you received)
- the intermediates, from the most specific to the most generic
Store the file on the server and configure Nginx properly using the following settings:
ssl on;
ssl_certificate /path/to/bundle.pem;
ssl_certificate_key /path/to/private-key.key;