Configure your website with SSL using NGINX as a reverse proxy

Prerequisite

  • Ubuntu 18.04
  • nginx running
  • A domain – Example.com
  • Let’s Encrypt certificate

In this blog post we will configure your website and securing it with SSL using NGINX as a reverse proxy, forwarding traffic to your backend web server.

For the sake of simplicity lets that you are you are running wordpress website with IP 192.168.1.100 and nginx reverse proxy with IP 192.168.1.200.

When you enter http://192.168.1.216 in your browser you will open up your website. That works OK in a local enviroment, but if you’re going to publicy expose your website to the internet you’re going to have to use a domain and preferably a reverse proxy. When a request is made to your website, it will be forwarded to your reverse proxy. The reverse proxy will terminate the traffic to 192.168.1.100.

Why use a reverse proxy

A reverse proxy sits in front the web server and will forward visitors (client request) to that web server. It increases security because you won’t expose your backend web server to internet. You can configure the reverse proxy to forward request to multiple backend serverse, thus increasing the anonymity of your network.

Configuring NGINX and generate an SSL certificate

In the sites-available directory in /etc/nginx create a conf file.

sudo vim example.com 

Here you will type in the instructions for NGINX and where to forward request to example.com. But before we do that we have to generate a certificate. Let’s Encrypt is free and easy to use with certbot.

Generate a certificate using this command.

certbot -d example.com --manual --preferred-challenges dns certonly

Certbot will generate an ACME challenge that you will have to paste in your public DNS. Create a TXT record and paste the ACME challenge that certbot provided you. Wait up to five minutes before you continue so the TXT record can propagate.

If succesfull your certficate will be located in:

/etc/letsencrypt/live/example.com

Remember to renew your certificate. Let’s encrypt certificate are valid for 3 month. You can use this command to renew a certificate. I will create a new blog post on how you can create a grafana dashboard to monitor your SSL certificate and setting up email alerts. But thats for later.

# Stop nginx service
service nginx stop

# Run certbot renew
certbot -d example.domain.net --standalone --renew-by-default certonly


# Start nginx service
service nginx start

#####
# If your domain don't have an A record in a public DNS you have to use this command and paste the ACME challenge in your public DNS
certbot -d example.domain.net --manual --preferred-challenges dns certonly

Now, back to nginx. Open up the conf file you created in sites-available and paste in this content. Edit example.com with your domain. Edit ssl_certificate and ssl_certificate_key so they point to the correct directory. Certbot provided you with the directories when you generated the certificate.


server {
    if ($host = example.com) {
        return 301 https://$host$request_uri;
    } 

        listen 80 ;
        listen [::]:80 ;

        server_name example.com www.example.com;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }
}


map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
}

# HTTPS Server
server {
    listen 443 ssl;
    server_name example.com;

    # You can increase the limit if your need to.
    client_max_body_size 200M;

    error_log /var/log/nginx/example.access.log;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # don’t use SSLv3 ref: POODLE
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    ssl_stapling on;
    ssl_stapling_verify on;

    location / {
        proxy_pass http://192.168.1.100;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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 X-Forwarded-Proto https;
        proxy_set_header X-Nginx-Proxy true;

        proxy_redirect off;
        auth_basic off;
    }

}

We will have to create a symlink to etc/nginx/sites-enabled.

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com

Verify that the syntax is correct and reload nginx service.

nginx -t 

##nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
##nginx: configuration file /etc/nginx/nginx.conf test is successful

service nginx restart

Create an A record in your public DNS

Port forward 443 on your router so that the outside world can talk to your reverse proxy.

Then you have to create an A record in your public DNS which points to your public IP address.

Now, visit your website from outside your local network. Your website now have a green lock and works fine.

Last few words

If you want to test your SSL configuration you can use this website [https://www.ssllabs.com/ssltest/]. It will give you a rating based on these attributes; Certificate, Protocl Support, Key Exchange and Cipher Strength. You can then determin how you want to increase security further.

Similar Posts

2 Comments

  1. Hello my loved one!
    I wish to say that this article is amazing, great written and include approximately all important infos.

    I would like to peer extra
    posts like this .

Comments are closed.