Have recently moved to CloudFlare as I wanted a DNS service that provided DNS credentials for certbot to generate a wildcard SSL certificate.
However, I am struggling to get a basic SSL Nginx setup running.
Background:
DNS resolution works fine. (When I just have an Nginx HTTP server block, the website loads insecurely over HTTP)
Can connect to website via direct IP with HTTPS address (not via CloudFlare IP). It gives an invalid cert warning but still connects.
openssl s_client -connect property-connect.co.uk:443 -servername property-connect.co.uk seems to indicate the SSL certificate is fine
Steps:
Ran certbot --nginx specified include both domains (www.property-connect.co.uk property-connect.co.uk)
sudo nginx -t was successful
sudo nginx -s reload
nginx.conf
events {
}
http {
server {
server_name www.property-connect.co.uk property-connect.co.uk;
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
location / {
proxy_pass http://localhost:700;
}
ssl_certificate /etc/letsencrypt/live/property-connect.co.uk-0001/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/property-connect.co.uk-0001/privkey.pem; # managed by Certbot
}
}
Any thoughts as to what I am missing with this basic config?
Your current certificate for this domain issued and managed by Cloudflare itself, not by your CertBot/Nginx:
$ openssl s_client -connect property-connect.co.uk:443 -servername property-connect.co.uk </dev/null 2>&1 | grep ^issuer
issuer=C = US, ST = CA, L = San Francisco, O = "CloudFlare, Inc.", CN = CloudFlare Inc ECC CA-2
I guess this is because you have proxied traffic via Cloudflare to your host
You should switch your domain to DNS only and then you will able to connect directly to your Nginx without Cloudflare reverse-proxying.
Turns out I just needed to change the Cloudflare SSL setting from 'Flexible' (Browser -> HTTPS -> Cloudflare -> HTTP -> Web server) to 'Full' (Browser -> HTTPS -> Cloudflare -> HTTPS -> Web server).
Related
I'm trying to reverse-proxy an http server via nginx. The service is listening on port 8123 and I want to proxy it on 443.
I created a self-signed certificate like this:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
Here is the complete nginx configuration:
events {
worker_connections 768;
}
http {
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /home/mcmsadm/cert.pem;
ssl_certificate_key /home/mcmsadm/key.pem;
location / {
proxy_pass http://localhost:8123;
}
}
}
When I try to connect to the server using Firefox, it says PR_END_OF_FILE_ERROR.
What am I doing wrong?
Thanks!
EDIT:
I found the nginx error message in the logs (Didn't think about it):
SSL_CTX_use_PrivateKey_file("/home/mcmsadm/key.pem") failed
(SSL: error:2807106B:UI routines:UI_process:processing error:while reading strings
error:0906406D:PEM routines:PEM_def_callback:problems getting password
error:0907B068:PEM routines:PEM_read_bio_PrivateKey:bad password read
error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib)
I did create the certificate with a password, but nginx is asking for it when I restart it via nginx -s reload. To temporarily solve this I wrote the password in a file and added this line to my nginx.conf:
ssl_password_file /etc/nginx/pass;
Is there any way that I can avoid writing the password in a file?
For anyone else with this issue.. it can also happen if you have forgotten to add ssl to the listen directives. Chrome shows ERR_SSL_PROTOCOL_ERROR whilst Firefox shows PR_END_OF_FILE_ERROR.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
...
}
The error is often not related to the browser. In our case it was also not a configuration thing of nginx, but a wrong setting of the firewall. So logically, when I say that often has nothing to do with the browser, server-side and not client-side. Accordingly, it was not a proxy or VPN.
Note for myself :-d
The default_server configuration (with ssl or/and without ssl) is missing from one of the virtual host definitions, like this:
server {
listen 80 default_server;
listen 443 default_server;
...
I have a .crt, .key and CA.pem files that were generated like this.
These certs are kind of project-wide, and they work when firing up a webpack-dev-server server on HTTPS like:
devServer: {
https: {
key: fs.readFileSync('/path/to/example.com.key'),
cert: fs.readFileSync('/path/to/examle.com.crt'),
ca: fs.readFileSync('/path/to/CA.pem'),
}
}
Now I need to setup an Nginx server using these 3 files, but I've been trying with no luck. Here's my config:
server {
listen 3000;
ssl_certificate certs/example.com.crt;
ssl_certificate_key certs/example.com.key;
# where does the CA.pem file go??
}
The result of this is Chrome giving me a
This site can’t provide a secure connection
example.com sent an invalid response.
ERR_SSL_PROTOCOL_ERROR
Nginx logs show random hex characters:
172.18.0.1 - - [14/Dec/2018:18:01:55 +0000] "\x16\x03\x01\x00\xDD\x01\x00\x00\xD9\x03\x03\xAB\xE1\xB3\x1F\xCE\x02\x02\xC5}q\xDFgd\xF1`\xC1m\x8E\x99\xCE' \x98\xDF\xDEEg\x8Fm\xED\x9F\xB1\x00\x00\x1C" 400 166 "-" "-" "-" 0.001 -
Any ideas what could I be doing wrong?
You need to concatenate your certificate with CA for nginx:
cp example.com.crt example.com.fullchain.pem
cat CA.pem >> example.com.fullchain.pem
and use this file in nginx config:
ssl_certificate certs/example.com.fullchain.pem;
Heroku gives simple instructions for updating your certificates for SSL:
$ heroku certs:update server.crt server.key
However, there is no indication that any verification is done before deploying. As this is production, I want to be sure that the two files I'm giving them will not cause any security snafus.
I have my foo_com.crt (which was signed by DigiCert), server.key, and DigitCertCA.crt.
I've found that I can use security verify-cert -c certificate.pem to verify my certificate (on OS X). My certificate doesn't verify though:
$ security verify-cert -c foo_com.crt
Cert Verify Result: CSSMERR_TP_NOT_TRUSTED
Which leads me to believe that my intermediary may not be trusted but:
$ security verify-cert -c DigiCertCA.crt
...certificate verification successful.
Specifying a purpose of SSL succeeds too
$ security verify-cert -p ssl -c foo_com.crt
...certificate verification successful.
I tried on a Linux box as well with similar mixed results.
$ openssl verify foo_com.crt
C = __, ST = ___, L = ___, O = "Foo Inc", CN = foo.com
error 20 at 0 depth lookup: unable to get local issuer certificate
error foo_com.crt: verification failed
$ openssl verify -CAfile DigiCertCA.crt foo_com.crt
foo_com.crt: OK
$ openssl verify -purpose sslserver -CApath /etc/ssl/certs foo_com.crt
C = __, ST = ___, L = ___, O = "Foo Inc", CN = foo.com
error 20 at 0 depth lookup: unable to get local issuer certificate
error foo_com.crt: verification failed
How can I be sure that when I update my certificates in Heroku, that everything will work smoothly?
Related: Renewing SSL certificate on Heroku
A suggestion from a colleague to run nginx led me to a confident way to know that everything would deploy smoothly.
I configured nginx with
server {
listen 443 http2 ssl;
listen [::]:443 http2 ssl;
server_name server_IP_address;
ssl_certificate /Users/traff/cert/gd.crt;
ssl_certificate_key /Users/traff/cert/server.key;
server_name localhost;
...
}
Once I had my nginx server set up I ran openssl s_client -connect localhost:443 -CApath /etc/ssl/certs. Then, after setting up foo.com in my hosts to point to my nginx server. I used curl https://foo.com.
Using the concatenation of foo_com.crt and DigiCertCA.crt (in that order) and server.key, upload was successful.
Furthermore, though Heroku's documentation does not state it, the update step does verify that SSL will serve properly
$ heroku certs:update foo_com_DigiCertCA_cat.crt server.key -a my-app
Resolving trust chain... done
_ Potentially Destructive Action
_ This command will change the certificate of endpoint ____
_ (_______.herokussl.com) from _ my-app.
_ To proceed, type my-app or re-run this command with
_ --confirm my-app
> my-app
Updating SSL certificate _____ (____.herokussl.com) for _ my-app... done
Updated certificate details:
Common Name(s): foo.com
Expires At: DateTime
Issuer: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
Starts At: DigiCert
Subject: blah blah blah
SSL certificate is verified by a root authority.
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 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