Nginx Reverse Proxy with TLS Encryption

TLS encryption of traffic is a security must have. In this article, I show how to create and install a self-signed certificate, and how to configure Nginx for providing encryption to all ingress and egress traffic.

My infrastructure at home is running: Docker as the execution environment for all applications, Nomad for scheduling Docker jobs, Consul for service discovery, and Traeffik as the edge router. In the next posts, I will evolve my infrastructure by securing the communications between the components and by adding new applications.

In the last article, I explained how to setup Nginx as a Reverse Proxy that uses Consul DNS entries to forward the requests. Now we need to encrypt all HTTP traffic. We will do this by generating TLS certificates with the openssl command line tool, and then configure Nginx to process HTTP requests.

With this, we will fulfill the following two requirements:

This article originally appeared at my blog.

Certificate Generation process

The normal way to generate certificates involves multiple steps:

Do you need to follow all these steps? Well, it depends. If you want to provide a certificate for a service or web page which is public, then you need to involve a paid certificate authority or use the free, three months valid certificates from Lets Encrypt. If you need a certificate inside a local network, for a local domain, you can self-sign certificates.

Self-signed certificate will be our choice.

Creating Certificates with OpenSSL

The openssl command line utility is a versatile tool: It offers commands to create, sign and validate different types of certificates, t can be used to encrypt files or compute hash values from files, and you can test TSL connections from client to server 1.

To generate a certificate, we need to execute the following command:

openssl req -new -x509 -days 90 -newkey rsa:4096 -sha512 -nodes -out admantium.cert -keyout admantium.key

The flags look scary — lets understand them:

The next step is to use the required directives in Nginx, as shown in the next snippet:

server {
server_name prometheus.infra;
listen 443 ssl;
ssl_certificate /etc/nginx/certs/admantium.cert;
ssl_certificate_key /etc/nginx/certs/admantium.key;
}

Finally, to increase the security, I also recommend to add the following directives to the http block:

http {
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256";
ssl_prefer_server_ciphers on;
}

Testing the Connection

Restart Nginx and browse to a page. Your browser will notify you that “the page is not secure” — a very misleading message! The message is about complaining that the certificate authority is not a well-known one — which is true, since we self-signed the certificates. But the connection is secured with TLS encryption. You need to accept the notification, and then browse normally.

Configure DNSmasq

The final piece is to set DNS resolution so that clients and services reach each other only via your TLS enabled proxy server. When you have followed my series, you know that I’m using DNSMasq. On each server, the DNSmasq configuration file needs to include an address setting that points to the server running Nginx.

address=/infra/192.168.2.201

Now you can resolve any https://*.infra addresses.

Critical Review

So, the goal is achieved, but it has two drawbacks:

Summary

This article explained how to provide TLS encryption to Nginx. We explored the OpenSSL command line utility to create a self-signed certificate. We showed how to configure Nginx to listen to TLS connection and provide the generated certificate. Finally, I showed how to configure DNSmasq to use Nginx for resolving all traffic inside the cluster.

Footnotes

--

--

IT Project Manager & Developer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store