NGINX HTTPS - SSL Certificates - nginx

I have three files regarding certificates:
- example.com.ca-bundle # contains root and intermediate certificates
- example.com.crt # Certificate
- example.com.p7b # only contains certificates and chain certificates
I need to configure NGINX to accept HTTPS, but I feel a bit confused as I do not have the most experience with SSL, and most examples seem to use a certificate/key pair. Would this NGINX configuration be the correct approach?
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /path/to/example.com.crt;
ssl_certificate_key /path/to/example.com.crt;
...
}

Like others pointed out in the comments you need to use the private key for ssl_certificate_key. If it helps further, below is an excerpt from an Nginx configuration using Let's Encrypt SSL certificates. In some cases cert.pem is not enough and chain.pem is also needed for compatibility across more browsers and server types.
# Full chain fullchain.pem is just a concatenation of public key cert.pem and chain.pem. If you are using certbot this will be automatically created.
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
# Like others pointed out in the comments there should be a private key and not the cert file
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
You can use certbot (a tool by Let's Encrypt) to automate the generation of your certificates. Here is a link with Step by Step instructions for automating HTTPS / SSL Certificate setup for your Nginx Hosted Website

Related

Is it possible to allow nginx to start if the specified certificate/keys files are absent?

I have following situation: I have an nginx instance serving a few websites like this:
server {
listen 443 ssl;
server_name website1.com;
root /var/www/website1;
ssl_certificate /etc/ssl/certs/website1.crt;
ssl_certificate_key /etc/ssl/private/website1.key;
...
}
server {
listen 443 ssl;
server_name website2.com;
root /var/www/website2;
ssl_certificate /etc/ssl/certs/website2.crt;
ssl_certificate_key /etc/ssl/private/website2.key;
...
}
server {
listen 80 default_server;
root /var/www/acme;
# Allow files to be served for the use of acme certification only
try_files $uri #redirect;
location #redirect {
return 301 https://$host$request_uri;
}
}
Now I ended with the chicken and the egg problem where:
Without certificates nginx will crash
To generate certificates I need to serve /var/www/acme files
To serve those file I need nginx running
I know I can manually remove uncertified vhosts from configuration, generate the certificates and then reenable it, but this will be a pain to automate in ansible.
Also I cannot disable nginx and use standalone certbot instance, since I need to be able to add websites without interfering with already existing websites.
In apache I was able to do this:
<IfFile /etc/ssl/certs/$name.crt>
<VirtualHost *:443>
...
</VirtualHost>
</IfFile>
Is there a similar feature in nginx, or at least a way to prevent errors in one of the vhosts from killing the entire server?
No, there is no way to start nginx with the erroneous configuration. You have the following options instead:
1. Using a dummy self-signed certificate to allow nginx to start
This one probably will be the most simple. The trick is that nginx does not require valid certificates/keys to start - it can be any self-signed certificate, it won't prevent LetsEncrypt from verifying the ACME challenge. You can generate a pair of the self-signed certificate/key using the following one-liner:
openssl req -nodes -new -x509 -subj "/CN=localhost" -keyout /etc/ssl/private/website.key -out /etc/ssl/certs/website.crt
Use those certificate/key in your nginx config and replace them with the valid ones after nginx will be started; then reload nginx to reload new certificate/key.
2. Using variables in the ssl_certificate and ssl_certificate_key directives
Since nginx version 1.15.9 you can use variables in the ssl_certificate/ssl_certificate_key directives parameters:
Changes with nginx 1.15.9 26 Feb 2019
*) Feature: variables support in the ssl_certificate and
ssl_certificate_key directives.
There are some caveats when you are using variables with those directives. You can't do something like
server {
listen 443 ssl;
server_name website1.com;
root /var/www/website1;
set $site website1;
ssl_certificate /etc/ssl/certs/$site.crt;
ssl_certificate_key /etc/ssl/private/$site.key;
...
}
As being pointed by Maxim Dounin, variables set with the set directive of the rewrite module are only available after rewrite instructions were evaluated when processing a request as it described in the rewrite module documentation. As such, these variables won't have any meaningful value during an SSL handshake. When loading certificates you have to use builtin connection-related variables, or custom variables which are always available - such as provided with map, geo, perl_set, or js_set directives.
That is, instead you can define a map block at the http configuration level:
map $server_name $site {
website1.com website1;
website2.com website2;
...
default dummy;
}
server {
listen 443 ssl;
server_name website1.com;
root /var/www/website1;
ssl_certificate /etc/ssl/certs/$site.crt;
ssl_certificate_key /etc/ssl/private/$site.key;
...
}
...
Note that the $server_name variable will be equal to the first argument of the server directive value. That is, it will be equal to website1.com if your server_name directive will look like
server_name website1.com www.website1.com;
and it will be equal to www.website1.com if your server_name directive will look like
server_name www.website1.com website1.com;
no matter if the actual request will be https://website1.com/ or https://www.website1.com. You can find out more details here. Another variable to be mapped can be the $ssl_server_name.
Caution! According to documentation, using variables implies that a certificate will be loaded for each SSL handshake, and this may have a negative impact on performance. I don't know what the amount of performance impact really is; most probably it is related to your current open_file_cache (and related) settings. However if you still want to choose certificates/keys dynamically and want to avoid that performance impact, you have the third option.
3. Using variables for ssl_certificate and ssl_certificate_key directives data
Since nginx version 1.15.10 you can use variables for specifying ssl_certificate/ssl_certificate_key directives data directly:
Changes with nginx 1.15.10 26 Mar 2019
*) Feature: loading of SSL certificates and secret keys from variables.
To use this you should declare your certificate/key the following way:
server {
listen 443 ssl;
server_name website.com;
ssl_certificate data:$site_cert;
ssl_certificate_key data:$site_key;
...
}
I did this trick in the past, and since there are some really non-obvious configuration steps involved, and I didn't find any working example of how to do it right at the time I was solving this task, I'm going to show how it can be done to made a question somewhat more complete.
The cert/key data should be specified in a single line, with a newlines being replaced with the escaped \n special character. Here is an example defaulting to self-signed certificate/key:
map $server_name $site_cert {
include /etc/ssl/certs/*.conf;
default "-----BEGIN CERTIFICATE-----\nMIIC+zCCAeOgAwIBAgIJAOG37sqlniFgMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV\nBAMMCWxvY2FsaG9zdDAeFw0yMTA3MjExMDE4MzJaFw0yMTA4MjAxMDE4MzJaMBQx\nEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\nggEBAKFbMLQ4n/BkgcrqE/0UKpSDO8Z2VkSWj2SDAPIhGoGGyk3omSv924woe+k/\nD6HidHEESmYC3WIliY3sIAABg+eUnfrmkafyE4BK/pnodkDSIjFM+0Klb3MQnG1r\njMrJ+F4vgMVNsHXgFCzWykzCwPLPJPdPEr1hqfNlkfJZNLHATC/MW+PeRJXb0D+a\nGn7TA7L60UP2baYjHldGO4fnSYkA8ta/PT+hfBRPr66K2ygaaGeC7jPNaIaMXJQo\nWPBOqGC0BoT5QM1X+8MjKc/ON/twwxR5ugKVADjS9fotXGcgPab+RchS2eXxXbyI\nwEEW31Um+SnNh6cZmTPVoqd5SPsCAwEAAaNQME4wHQYDVR0OBBYEFDTTf4DvdTKm\nb9zFuSvtFUr6XCuYMB8GA1UdIwQYMBaAFDTTf4DvdTKmb9zFuSvtFUr6XCuYMAwG\nA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB4Pj1V0Zxac5RF3uPPgzJyV\nVAIUc+Br3bcxmT69qLXe9JPkBSduLlOkpg2++RU2/IJ5KE4WSXm6hkfn+O/Erae0\n96OuE1OF+q+O/3mzMLh07+NWnGzFcQ7DF3wmMG3dp0Byy/clzYVxfkUlU3ZDCPyO\n5X6j/jxt2eH138sNO6Cx8Pea3LHu02LlpOCzgCsVLsbbZi8Lu7ZyYTPTTJbO/oMO\nRBabFyIWgvZpN3MO7Iyd07nTRiRg8dsDqwj0//zZrmfd9mMvbDzo4Suwb7IO04kC\noxe4tF8P47mzrEmFmR8FMGnHbGWFz8Gu8EQvz5l1FG+Z9o0zaCFPKVJUPZd8ztY=\n-----END CERTIFICATE-----\n";
}
map $server_name $site_key {
include /etc/ssl/private/*.conf;
default "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQChWzC0OJ/wZIHK\n6hP9FCqUgzvGdlZElo9kgwDyIRqBhspN6Jkr/duMKHvpPw+h4nRxBEpmAt1iJYmN\n7CAAAYPnlJ365pGn8hOASv6Z6HZA0iIxTPtCpW9zEJxta4zKyfheL4DFTbB14BQs\n1spMwsDyzyT3TxK9YanzZZHyWTSxwEwvzFvj3kSV29A/mhp+0wOy+tFD9m2mIx5X\nRjuH50mJAPLWvz0/oXwUT6+uitsoGmhngu4zzWiGjFyUKFjwTqhgtAaE+UDNV/vD\nIynPzjf7cMMUeboClQA40vX6LVxnID2m/kXIUtnl8V28iMBBFt9VJvkpzYenGZkz\n1aKneUj7AgMBAAECggEAUtiQVCgyrmncXkP7SVi+WAxdd5OwzXyEWTYOGUO36UM8\nwe2oH3cy726l2GdhblvoL1LlpCTaaBcf3jebYoVkpVWgG3+gz5syOg/HU1yQws1h\ncvC0nU51v52Kw3+SBVjX5fv74NH3xT3s/ey2Z90i1khXEYeO9p+bc/X1jnoQ3SYv\nAov2pncfaiStdi9g7URMHG9ZYMCAWi3nqbQ6xamZfrFiCQjfM8mpC9b/uQlek2bE\nOsLIS2umdYE1lt3f5wYdwHjUnHWAt3RUjAuI9Y78CUf87Hla+5kywGMFcT+LSsXq\nqTlFRCk4fcMmqUCNMFgdj7P0xulG014bbbb6cm5jQQKBgQDMNpHkBCkOFU5XFQ9K\n4gzXNWr+FF91+BdUDRjkhGb5ocBBujoVUZ/V+v+ioh2IwPHEPFXWSrPM2nVI0+2/\nGe5+aBinHj0sxWAfLRU8A4TPmfAt4MHNiE6PYMHiwxI0tP9nv8cA44xlIwJR7oJf\nxRhCS9uETzoFWxyBrTvsA46HmwKBgQDKRl2ZrDgOLZB7QHZC1HZulTI7u84hyOKM\ndoB52e+nP32cXID0X4p8me6yAP/LC0Rtp1Z8460NFyToXqk29xjo2aVO2hARltxE\nggeXaLL2q55niRulMvbloRXz+4kxP725NHW/33gBatv2TysU9/a/XWGrBA3qUrT8\nOtRqSKVKIQKBgFMtrwLXBvnrh7tEorP3mw9VfLz9A10DrkzYANmjbGYlki+zcNEa\nLCZ2VAWkTq9TF6a8hKICT3YTTU5atC3wnAn00IXRdU11H4/TRyDotgHxS7kEISxc\nZtNTr+VzW0kIqDdUD/S2uoq/VcSVh5kGqLjoOQONWa6wy82uCAg78qQdAoGAYMi2\ndJdA4xfOMAsyCtwaJuNge9Bq2yOBsu/onWU4FHB+q9hfI46rdt84pRdxTTgA7+7H\npU5TORY/5KeWk+Q7mP666DXSxnfGwUjuVPYV241WZ/fksHDoTgt7s5hBlr0HDJ0b\nUkmc5CC7SumqlYfoGryVxPxVpC8axi1oAcrsu8ECgYAlBXMs1vHwcepKaK6RTACZ\nqHlQbaDbnkJkiTzUv61D7hEFAghTy+uP1c/7//mopPcyJzS6mCmx6hYjsEdvrIQn\nC5SjEXcC/5UiNSl2+3YvooP/VQqaKmD0dhTSuAQ0OafoWybC3EbLsISvY87EagSA\nxzPH0XOM8P4jMgkcTBYP+g==\n-----END PRIVATE KEY-----\n";
}
To get the .conf map block line from the key/cert, I'm using the following scripts:
get_key_line.sh:
#!/bin/bash
echo -n "$1 \""; while read line; do echo -n "$line\\n"; done <$2; echo "\";"
get_cert_line.sh:
#!/bin/bash
echo -n "$1 \""; while read line; do echo -n "$line\\n"; done <$2; echo "$cert_r3\";"
These scripts are to be invoked in the following way:
# get_cert_line.sh website.com /etc/ssl/certs/website.crt >/etc/ssl/certs/website.conf
# get_key_line.sh website.com /etc/ssl/private/website.key >/etc/ssl/private/website.conf
Did you notice the script difference and the $cert_r3 part? That's because of nginx limitation of the configuration file line length, which is about 4K characters. This limitation makes impossible to include the full certificates chain with a single configuration line, so I finished up with the variables interpolation, with the every certificate map line looking as
website "-----BEGIN CERTIFICATE-----\n<cert data here>-----END CERTIFICATE-----\n$cert_r3";
and including an additional block to my nginx configuration file:
geo $cert_r3 {
default "-----BEGIN CERTIFICATE-----\nMIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw\nTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\ncmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw\nWhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg\nRW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\nAoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP\nR5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx\nsxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm\nNHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg\nZ3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG\n/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC\nAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA\nFHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw\nAoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw\nOi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB\ngt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W\nPTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl\nikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz\nCkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm\nlJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4\navAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2\nyJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O\nyK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids\nhCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+\nHlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv\nMldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX\nnLRbwHOoq7hHwg==\n-----END CERTIFICATE-----\n";
}
(Well, actually at the times this was written, I used two chained blocks including both R3 and ISRG Root X1 certificates, however the second one is not really needed anymore nowadays.)
Caution! Nginx documentation warns about the security implications of this syntax usage, such as writing secret key data to error log. As for me, possibility of exposing the key data via enabled SSI mechanism looks somewhat more dangerous.

install ssl certificate on nginx when provided with private key, CA and ssl certificate

I purchased SSL certificate from a certain hoster and I got these 4 files
> SSL Certificate:
> CSR:
> Private Key:
> CA Certificate:
How can I install those files into my VPS server using Nginx? My hoster is not collaborative, and I have to figure out how to install this to my client site. All googling leads me to the normal installation where we generate CSR from my VPS, submit to hoster, get certificates, merge and then fix them with Nginx, but for this case, I'm totally confused
Any help, I will appreciate
Typically if you receive your server certificate and private key you would place those in a directory on your web server then target those files inside of your config file. This can be a full path or a path relative to the .conf file where this server is configured.
Configure HTTPS server
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /path/to/your/file.crt;
ssl_certificate_key /path/to/your/file.key;
}
Depending on your certificate provider they should have also given you a file that contains the CA chains necessary for browsers to validate your certificate. I'm guessing the file you call CA Certificate is that file. You will need to combine both your server certificate and the CA certificate, then target that file inside of your nginx conifiguration.
Example:
cat SSL_Certificate CA_Certificate > website.crt
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /path/to/your/website.crt;
ssl_certificate_key /path/to/your/website.key;
}

Nginx load balancer SSL certs

I'm totally new to NGINX. I would like to use the free version (not nginx plus) to load balance (reverse proxy) between 3 servers and the connection must be SSL / 443.
Do i put the SSL certificate on the NGINX load balancer server or do I put 3 x SSL certs on the 3 web servers individually? I've heard mixed reviews. I'm looking for best performance.
Additional info: i'm using a wildcard SSL cert and the web other web servers are IIS with IP_Hash to keep sessions on the same web servers.
Open your configuration file again for edit.
sudo nano /etc/nginx/conf.d/load-balancer.conf
Then add the following server segment to the end of the file.
server {
listen 443 ssl;
server_name domain_name;
ssl_certificate /etc/letsencrypt/live/domain_name/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/domain_name/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
location / {
proxy_pass http://backend;
}
}
Then save the file, exit the editor and restart nginx again.
sudo systemctl restart nginx
With the HTTPS-enabled you also have the option to enforce encryption to all connections to your load balancer
server {
listen 80;
server_name domain_name;
return 301 https://$server_name$request_uri;
#location / {
# proxy_pass http://backend;
#}
}
Save the file again after you have made the changes. Then restart nginx.
sudo systemctl restart nginx
This question was asked already in the StackExchange network, but I'm going to try and answer your question anyway.
The performance impact should be noticeable, but it really depends on what you're running.
One thing to consider using multiple certificates, is that once the request hits the load balancer, it stays secure inside the datacenter/network.
This is useful, in cases where you don't own the hardware and don't have physical access to the machines/datacenter. This is because there are probably multiple people running servers and applications in a shared space and you can't know for sure if someone in that network is snooping around and watching the traffic. You just can't be sure that's not going to happen.
Using only one certificate (for the load balancer) is called 'SSL Offloading' and you can and should find out more about it here:
https://security.stackexchange.com/questions/30403/should-ssl-be-terminated-at-a-load-balancer
https://security.stackexchange.com/questions/79672/in-detail-how-does-ssl-offloading-acceleration-termination-work
SSL performance implications
https://serverfault.com/questions/112547/does-using-ssl-cause-a-significant-performance-hit

parametrize the server name in nginx conf

I have multiple domains all pointing to the same VM. (mydomain1.com, mydomain2.com, mydomain3.eu)
Now I have a huge nginx.conf which looks like this:
server {
listen 443 ssl;
server_name *.mydomain1.com;
ssl on;
ssl_certificate /etc/nginx/ssl/mydomain1.com.chained.crt;
ssl_certificate_key /etc/nginx/ssl/mydomain1.com.key;
# hundred more lines of rules
}
server {
listen 443 ssl;
server_name *.mydomain2.com;
ssl on;
ssl_certificate /etc/nginx/ssl/mydomain2.com.chained.crt;
ssl_certificate_key /etc/nginx/ssl/mydomain2.com.key;
# the same hundred more lines of rules
}
server {
listen 443 ssl;
server_name *.mydomain3.eu;
ssl on;
ssl_certificate /etc/nginx/ssl/mydomain3.eu.chained.crt;
ssl_certificate_key /etc/nginx/ssl/mydomain3.eu.key;
# the same hundred more lines of rules
}
Is there a way to shorten this - because currently I'm cloning such a huge code blcok when I have to add a new domain and only change the 3 lines where my domain name differs. I thought about some kind of parametrization, like (without knowing the correct syntax):
SERVER_NAME = {request_server_name}
ssl_certificate /etc/nginx/ssl/${SERVER_NAME}.chained.crt;
ssl_certificate_key /etc/nginx/ssl/${SERVER_NAME}.key;
is this possible? How?
There are two things you can do about it
Multi Domain SAN Certificate
You can purchase a multi domain SAN certificate. Which allows your to use different domains in the same certificate. So this way you wont have to have multiple blocks. In case you are using a self-signed certificate you can still create SAN certificate yourself
Use OpenRestry or Nginx+LUA
You can use OpenResty or Nginx with LUA support and use the ssl_certificate_by_lua_block directive of he same.
syntax: ssl_certificate_by_lua_block { lua-script }
context: server
phase: right-before-SSL-handshake
This directive runs user Lua code when NGINX is about to start the SSL handshake for the downstream SSL (https) connections.
It is particularly useful for setting the SSL certificate chain and the corresponding private key on a per-request basis. It is also useful to load such handshake configurations nonblockingly from the remote (for example, with the cosocket API). And one can also do per-request OCSP stapling handling in pure Lua here as well.
https://github.com/openresty/lua-nginx-module#ssl_certificate_by_lua_block
Also see below articles for some example implementations
https://medium.com/#mtourne/how-to-use-nginx-for-ssl-termination-for-any-domain-dc2e2c630058
https://blog.readme.io/auto-generating-ssl-certificates-for-custom-domains-using-lets-encrypt/

Nginx unable to get certificate CRL

I'm using nginx(1.1.9) for serving debian packages on https by using client certificate feature.
listen 443 ssl;
...
ssl_certificate /etc/ssl/ca.chain.crt;
ssl_certificate_key /etc/ssl/server.key;
#ssl_crl /etc/ssl/ca-crl.pem;
ssl_client_certificate /etc/ssl/ca.pem;
ssl_verify_client on;
ssl_verify_depth 2;
ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.1;
...
error_log /var/log/nginx/error.log debug;
...
I use reprepro to config an apt repo.I can use apt-get update to this repo without any error but when I comment out ssl_crl in order to use revocation list, Log display:
client SSL certificate verify error: (3:unable to get certificate CRL) while reading client request headers, client: xxx.xxx.xxx.xxx, server: apt.myrepo.com, request: "GET /ubuntu/dists/precise/non-free/i18n/Translation-en HTTP/1.1", host: "apt.myrepo.com"
I'm not sure why nginx can find my certificate revocation list.
This occurs because nginx needs to have CRLs for every certificate that's mentioned in ssl_client_certificate cert chain, including the root CA's CRL.
I hit this myself when I created root and intermediate CAs in order to generate certs for intranet sites. When I configured nginx to use SSL client authentication, I only used the CRL from our intermediate CA. nginx needs to see the CRL for every certificate in the chain, including the intermediate CA, to make sure that the intermediate CA's certificate hasn't been revoked by the root. Concatenating the root CRL onto the intermediate CRL fixed the issue.
Notes
The default CRL expiration period (default_crl_days) is 30 days, so you'll need to work out a system for keeping everything up to date.
Thank you to this post, which I found after much Google-fu, that suggested I was missing another cert in the chain.

Resources