Setting up a UFW Secured Nginx Reverse Proxy with HTTP Authentication and TLS Certificates from Let’s Encrypt

Syed R Ali
10 min readAug 6, 2019
Secure data exchange
Image by C-Data Exchange from CIT

Web application security is a central component of any web-based system. The global nature of the Internet exposes web properties to attack from different locations and various levels of scale and complexity. Web application security deals specifically with websites, web applications and web services such as APIs.

This article covers basic securing of access to your web application or service using an Nginx reverse proxy, HTTP authentication, Transport Layer Security encryption with certificates from Let’s Encrypt, and the Uncomplicated Firewall commonly used with Debian based Linux distributions.

SSL certificate & Nginx configuration best practices
Image by Jun from Relics of the deceased

A proxy server is a go‑between or intermediary server that forwards requests for content from multiple clients to different servers across the Internet. A reverse proxy server is a proxy server that typically sits behind the firewall in a private network and directs client requests to the appropriate backend server. A reverse proxy provides an additional level of abstraction and control to ensure the smooth flow of network traffic between clients and servers.

Use Nginx
Image by Mr. Xu from Mr. Xu’s blog network

Nginx is a free, open-source, high-performance HTTP server and reverse proxy and an IMAP/POP3 proxy server. Nginx is known for its high performance, stability, rich feature set, simple configuration, and low resource consumption.

Nginx is built to offer low memory usage and high concurrency. Rather than creating new processes for each web request, Nginx uses an asynchronous, event-driven approach where requests are handled in a single thread.

HTTP Basic Authentication
Image by Java EE from Oracle

In the context of a Hypertext Transfer Protocol transaction, basic access authentication is a method for an HTTP user agent, e.g. a web browser, to provide a user name and password when making a request.

In basic HTTP authentication, a request contains a header field of the form Authorization: Basic <credentials>, where credentials are the base64 encoding of id and password joined by a single colon.

How a WordPress SSL Certificate Work?
Image by Moeez from WPblog

Transport Layer Security, or TLS, is a protocol that provides authentication, privacy, and data integrity between two communicating computer applications. It’s the most widely deployed security protocol used today.

TLS is used for web browsers and other applications that require data to be securely exchanged over a network, such as a web browsing session, file transfer, VPN connection, remote desktop session, and voice over IP. In common parlance, TLS is often referred to by the name of its deprecated predecessor, Secure Sockets Layer, or its web-based implementation, HTTP Secure.

Let’s Encrypt
Image by Let’s Encrypt from Let’s Encrypt

Let’s Encrypt is a non-profit certificate authority run by the Internet Security Research Group that provides X.509 certificates for TLS encryption at no charge. The certificate is valid for 90 days, during which renewal can take place at any time. This provision is accompanied by an automated process designed to overcome manual creation, validation, signing, installation, and renewal of certificates for secure websites.

Firewall
Image by Blog from Datacentreplus

A firewall is a network security device that monitors incoming and outgoing network traffic and decides whether to allow or block specific traffic based on a defined set of security rules.

Firewalls have been the first line of defence in network security for over twenty-five years. They establish a barrier between secured and controlled internal networks that you can trust and untrusted outside networks, such as the Internet.

Image by Arnaud Lemercier from Coded Design

The Uncomplicated Firewall, or UFW, is a frontend for managing firewall rules in Arch Linux, Debian, or Ubuntu.

UFW is used through the command line, although it has GUIs available, and aims to make firewall configuration easy or uncomplicated.

Reverse proxy server diagram
Image source unknown

One advantage of a reverse proxy and the main reason we’re using it in this example set-up is that it makes it easy to set up HTTP authentication, have all other access restricted via the firewall, and encryption with HTTPS using a TLS certificate.

To provide this basic level of security and authenticated access to your web application, let’s start with setting up the reverse proxy to it via Nginx.

First, download the latest package lists, and update them to get information on the newest versions of packages and their dependencies.

sudo apt-get update

To install Nginx, you must execute the following command on the Debian-based Linux host that will be acting as the reverse proxy server:

sudo apt-get install nginx

