Nginx and https. We get class A +

  • Tutorial

Recently, I recalled that there is such a service - StartSsl, which distributes trusted certificates to domain owners for free personal use. Yes, and the weekend was free. In general, now I’ll write how to configure HTTPS in nginx so that when checking in SSL Labs I get an A + rating and protect myself from the latest bugs with SSL cutting.

So let's get started. We will assume that you have already registered at StartSsl, passed a personal check and received a coveted certificate. To start, I will publish the final config, and after that I will analyze it.

That's what I did:

server {
    listen 80;
    return 301$request_uri;
server {
    listen 443 ssl spdy;
    ssl_stapling on;
    ssl on;
    ssl_certificate /etc/pki/nginx/;
    ssl_certificate_key /etc/pki/nginx/;
    ssl_dhparam /etc/pki/nginx/dhparam.pem;
    ssl_session_timeout 24h;
    ssl_session_cache shared:SSL:2m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    add_header Strict-Transport-Security "max-age=31536000;";
    add_header Content-Security-Policy-Report-Only "default-src https:; script-src https: 'unsafe-eval' 'unsafe-inline'; style-src https: 'unsafe-inline'; img-src https: data:; font-src https: data:; report-uri /csp-report";

In the first section, everything seems to be clear, any input via http with any URI will redirect with the same URI to the https scheme.

Let's start parsing the server section for https. Directive listen 443 ssl spdy; immediately turn on spdy. Here is the difference in the picture: The


next step is to enable ssl_stapling on;- we allow the server to attach OCSP responses, thereby reducing the page load time for users. The certificate chain (domain - intermediate authorization center - root authorization center) can contain 3-4 levels. And at each level, the browser must establish a connection and receive a certificate. You can send all the certificates (including the intermediate one: this is what the TCP sending windows was set up to ensure that the certificate chain fits in one packet forwarding) at once, then the browser will check the entire chain locally and only request the root one (which in most cases is already on client). For this function to work, it is imperative to describe a resolver - I have my own DNS server raised, so is specified as the value, you can specify, but many people have been complaining about it lately. What is ssl on; I think it makes no sense to tell.

Next, the ssl_certificate and ssl_certificate_key directives specify the paths to the certificates received through StartSsl. You already have 3 files:, and Copy the keys in (my case) / etc / pki / nginx.

Do not forget that the pem file for nginx must be merged with the CA certificate (It should come from 3x - 2 files.):

cp /etc/pki/nginx
cat > /etc/pki/nginx/

Now about ssl_dhparam /etc/pki/nginx/dhparam.pem; - this is necessary for Forward Secrecy to work for us. Direct secrecy means that if a third party recognizes any session key, then it can only get access to data protected only by this key. To preserve perfect direct secrecy, the key used to encrypt the transmitted data should not be used to obtain any additional keys. Also, if the key used to encrypt the transmitted data was obtained on the basis of some other key material, this material should not be used to obtain any other keys.

You can generate a key like this:

openssl dhparam -out /etc/pki/nginx/dhparam.pem 4096

Further simple settings ssl_session_timeout 24h; and ssl_session_cache shared: SSL: 2m;, which do not require special descriptions - the session expiration date and the size of the memory allocated for cache storage - I have a small blog, so 2 MB is enough.

Further - important parameters : ssl_protocols TLSv1 TLSv1.1 TLSv1.2; and ssl_ciphers kEECDH + AES128: kEECDH: kEDH: -3DES: kRSA + AES128: kEDH + 3DES: DES-CBC3-SHA:! RC4:! aNULL:! eNULL:! MD5:! EXPORT:! LOW:! SEED:! CAMELLIA :! IDEA:! PSK:! SRP:! SSLv2; - here we indicate that we only want TLS and the second line we burn all the SSL with red-hot iron. In light of the latest SSL files, it’s very important that I advise you too. Well and the ssl_prefer_server_ciphers on directive ; force nginx to strictly abide by this.

Directiveadd_header Strict-Transport-Security "max-age = 31536000;" tells browsers how much they should remember for these security requirements for my domain. In this case, 1 year. By the way, if you write the directive like this: add_header Strict-Transport-Security “max-age = 31536000; includeSubDomains; preload "; , then these conditions will apply to all domains of the third and higher level of your domain. Be careful here! I originally described it this way, but since StartSsl issues certificates for a limited number of subdomains, I stumbled upon the inability to even get to my subdomains, which serve a variety of admins, only those for which trusted certificates were issued worked. Therefore, I chose the first option for myself.

Further -add_header Content-Security-Policy-Report-Only "default-src https :; script-src https: 'unsafe-eval' 'unsafe-inline'; style-src https: 'unsafe-inline'; img-src https: data :; font-src https: data :; report-uri / csp-report "; - I really have not yet deeply studied the properties of this header. Content Security Policy (CSP) is a new standard that defines the HTTP headers Content-Security-Policy and Content-Security-Policy-Report-Only, which tell the browser a white list of hosts from which it can load various resources.


Temporarily, I took this line from a Yandex article about using CSPs from them, you can read more here: .

That seems to be all. A few links where you can check the results of your own and others' work:

1. SPDY Check - this is the result of my work .

2. SSL Labs - checking the quality of protection of your server .

Good luck, colleagues!

Also popular now: