๐Ÿš€ Securing Your NGINX Server with mTLS ๐Ÿ’ฅ

Saidu BelloSaidu Bello
5 min read

With cyber threats becoming more rampant in today's digital world, it is crucial to fortify your web servers with a more sophisticated security measure.

the term "mTLS" might sound familiar if you have heard of TLS in the past.
Basically, mTLS stands for mutual transport layer security which is a powerful authentication method that adds an extra layer of protection to your server, ensuring that both client and server can trust each other's identities before establishing a secure connection.

In this article, I will guide you through the proper steps of setting up mTLS on an NGINX server.

Note: we will be using let's encrypt the generate keys for the server and then a self-signed CA will be used to generate and sign the client certificates.

The following are the main points covered in the article:

  • Installing Nginx on an Ubuntu server.

  • Installing certbot

  • Generate let's encrypt certificates on the server

  • Generating a self-signed root Certificate Authority (CA) and client Certificate.

Step 1 - Installing Nginx

NGINX can be installed from Ubuntu's default repositories using the apt package system.

$ sudo apt update
$ sudo apt install nginx

Before putting Nginx to the test, let's make sure the firewall software is properly configured to allow access to the appropriate ports.

View the application settings recognized by ufw by typing the following command:

$ sudo ufw app list

Result

Output
Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH

The above profile list is configured for exposing specific ports

  • Nginx Full: This profile enables access to both port 80 (non-secure web traffic) and port 443 (TLS/SSL encrypted traffic).

  • Nginx HTTP: This profile allows access to only port 80 (non-secure web traffic).

  • Nginx HTTPS: This profile grants access to port 443 (TLS/SSL encrypted traffic).

  • openSSH: This profile grants access to an open secure shell on port 22

You can enable any of the profiles using the below command.

$ sudo ufw allow <Profile>

Check the status of your Nginx server using the below command.

$ systemctl status nginx
Output
โ— nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2022-03-01 16:08:19 UTC; 3 days ago
     Docs: man:nginx(8)
 Main PID: 2369 (nginx)
    Tasks: 2 (limit: 1153)
   Memory: 3.5M
   CGroup: /system.slice/nginx.service
           โ”œโ”€2369 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           โ””โ”€2380 nginx: worker process

The above output simply means your Nginx server is up and running just fine.
You can actually confirm this using your browser.

Step 2 - Installing Certbot

Certbot can be installed from Ubuntu's default repositories using the apt package system.

sudo apt install certbot python3-certbot-apache

Step 3 - Generating Let's Encrypt certificate

Obtain an SSL certificate for your domain using Certbot with the command below.

sudo certbot --nginx -d your_domain.com

Certbot will guide you through the certificate issuance process, and it may ask if you want to redirect HTTP traffic to HTTPS. Choose the appropriate option.

Automate renewal: Let's Encrypt certificates expire after 90 days. To automate the renewal process, create a cron job to run Certbot periodically:

sudo crontab -e

Add the following line to run Certbot renewal checks twice a day

0 */12 * * * certbot renew

Test renewal (optional): You can manually test the certificate renewal with the following command:

sudo certbot renew --dry-run

If it runs successfully without errors, your certificate renewal is properly configured.
At this point, the server has SSL correctly configured, allowing us to access the domain using the https:// protocol.

Step 4 - Generate a self-signed Root CA & Client Certificate

To create a self-signed root Certificate Authority(CA) and use it to sign the client certificate. We need OpenSSL installed on the machine.

Create a Root CA

Create a directory to store your CA files

mkdir myCA
cd myCA

Generate a private key for the Root CA:

bashCopy codeopenssl genpkey -algorithm RSA -out rootCA.key

Create a self-signed certificate for the Root CA using the private key:

openssl req -new -key rootCA.key -x509 -days 3650 -out rootCA.crt

This will generate rootCA.crt as your self-signed root CA certificate.

Reference the root CA in your Nginx config file.
check /etc/nginx/sites-enabled/default or your config custom config file path if you are not using nginx default config file.

    ssl on;
    ssl_certificate /etc/letsencrypt/live/path to cert;        # Your server certificate
    ssl_certificate_key /etc/letsencrypt/live/path to key;    # Your server private key
    ssl_client_certificate /path/to/rootCA.crt; # Your Root CA certificate
    ssl_verify_client on;

Create a Client Certificate

Now, you can create a client certificate key and signing request (CSR). Replace "client" with your desired client name

openssl genpkey -algorithm RSA -out client.key

Generate a signing request (CSR):

openssl req -new -key client.key -out client.csr

Sign the Client Certificate with Root CA

Sign the client certificate using your Root CA:

openssl x509 -req -in client.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out client.crt -days 365

This will generate client.crt, which is the client certificate signed by your self-signed root CA.

We can test the configurations so far by using a curl request and appending the certificate path alongside the curl request

curl --cert client.crt --key client.key <your domain>

The request will definitely fail if the client certificate is invalid. Furthermore, your browser will throw this error in case of an invalid certificate or no certificate was provided at all.

Thank you for reading ๐Ÿ˜Š.
Please feel free to reach out if you encounter any challenges following the above steps

Email: saeedbello12@gmail.com

1
Subscribe to my newsletter

Read articles from Saidu Bello directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Saidu Bello
Saidu Bello

Versatile Cloud-Native Tech Bro| Mobile Maestro ๐Ÿš€ ๐Ÿ“ฑ Flutter + Swift โœจ | ๐ŸŒ Node.js + TypeScript ๐Ÿช„ ๐Ÿ”ต Postgres | ๐Ÿ”ถ MySQL | ๐Ÿƒ MongoDB | โ˜๏ธ Firestore ๐Ÿณ Kubernetes & Docker Enthusiast ๐ŸŒŸ Elevating the Digital Realm, One Line of Code at a Time. ๐Ÿš€๐ŸŒ