Once Nginx has been installed, the next step is to disable the default virtual host.

sudo unlink /etc/nginx/sites-enabled/default

Then, we need to create a file within the /etc/nginx/sites-available directory that contains the reverse proxy information pointing at your web application location. We can name this reverse-proxy.conf for example.

sudo nano /etc/nginx/sites-available/reverse-proxy.confserver {
listen 80;
server_name your_reverse_proxy_host;
location / {
proxy_pass http://your_web_application_host:port;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

Once you’ve added the appropriate directives to your configuration file, activate it by linking to /sites-enabled/ using the following command:

sudo ln -s /etc/nginx/sites-available/reverse-proxy.conf /etc/nginx/sites-enabled/reverse-proxy.conf

Lastly, run an Nginx configuration test to verify the syntax of your configuration edits.

sudo nginx -t

If you get an error, reopen the reverse proxy configuration file and check for any typos or missing characters. Enable Nginx to start at system boot-up:

sudo systemctl enable nginx

Restart Nginx by starting and stopping the service using the systemctl command to pick up the configuration changes.

sudo systemctl restart nginx

Your web application should now be available at: http://your_reverse_proxy_host/

Image source unknown

Next, we’ll look at how to restrict access to an Nginx website using HTTP basic authentication. HTTP basic authentication is a simple username and hashed password authentication method. First, you’ll create a password for the user who will be using the website.

Image by David from Medium

You will store that password and the associated username in a file that you specify. You will encrypt the password, and the name of the file can be anything you like.

Here, we use the file /etc/nginx/.htpasswd and username we specify. To create the encrypted password, run the following command. You’ll need to authenticate, then specify and confirm a password.

sudo htpasswd -c /etc/nginx/.htpasswd username

You can check the contents of the newly-created file to see the username and hashed password.

cat /etc/nginx/.htpasswd

Example /etc/nginx/.htpasswd:

username:$apr1$ilgq7ZEO$OarDX15gjKAxuxzv0JTrO/

Now that you’ve created the HTTP basic authentication credential, the next step is to update the Nginx configuration for the target website to use it.

HTTP basic authentication is made possible by the auth_basic and auth_basic_user_filedirectives. The value of auth_basic is any string and will be displayed at the authentication prompt; the value of auth_basic_user_file is the path to the password file you created above.

Both directives should be in the Nginx configuration file of your reverse proxy. Open that configuration file. Under the location section, add both directives, then save and close the file:

sudo nano /etc/nginx/sites-available/reverse-proxy.conf. . .location / {
auth_basic "Private Website";
auth_basic_user_file /etc/nginx/.htpasswd;
. . .
}. . .

Check your changes by testing the new configuration.

sudo nginx -t

Then to apply the changes, restart Nginx, dropping any current connections:

sudo systemctl restart nginx

Now try accessing your website, which you just secured by going to http://your_reverse_proxy_host/ in your browser. Your website should present you with an authentication window (which says "Private Website", the string we set for auth_basic), and you will not be able to access the website until you enter the correct credentials. If you enter the username and password you set, you'll see your web application home page.

The Uncomplicated Firewall
Image by Jack Wallen from Tech Republic

The Uncomplicated Firewall or UFW is a frontend for the most widely used Linux firewall, iptables , which is used for host-based firewalls. UFW gives a command-line interface for controlling the firewall.

UFW provides a user-friendly and easy to use interface without having to be too familiar with firewall concepts. If it’s not installed, you can install it using the apt command shown below.

sudo apt-get install ufw

By default, every incoming connection is denied. It is recommended that you enable the most restrictive profile that will still allow the traffic you’ve configured. Typically this will be web traffic via Nginx and Secure Shell connections to access our reverse proxy host. To allow both incoming and outgoing connections on port 22 for SSH, you can run:

sudo ufw allow ssh

Before you use UFW, you should check whether it is running or not. Use the following command to check it:

sudo ufw status

If you found Status: inactive, it means it’s not active or is disabled. To enable it, you need to type the following command at the terminal.

sudo ufw enable

Nginx registers itself as a service with UFW upon installation. This makes it rather easy to allow Nginx access. We can list the applications configurations that UFW knows how to work with by typing:

sudo ufw app list

Next, enable full Nginx traffic. This will allow both HTTP and HTTPS on port 80:

sudo ufw allow 'Nginx Full'

After the firewall is activated and you have added your rules into it, you can type the below if you want to see these.

sudo ufw status verbose
Certificate-based mutual authentication
Image by Java EE from Oracle

Certbot is a tool from Let’s Encrypt that allows you to obtain certificates to enable TLS over HTTP quickly. Follow these steps to get a certificate via Certbot. Certbot will automatically update your Nginx configuration files to use the new certificate.

Image by Certbot from EFF

Update the package lists, then add the Universe repository. This repository consists of free and open-source software that doesn’t have a guarantee of regular security updates. You may find it already enabled.

sudo apt-get updatesudo add-apt-repository universe

Next, add the software properties common package. This provides an abstraction of package repositories. It allows you to manage your distribution and independent software vendor software sources easily. In practice, that means it provides some useful scripts for adding and removing Personal Package Archives:

sudo apt-get install software-properties-common

A PPA is a package archive that allows software developers to create their own repositories for Ubuntu-based distributions such as Ubuntu itself, Linux Mint, Linux Lite, Zorin OS, and others.

You can add a PPA repository, then when you update your system, your system would know about the availability of new software, and you can install it using the standard install command. Add the Certbot PPA, then update the package list to pick up the new repository’s package information.

sudo add-apt-repository ppa:certbot/certbotsudo apt-get update

Now you can install Certbot with the Nginx extension and start it.

sudo apt-get install python-certbot-nginxsudo certbot --nginx

Certbot needs to be able to find the correct server block in your Nginx configuration for it to configure SSL automatically. Specifically, it does this by looking for a server_namedirective that matches the domain you request a certificate for. To check, open the server block file for your domain:

sudo nano /etc/nginx/sites-available/reverse-proxy.conf

Find the existing line. It should look like this if you followed the Nginx configuration earlier:

. . .
server_name your_reverse_proxy_host;
. . .

If it does, you can exit your editor and move on to the next step. If it doesn’t, update it to match. Then save the file, quit your editor, and test the syntax of your configuration edits.

sudo nginx -t

Once your configuration file’s syntax is correct, reload Nginx to load the new configuration. Certbot can now find the correct server block and update it. Have Nginx reload its configuration without dropping any current connections:

sudo systemctl reload nginx

Next, obtain the TLS certificates. The Nginx plug‑in for certbot takes care of reconfiguring Nginx and reloading its configuration whenever necessary. Run the following command to generate certificates with the Nginx plug‑in:

sudo certbot --nginx -d yourwebapplicationhost

You will be prompted to enter your email address and agree to the terms of service. If successful, Certbot will ask you how you would like to configure your HTTPS settings:

Image by James Kiarie from TecMint

Select your choice and hit enter. Your certificates will be downloaded and installed. Browse to your reverse proxy server using HTTPS rather than HTTP, and you will see that access to your web application via the reverse proxy now has TLS encryption enabled.

Let’s Encrypt’s certificates are only valid for ninety days. This is to encourage users to automate their certificate renewal process. The certbot package we installed takes care of this for us by adding a renew script to /etc/cron.d.

This script runs twice a day and will automatically renew any certificate that's within thirty days of expiration. To test the renewal process, you can do a dry run with:

sudo certbot renew --dry-run

If you see no errors, you’re all set. When necessary, Certbot will renew your certificates and reload Nginx to pick up the changes.

If the automated renewal process ever fails, Let’s Encrypt will send a message to the email you specified, warning you when your certificate is about to expire.

Your web application now has a basic level of secured access with a reverse proxy, HTTP authentication, TLS, and a firewall.

📝 Read this story later in Journal.

👩‍💻 Wake up every Sunday morning to the week’s most noteworthy stories in Tech waiting in your inbox. Read the Noteworthy in Tech newsletter.

--

--

Syed R Ali

Londoner, desi, financial technologist, geek, weight training & combat sports junkie.