📜 ⬆️ ⬇️

Let's Encrypt and Express. To each server - on the green lock

HTTPS is becoming an increasingly strong trend of the modern Internet. And this is good, especially when clients, interacting with servers, exchange confidential data with them. In order to use HTTPS, you need an SSL certificate that is used to authenticate the server. The Let's Encrypt project has greatly simplified the process of obtaining SSL certificates. Before his appearance, everything was much more complicated.

image

Let's Encrypt use Certbot from the Electronic Frontier Foundation to automate the process of obtaining an SSL certificate. Different types of web servers are supported (Apache, nginx, and others) that run on Unix-like operating systems. If your server meets the Let's Encrypt system requirements, it means that you can get a certificate in almost completely automatic mode. Unfortunately, Let's Encrypt does not support the Node.js / Express.js bundle. That is, in this case, it will not be possible to automatically receive a certificate from Certbot. However, all is not lost. Using Let's Encrypt and Certbot, the certificate is not so difficult to get manually.

Preliminary Information


We are going to use Certbot in webroot mode, running it with the --webroot . In a nutshell, in this mode, Certbot will place the file in some directory of our server, which should be accessible via HTTP.

Using Express, you can serve directories containing static files using the express.static() function.
')
If you look at the Certbot section of the webroot mode , it turns out that Certbot will search the server for the file at http://<your_server_url>/.well-known/acme-challenge/ . If he can successfully obtain the HTTP file that was placed in the specified directory, he will create an SSL certificate for this server.
So let's get started.

Work plan


To obtain a certificate and maintain its relevance, we will need to go through five stages:

  1. Redirect the appropriate ports.
  2. Set up the directory structure for static files and organize its maintenance using Express.
  3. Install and run Certbot.
  4. Configure Express to use HTTPS.
  5. Renew Let's Encrypt certificate after 90 days.

Below we describe these stages in more detail, with examples of code and commands.

Port Forwarding


I am sure that this will not cause anyone any difficulties, but, for completeness, I will describe this step.

To successfully complete the verification process, a server URL is required. Certbot will use this URL to connect to the server and retrieve data via HTTP. This means that port 80 on the provided URL must be accessible from the Internet. It does not hurt to open port 443, since this is the default HTTPS port.

Personally, I prefer to keep my Express servers on ports whose numbers are higher than 1024, and then, using the redirection rules, send traffic from ports 80 or 443 to the servers. As a result, I do not need to give Express elevated privileges, which is safer, especially considering that the web server will handle potentially dangerous traffic.

In order to check the network settings, you can use the curl utility. For example, if the server has an address for testing system health (which is always useful), a request to that address can be made using curl . Suppose a server is configured like this:

 // filename: app.js const app = require('express')(); app.get('/health-check', (req, res) => res.sendStatus(200)); app.listen(8080); 

If you access the health-check endpoint with curl , that everything is fine, the HTTP 200 will indicate the answer.

 curl http://<your_server_url>/health-check 

When the network and the server are ready for operation, you can proceed to configuring the maintenance of static files.

Serving static files


As mentioned above, the address that Certbot will contact to check the server is /.well-known/acme-challenge . Express uses the express.static() function to serve static files along the path specified by this function. This path becomes the root of the server. Often, a folder that stores static website data is called public or static , and, for example, if you have a text file visible in the file system as /static/test-text/mytextfile.txt , you can access it from the outside at http://<your_server_url/test-text/mytextfile.txt . Given this, we will create a directory structure for the needs of Certbot and connect it to Express.

 cd static mkdir -p .well-known/acme-challenge 

The above command is executed from the project root, which implies that the static data directory is static .

 // filename: app.js const express = require('express'); const app = express(); app.use(express.static('static')); app.listen(8080); 

Now, after Express is configured to maintain the correct folder, check the system for proper operation.

 echo "this is a test" > static/.well-known/acme-challenge/9001 curl http://<your_server_url>/.well-known/acme-challenge/9001 

If the text “this is a test” is displayed in the console, this step is successfully completed and you can go further - to create a new SSL certificate.

Certbot


The first step in this step is to install Certbot. Here you can find installation instructions. Namely, in order to see them, in the I'm using field, select None of the above , then, in the next field, select your OS. After that, the command for installation will be shown. For example, for Ubuntu 16.04 (xenial) this command looks like this: sudo apt-get install letsencrypt .

The next step is to generate a certificate. As already mentioned, we are going to run Certbot in webroot mode. To do this, you will need to pass to it the path that will be used as the root of the web server (using the –w key) and the domain name (using the –d key). In this case, the command looks like this:

 letsencrypt --webroot -w ./static -d <your_server_url> 

Here we assume that you are in the project directory. After successful execution of the command, you will see the corresponding message and information about the location of the generated files. They are usually located at /etc/letsencrypt/live/<your_server_url> . You can find out about these files in the Webroot section of the Certbot manual. We are going to use the fullchain.pem and privkey.pem files with our Express server.

Fine! Here it is, our new SSL certificate. Now use it.

Express and HTTPS


Express, immediately after installation, works only over HTTP. We can configure the use of HTTPS in Express using the Node https module. In order to do this, you will need two files - a certificate and a private key. By the way, keep the secret key of your server from prying eyes, and only authorized users can access the secret key file.

In addition, it is recommended to either copy the fullchain.pem and privkey.pem to the project directory, or create symbolic links to them. Creating symbolic links simplifies the update process, but what you choose is up to you.

The code below is based on the assumption that the fullchain.pem and privkey.pem are in the sslcert folder in the project directory.

 // filename: app.js const https = require('https'); const fs = require('fs'); const express = require('express'); const app = express(); //   Express const options = {   cert: fs.readFileSync('./sslcert/fullchain.pem'),   key: fs.readFileSync('./sslcert/privkey.pem') }; express.listen(8080); https.createServer(options, app).listen(8443); 

In addition, Helmet.js does not hurt here . This package helps protect the Express server by managing the HTTP headers. It adds, among other things, HSTS , removes the X-Powered-By header and sets the X-Frame-Options header to protect against clickjacking .

It is very easy to install:

 npm install --save helmet 

After installing Helmet, it can be used in Express as an intermediate layer of data processing.

 // filename: app.js app.use(require('helmet')()); 

Now, to finally make sure that everything is working, you can test the server with something like SSL Server Test .

Certificate renewal


Certificates Let's Encrypt are valid for 90 days. Good or bad - to argue is pointless, especially considering that the process of renewing a certificate is very simple. Namely, to update the certificate, it is enough to execute the command letsencrypt renew and Certbot will issue a new certificate. It is recommended to automate this process using either cron jobs or something like systemd .

findings


As a result, we configured the Express server to serve static files in a specific path, used Certbot in webroot mode to create a server certificate and connected HTTPS to Express using the newly created certificate. Although the automatic process of interaction with Certbot is not available to us, it’s not so difficult to do everything manually.

I would like to hope that Certbot, in the foreseeable future, will be equipped with Node.js support.

How do you get SSL certificates for Express servers? Do you use certificates from Let's Encrypt?

Source: https://habr.com/ru/post/321268/


All Articles