Let’s Encrypt и Express. Каждому серверу – по зелёному замку́

в 13:34, , рубрики: express, HTTPS, node.js, SSL, Блог компании RUVDS.com, хостинг, хранение данных, хранилища данных

HTTPS становится всё более сильным трендом современного интернета. И это хорошо, особенно, когда клиенты, взаимодействуя с серверами, обмениваются с ними конфиденциальными данными. Для того, чтобы пользоваться HTTPS, нужен SSL-сертификат, который применяется для проверки подлинности сервера. Проект Let’s Encrypt значительно упростил процесс получения SSL-сертификатов. До его появления всё было гораздо сложнее.

image


Let’s Encrypt использует Certbot от Electronic Frontier Foundation для автоматизации процесса получения SSL-сертификата. Поддерживаются разные типы веб-серверов (Apache, nginx, и другие), которые работают на Unix-подобных ОС. Если ваш сервер соответствует системным требованиям Let’s Encrypt, это значит, что вы сможете получить сертификат в практически полностью автоматическом режиме. К сожалению, связку Node.js/Express.js Let’s Encrypt не поддерживает. То есть, в данном случае автоматически получить сертификат от Certbot не получится. Однако, не всё потеряно. Используя Let’s Encrypt и Certbot, сертификат не так уж и сложно получить вручную.

Предварительные сведения

Мы собираемся использовать Certbot в режиме webroot, запуская его с ключом --webroot. Если в двух словах, то в этом режиме Certbot разместит файл в некоей директории нашего сервера, которая должна быть доступна по протоколу HTTP.

С помощью Express обслуживать директории, содержащие статические файлы, можно, используя функцию express.static().

Если взглянуть на раздел документации Certbot, посвящённый режиму webroot, окажется, что Certbot будет искать на сервере файл по адресу http://<your_server_url>/.well-known/acme-challenge/. Если он может успешно получить по HTTP файл, который был размещён в указанной директории, он создаст для этого сервера SSL-сертификат.
Итак, приступим.

План работ

Для получения сертификата и поддержания его актуальности нам понадобится пройти через пять этапов:

  1. Перенаправить соответствующие порты.
  2. Настроить структуру директорий для статических файлов и организовать её обслуживание с помощью Express.
  3. Установить и запустить Certbot.
  4. Настроить Express на использование HTTPS.
  5. Обновить сертификат Let’s Encrypt через 90 дней.

Ниже опишем эти этапы подробнее, с примерами кода и команд.

Перенаправление портов

Уверен, это ни у кого затруднений не вызовет, но, для полноты изложения, опишу этот шаг.

Для успешного прохождения процесса верификации требуется URL сервера. Certbot будет использовать этот URL для того, чтобы связаться с сервером и получить данные по HTTP. Это означает, что порт 80 на предоставленном URL должен быть доступен из интернета. Не помешает открыть и порт 443, так как это порт HTTPS по умолчанию.

Лично я предпочитаю держать мои Express-сервера на портах, номера которых выше, чем 1024, а затем, используя правила перенаправления, передавать трафик с портов 80 или 443 на сервера. Как результат, мне не нужно давать Express повышенные привилегии, что безопаснее, особенно учитывая то, что веб-сервер будет обрабатывать потенциально опасный трафик.

Для того, чтобы проверить сетевые настройки, можно воспользоваться утилитой curl. Например, если на сервере имеется адрес для тестирования работоспособности системы (что всегда полезно), запрос на этот адрес можно выполнить с помощью curl. Предположим, сервер настроен так:

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

Если обратиться к конечной точке health-check с помощью curl, на то, что всё в порядке, укажет ответ HTTP 200.

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

Когда сеть и сервер готовы к работе, можно переходить к настройке обслуживания статических файлов.

Обслуживание статических файлов

Как сказано выше, адрес, по которому обратится Certbot для проверки сервера — /.well-known/acme-challenge. Express использует функцию express.static() для обслуживания статических файлов по пути, указанному этой функции. Этот путь становится корнем сервера. Часто папка, которая хранит статические данные веб-сайта, называется public или static, и, например, если у вас есть текстовый файл, видный в файловой системе как /static/test-text/mytextfile.txt, обратиться к нему извне можно по адресу http://<your_server_url/test-text/mytextfile.txt. Учитывая это, создадим структуру директорий для нужд Certbot и подключим её в Express.

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

