๐ Securing Your NGINX Server with mTLS ๐ฅ
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
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. ๐๐