HTTPS — стандарт безопасности для современных сайтов. Google понижает в поиске сайты без HTTPS, браузеры показывают предупреждения «Не защищено», а пользователи доверяют защищённым сайтам больше. В этом руководстве — полная настройка HTTPS-сервера в Nginx: от получения сертификата до оптимизации.

Базовая настройка HTTPS

Для работы HTTPS необходим SSL-сертификат и закрытый ключ. Минимальная конфигурация:

server {
    listen              443 ssl;
    server_name         example.com www.example.com;
    ssl_certificate     /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
}

Параметры

  • listen 443 ssl — слушать порт 443 с SSL
  • ssl_certificate — путь к файлу сертификата (публичный, можно показывать всем)
  • ssl_certificate_key — путь к закрытому ключу (секретный, права доступа 600)
  • ssl_protocols — разрешённые версии TLS (рекомендуется только 1.2 и 1.3)
  • ssl_ciphers — разрешённые шифры

Безопасность закрытого ключа

Закрытый ключ — самый чувствительный файл на сервере. Если его украдут, можно подделать сертификат. Правила:

  • Хранить в отдельном файле с правами 600 (только root/nginx может читать)
  • Никогда не передавать по незащищённым каналам
  • Не хранить в репозитории Git
  • Не включать в резервные копии без шифрования

Редирект с HTTP на HTTPS

Весь трафик должен идти по HTTPS. Настраиваем редирект:

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

Все запросы по HTTP (порт 80) будут автоматически перенаправлены на HTTPS (порт 443).

Получение бесплатного сертификата (Let’s Encrypt)

Let’s Encrypt — бесплатный центр сертификации. Сертификаты действуют 90 дней и автоматически продлеваются.

Установка Certbot

# Ubuntu/Debian
sudo apt update
sudo apt install certbot python3-certbot-nginx

# CentOS/RHEL
sudo yum install certbot python3-certbot-nginx

Получение сертификата

# Автоматическая настройка (certbot изменит конфигурацию Nginx)
sudo certbot --nginx -d example.com -d www.example.com

# Или только получить сертификат (без изменения конфигурации)
sudo certbot certonly --nginx -d example.com -d www.example.com

Автоматическое продление

# Проверить продление
sudo certbot renew --dry-run

# Certbot автоматически ставит cron для продления
# Проверить: cat /etc/cron.d/certbot

Где хранятся сертификаты Let’s Encrypt

  • Сертификат: /etc/letsencrypt/live/example.com/fullchain.pem
  • Закрытый ключ: /etc/letsencrypt/live/example.com/privkey.pem

Оптимизация HTTPS

SSL-операции потребляют ресурсы процессора. Самая дорогая операция — SSL handshake (рукопожатие). Способы оптимизации:

1. Кэширование SSL-сессий

Повторные подключения используют параметры из кэша, пропуская handshake:

ssl_session_cache   shared:SSL:10m;  # 10 МБ ≈ 40 000 сессий
ssl_session_timeout 10m;              # Сессия живёт 10 минут

2. Keepalive соединения

Позволяет обрабатывать несколько запросов в одном соединении:

keepalive_timeout 70;

3. OCSP Stapling

Сервер сам проверяет сертификат и кэширует ответ, ускоряя проверку для клиентов:

ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

4. Современные шифры

Используйте только современные шифры для безопасности и скорости:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;

Полная оптимизированная конфигурация

# Редирект HTTP → HTTPS
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

# HTTPS сервер
server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    # Сертификаты
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Безопасность
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers on;

    # Оптимизация
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;
    keepalive_timeout   70;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # Безопасные заголовки
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options DENY always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Сайт
    root /var/www/example.com;
    index index.html index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

Цепочки сертификатов

Некоторые центры сертификации выдают промежуточные сертификаты. Их нужно объединить с основным:

# Объединяем сертификат и цепочку
cat server.crt intermediate.crt > fullchain.crt

Важен порядок: сначала серверный сертификат, потом промежуточные. Если порядок неправильный, Nginx выдаст ошибку:

SSL_CTX_use_PrivateKey_file(" ... /example.com.key") failed
   (SSL: error:05800074:x509 certificate routines::key values mismatch)

Проверка SSL-конфигурации

Командная строка

# Проверка сертификата
openssl s_client -connect example.com:443

# Проверка цепочки сертификатов
openssl s_client -connect example.com:443 -showcerts

# Проверка срока действия
openssl x509 -enddate -noout -in /etc/ssl/certs/example.com.crt

Онлайн-сервисы

  • SSL Labs (ssllabs.com/ssltest) — полная проверка SSL/TLS
  • SSL Shopper (sslshopper.com) — проверка сертификата
  • Mozilla SSL Configuration Generator — генерация конфигурации

Безопасные заголовки

Добавьте HTTP-заголовки для дополнительной защиты:

# Принудительный HTTPS на год
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# Запрет встраивания в iframe
add_header X-Frame-Options DENY always;

# Запрет MIME-type сниффинга
add_header X-Content-Type-Options nosniff always;

# Защита от XSS
add_header X-XSS-Protection "1; mode=block" always;

# CSP (Content Security Policy)
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" always;

Настройка для WordPress

# Редирект на HTTPS
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

# Основной сервер
server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    root /var/www/example.com;
    index index.php index.html;

    # HSTS
    add_header Strict-Transport-Security "max-age=31536000" always;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 30d;
        add_header Cache-Control "public";
    }

    location ~ /\.ht {
        deny all;
    }
}

После настройки HTTPS в WordPress нужно изменить адреса сайта:

  • Админка → Настройки → Общие → WordPress Address: https://example.com
  • Админка → Настройки → Общие → Site Address: https://example.com

Частые ошибки

Смешанный контент (Mixed Content)

Страница загружена по HTTPS, но ресурсы (картинки, скрипты) — по HTTP. Браузер покажет предупреждение. Решение: заменить все http:// на https:// в коде.

Сертификат не доверенный

Самоподписанные сертификаты не подходят для продакшена. Используйте Let’s Encrypt или коммерческий сертификат.

Срок действия сертификата истёк

# Проверить срок
openssl x509 -enddate -noout -in /etc/letsencrypt/live/example.com/fullchain.pem

# Продлить
sudo certbot renew

Порт 443 занят

# Найти процесс
sudo ss -tlnp | grep :443

# Перезапустить Nginx
sudo systemctl restart nginx

Заключение

HTTPS обязателен для любого современного сайта. С Let’s Encrypt получить бесплатный сертификат можно за 5 минут. Оптимизация SSL (кэширование сессий, OCSP stapling, современные шифры) снижает нагрузку на сервер и ускоряет загрузку.

Читайте также:

Добавить комментарий

Разработка сайтов на Wordpress