Настройка SSL в Nginx

0
5589
Обложка статьи: Настройка SSL в Nginx

Остальную защиту сервера смотрите в hardening Linux, а ограничение доступа к портам в статье про firewall.

Нужен рабочий HTTPS на nginx: сертификат, ключ, TLS 1.2/1.3 и проверка, что 443 отвечает нужным именем. Рейтинг A+ — побочный эффект, не цель.

Что нужно заранее

  • Имя, которое совпадает с сертификатом. Для нескольких имён на одном IP нужен SNI: nginx -V 2>&1 | grep -i sni должно сказать, что SNI включён.
  • Кто выпускает сертификат: Let’s Encrypt, коммерческий УЦ или свой УЦ. Не StartSSL.
  • Консоль или второй вход. Ошибочный reload на единственном 443 без консоли отрежет вас от сайта.

1. Сертификат и ключ

Публичный сайт — обычный путь Let’s Encrypt. На Debian/Ubuntu:

sudo apt update
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d www.example.com

Плагин сам правит server-блок. Если хотите файлы вручную:

sudo certbot certonly --webroot -w /var/www/html -d www.example.com
sudo ls -l /etc/letsencrypt/live/www.example.com/

Ожидание: fullchain.pem и privkey.pem. Ключ — не в git и не world-readable. Документация nginx: сертификат публичный, ключ читает только master-процесс.

Если УЦ дал серверный сертификат и bundle отдельно, склейте в правильном порядке — сначала ваш сертификат, потом цепочка:

cat www.example.com.crt bundle.crt > www.example.com.chained.crt

Обратный порядок nginx не поднимет: в логе будет mismatch ключа и сертификата.

2. Минимальный server

По Configuring HTTPS servers:

server {
    listen 443 ssl;
    server_name www.example.com;
    ssl_certificate     /etc/letsencrypt/live/www.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
}

С 1.27.3 умолчания модуля — TLSv1.2 TLSv1.3 и HIGH:!aNULL:!MD5, если сборка и OpenSSL это умеют. На старых пакетах умолчания шире и могут включать TLS 1.0/1.1 — протоколы лучше прописать явно. Не копируйте из архивных сниппетов nginx.org строки с RC4 и 3DES: это иллюстрация синтаксиса, не рекомендация 2026 года.

Наборы шифров — в Mozilla SSL Configuration Generator; жёсткий nginx — в CIS Benchmarks. Защита канала в NIST SP 800-53 — SC-8 / SC-13, это не замена вашего конфига.

HTTP/2: в nginx 1.25.1+ это отдельная директива http2 on;, в более старых — параметр listen 443 ssl http2. Смотрите man своей сборки, не смешивайте оба синтаксиса.

Два имени на одном IP (официальный приём — SNI, отдельные server):

server {
    listen 443 ssl;
    server_name www.example.com;
    ssl_certificate     /etc/letsencrypt/live/www.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
}
server {
    listen 443 ssl;
    server_name www.example.org;
    ssl_certificate     /etc/letsencrypt/live/www.example.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.example.org/privkey.pem;
}

Без SNI клиент получит сертификат сайта по умолчанию — первого server в конфиге. Сессии между воркерами, если ядер несколько:

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

3. Проверить конфиг и перечитать

sudo nginx -t
sudo systemctl reload nginx

Пример удачного nginx -t:

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

Ключ не читается — обычно SSL_CTX_use_PrivateKey_file и права на privkey.pem. Reload, не restart, если уже есть живой трафик. Не отключайте 80 и 443 одновременно на машине без консоли.

4. Редирект и HSTS

Постоянный 80 → 443 включайте, когда HTTP больше не нужен клиентам и мониторингу.

server {
    listen 80;
    server_name www.example.com;
    return 301 https://$host$request_uri;
}

Снова nginx -t и reload. HSTS (Strict-Transport-Security) — отдельное решение. Пока имя, сертификат или смешанный HTTP не устоялись, длинный max-age не ставьте: у клиентов его сложно «отменить».

Как проверить

ss -lntup | grep -E ':443s'
echo | openssl s_client -connect www.example.com:443 -servername www.example.com 2>/dev/null | openssl x509 -noout -dates -subject
echo | openssl s_client -connect www.example.com:443 -servername www.example.com -tls1_1 2>&1 | head
sudo certbot renew --dry-run

Пример куска openssl x509:

notBefore=Oct  1 00:00:00 2026 GMT
notAfter=Dec 30 00:00:00 2026 GMT
subject=CN = www.example.com

Ожидание: 443 слушает nginx; имя совпадает; срок не истёк. TLS 1.1 при закрытых протоколах обычно заканчивается sslv3 alert handshake failure или no protocols available. renew --dry-run — только если сертификат выпускал certbot. SSL Labs и testssl.sh — дополнительная проверка своих хостов, не приёмка сами по себе.

Откат

Верните предыдущий файл из sites-available, nginx -t, reload. Ключ и сертификат не удаляйте, пока новый вход по HTTPS не подтверждён.

Источники

Комментарии закрыты.