SSL Advanced Configuration: NGINX on MAC (Part 4)

Nginx from Beginner to Advanced

The previous 3 parts are available here: Installing Nginx, Simple Configuration & Self-Signed SSL.

In this part we will continue our quest to a more better and secure Nginx configuration by setting directives that will help with security & performance optimisations.

Here is the file from previous tutorial. We will be adding directives inside the HTTPS server context.

events {}http {
# HTTP server
server {
listen 80;
return 301 https://localhost:443;
}
# HTTPS server
server {
listen 443 ssl;
ssl_certificate /usr/local/etc/ssl/certs/self-signed.crt;
ssl_certificate_key /usr/local/etc/ssl/private/self-signed.key;
location / {
root /Users/arjav/Desktop/www;
index index.html index.htm;
}
}
}

Transport Layer Security (TLS) are a set of cryptographic protocols to communicate securely over a computer network. TLS v1.1 and older uses cipher suites that are insecure in today’s world. So let’s just enable TLS 1.2 & 1.3. Add the new directive just below listen 443 ssl;

ssl_protocols TLSv1.2 TLSv1.3;

TLSv1.2 and TLSv1.3 have secure enough cipher suites. So it would be okay to have the below option as off. What it basically says is allow the client to select the cipher algorithm that is best for itself but defined in TLSv1.2 and TLSv1.3 only.

ssl_prefer_server_ciphers off;

In case you are as skeptical as me and want to allow a specific cipher suites only, you can turn it on as below and mention the list of ciphers. Do remember that the order of the cipher matters and the client will make selection in that order.

ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";

When a client communicates with a server it needs to verify the server certificate either via Certificate Revocation List (CRL) or an Online Certificate Status Protocol (OCSP). The CRL process is bandwidth consuming and resource heavy while OCSP is much more light weight but with its own issues. Since we are using a self-signed certificate on a local machine it won’t be an issue, but for 3rd party certificates all the intermediate certificates needs to be present in your ssl certificate. This can alleviated by using ssl_trusted_certificate directive. You can read more about it here.

ssl_stapling on;
ssl_stapling_verify on;

Diffie-Hellman is one of the most common key exchange used in Perfect Forward Secrecy (PFS). Open terminal and run the below command to generate parameters for Diffie-Hellman key exchange. Note: It will take a long time to generate the parameters.

sudo openssl dhparam -out /usr/local/etc/ssl/certs/dhparam.pem 4096

Once generated you can use these parameters by adding the following directive in Nginx

ssl_dhparam /usr/local/etc/ssl/certs/dhparam.pem;

The below directive tells the client that you are allowed to contact the server only via secure HTTPS protocol. Our server is like: Till 'max-age' time passes you cannot contact me via un-secure channels.. If you don't want to include subdomains you can remove includeSubdomains

add_header Strict-Transport-Security "max-age=63072000; includeSubdomains" always;

The next directive is used when you don’t want to allow your side to be embedded in an iFrame. For more frame options you can visit Mozilla’s site.

add_header X-Frame-Options DENY;

Lastly we disable Content or MIME sniffing by applying the below directive. It is one of the key things for avoiding XSS attacks. Also if you will get your site audited it is one of the response headers that needs to be set.

add_header X-Content-Type-Options nosniff;

There are a lot of other response headers you can set to optimise the website and increase security. For further details Mozilla has great resources for the same: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers.

Caching a TLS connection is helpful to avoid unnecessary handshakes in turn increasing your performance of the site. The caching can be set with the help of below directives.

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1h;

The directives say that the session cache is shared among all worker processes and can use upto 10MB of space. The time out for each session is 1h.

These SSL directives will make your website secure and perform better. Our final nginx.conf file will be as below:

events {}http {
# HTTP server
server {
listen 80;
return 301 https://localhost:443;
}
# HTTPS server
server {
listen 443 ssl;
ssl_certificate /usr/local/etc/ssl/certs/self-signed.crt;
ssl_certificate_key /usr/local/etc/ssl/private/self-signed.key;
# Enable only TLSv1.2 TLSv1.3;
ssl_protocols TLSv1.2 TLSv1.3;
# Enable cipher suites
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
# Enable OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# Set DH parameters
ssl_dhparam /usr/local/etc/ssl/certs/dhparam.pem;
# Add Response Headers
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains" always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options "nosniff";
# Cache Connections
ssl_session_cache shared:SSL:10m;
location / {
root /Users/arjav/Desktop/www;
index index.html index.htm;
}
}
}

PS: Since Nginx is cross-platform these directives can work on any OS. Just make sure that you select the paths specific to OS.

That concludes our 4 part series of NGINX on MAC. Hope you have enjoyed it. If you are looking for installing & configuring Nginx on Linux to host a laravel project digital ocean has a nice tutorial Installing & Configuring Laravel. Make sure to go through the pre-requisites.

Royale Cheese: Co-Founder & Technical Director