let's Encrypt і Express. Кожному серверу – по зеленому замку

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?
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.