Чтобы создать безопасный сервер со связкой NGINX+NodeJS, а также, чтобы была возможность использовать http2 протокол передачи данных, необходимо выполнить следующее:
Файлы сертификатов для NodeJS и NGINX должны быть идентичны и могут находится в одной и той же папке.
PATH далее - это полный путь от корня к папке, где лежат файлы необходимого сайта, к примеру
/var/www/example.com/
Как получить сертификат смотрите в этой статье.
1. Создайте TLS сертификат.
На сайте https://www.sslforfree.com необходимо создать соответствующие сертификаты по инструкции, которая там указана, либо получить сертификат как-то иначе.
Далее Вам необходимо из файла ca_bundle.crt
скопировать его содержимое в файл certificate.crt
, чтобы получилось так:
2. Создайте dhparam.pem
При этом файлы certificate.crt
и private.key
должны находиться в той же директории (например: /etc/nodejs/ctr/
), куда Вы указываете создание dhparam.pem
(взять эти файлы нужно в скачанном архиве с сайта sslforfree.com).
openssl dhparam -out /PATH/dhparam.pem 4096
После длительного ожидания, выполните следующие пункты...
3. Запустите nodejs скрипт (сохраните файл в директории 'example.com' > [с именем, к примеру] = server.js)
const https = require('https')
const fs = require('fs')
const hostname = 'example.com'
const options = {
key: fs.readFileSync('/PATH/private.key'),
cert: fs.readFileSync('/PATH/certificate.crt'),
dhparam: fs.readFileSync("/PATH/dhparam.pem"),
hostname
}
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(5000)
Команда для запуска nodejs скрипта:
node /PATH/server.js
4. Создайте NGINX конфигурацию:
server {
server_name example.com;
rewrite ^(.*) https://example.com$1 permanent;
}
server {
listen 80;
# redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
return 301 https://$host$request_uri;
}
server{
if ($http_host != "example.com") {
rewrite ^ https://example.com$request_uri permanent;
}
server_name_in_redirect off;
expires $expires;
if ($request_method !~ ^(GET|HEAD|POST)$ ){return 444;}
server_tokens off;
listen 443 ssl http2;
ssl_certificate /PATH/certificate.crt;
ssl_certificate_key /PATH/private.key;
ssl_dhparam /PATH/dhparam.pem;
server_name example.com;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
http2_push_preload on;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK;
#add_header Strict-Transport-Security max-age=15768000;
ssl_stapling on;
ssl_stapling_verify on;
root /PATH/example.com;
charset utf8;
location ~ \.(eot|ttf|otf|woff|woff2)$ {
add_header Access-Control-Allow-Origin *;
access_log off;
expires 365d;
}
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|pdf|ppt|txt|docx|doc|rtf|js|ttf|otf|woff2|eot|svg|woff)$ {
access_log off;
expires 365d;
}
location ~* ^.+\.(jpg|txt|docx|doc|js)$ {
valid_referers none blocked
example.com www.example.com;
if ($invalid_referer) {
rewrite ^/ https://example.com/errorvps?rq=$request&rf=$http_referer&st=$status;
}
}
location ~ \.mp4${
valid_referers none blocked
example.com www.example.com;
if ($invalid_referer) {
rewrite ^/ https://example.com/sys/errorvps?rq=$request&rf=$http_referer&st=$status;
}
mp4;
if ($request_filename ~* ^.*?/([^/]*?)$){
set $filename $1;
add_header Content-Disposition "attachment; filename=$filename";
}
}
location ~ \.flv${
valid_referers none blocked
example.com www.example.com;
if ($invalid_referer) {
rewrite ^/ https://example.com/sys/errorvps?rq=$request&rf=$http_referer&st=$status;
}
flv;
}
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass https://example.com:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
location @missing {
rewrite ^ $scheme://$host/ permanent;
}
error_page 404 /?rq=$request&rf=$http_referer&st=$status;
error_page 403 /?rq=$request&rf=$http_referer&st=$status;
error_page 405 /?rq=$request&rf=$http_referer&st=$status;
error_page 415 /?rq=$request&rf=$http_referer&st=$status;
error_page 401 /?rq=$request&rf=$http_referer&st=$status;
error_page 402 /?rq=$request&rf=$http_referer&st=$status;
error_page 500 /?rq=$request&rf=$http_referer&st=$status;
}
##SERVER
5. Перезапустите nginx:
sudo service nginx reload
6. Попробуйте открыть example.com в своем браузере.
https://example.com
Проверка http2
echo | openssl s_client -alpn h2 -connect example.com:443 | grep ALPN
Ответ
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = example.com
verify return:1
DONE
ALPN protocol: h2
Проверить http2 онлайн: https://tools.keycdn.com/http2-test
Посмотреть, что поддерживает Ваш сервер по TLS: https://www.ssllabs.com/ssltest/index.html