Вышеприведённая команда выполняется из корня проекта, при этом подразумевается, что директория для статических данных имеет имя static.

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

Теперь, после того, как Express настроен на обслуживание правильной папки, проверим работоспособность системы.

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

Если в консоль будет выведен текст «this is a test», значит данный шаг успешно завершён и можно идти дальше – к созданию нового SSL-сертификата.

Certbot

Первый шаг на данном этапе – установка Certbot. Здесь можно найти инструкции по установке. А именно, чтобы их увидеть, в поле I’m using выберите None of the above, затем, в следующем поле, выберите вашу ОС. После этого будет показана команда для установки. Например, для Ubuntu 16.04 (xenial) эта команда выглядит так: sudo apt-get install letsencrypt.

Следующий шаг заключается в том, чтобы сгенерировать сертификат. Как уже было сказано, мы собираемся запустить Certbot в режиме webroot. Для этого понадобится передать ему путь, который будет использован в качестве корня веб-сервера (используя ключ –w), и доменное имя (с помощью ключа –d). В данном случае команда выглядит так:

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

Здесь мы исходим из предположения, что вы находитесь в директории проекта. После успешного выполнения команды, вы увидите соответствующее сообщение и сведения о расположении сгенерированных файлов. Обычно они находятся по адресу /etc/letsencrypt/live/<your_server_url>. О том, что это за файлы, можно узнать из раздела Webroot в руководстве по Certbot. Мы собираемся использовать с нашим Express-сервером файлы fullchain.pem и privkey.pem.

Отлично! Вот он, наш новенький SSL-сертификат. Теперь задействуем его.

Express и HTTPS

Express, сразу после установки, работает лишь по HTTP. Мы можем настроить использование HTTPS в Express, используя модуль Node https. Для того, чтобы это сделать, понадобится два файла – сертификат и секретный ключ. Кстати сказать, берегите от чужих глаз секретный ключ вашего сервера, а доступ к файлу секретного ключа давайте только авторизованным пользователям.

Кроме того, рекомендуется либо скопировать файлы fullchain.pem и privkey.pem в директорию проекта, либо создать символические ссылки на них. Создание символических ссылок упрощает процесс обновления, но что именно выбрать – дело ваше.

Нижеприведённый код основан на предположении о том, что файлы fullchain.pem и privkey.pem находятся в папке sslcert в директории проекта.

// 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);

Кроме того, тут не помешает Helmet.js. Этот пакет помогает защищать Express-сервера, управляя HTTP-заголовками. Он, помимо прочего, добавляет HSTS, убирает заголовок X-Powered-By и устанавливает заголовок X-Frame-Options для защиты от кликджекинга.

Установить его очень просто:

npm install --save helmet

После установки Helmet, его можно задействовать в Express как промежуточный слой обработки данных.

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

Теперь, чтобы окончательно убедиться в том, что всё работает, можно проверить сервер с помощью чего-то вроде SSL Server Test.

Обновление сертификата

Сертификаты Let’s Encrypt действуют 90 дней. Хорошо это или плохо – спорить бессмысленно, особенно учитывая то, что процесс обновления сертификата очень прост. А именно, для обновления сертификата достаточно выполнить команду letsencrypt renew и Certbot выпустит новый сертификат. Рекомендуется автоматизировать этот процесс, используя либо задания cron, либо что-то вроде systemd.

Выводы

В итоге, мы настроили сервер Express на обслуживание статических файлов по специфическому пути, использовали Certbot в режиме webroot для создания сертификата сервера и подключили HTTPS в Express, используя только что созданный сертификат. Хотя автоматический процесс взаимодействия с Certbot нам и не доступен, сделать вручную всё, что надо, не так уж и сложно.

Хочется надеяться, что Certbot, в обозримом будущем, оснастят поддержкой Node.js.

А как вы получаете SSL-сертификаты для Express-серверов? Пользуетесь ли сертификатами от Let’s Encrypt?

Автор: RUVDS.com

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js