Защита Nginx с помощью HTTPS: пошаговое руководство

Узнайте, как защитить ваш веб-сервер Nginx с помощью HTTPS, в этом подробном пошаговом руководстве. Мы рассмотрим получение бесплатных SSL/TLS-сертификатов от Let's Encrypt с использованием Certbot, настройку Nginx для зашифрованных соединений и внедрение важных мер безопасности, таких как HSTS. Защитите свои данные, завоюйте доверие пользователей и улучшите SEO с помощью правильно настроенного HTTPS.

Защита Nginx с помощью HTTPS: пошаговое руководство

Защита Nginx с помощью HTTPS обычно является небольшой задачей, но это одна из тех задач, где мелкие ошибки имеют громкие последствия. Отсутствующий файл сертификата не позволяет Nginx перезагрузиться. Забытое правило брандмауэра делает сайт недоступным. Поспешный заголовок HSTS может заблокировать пользователей в неработающей HTTPS-настройке дольше, чем вы планировали.

Хорошая новость в том, что стандартный путь прост. Вы направляете DNS на сервер, убеждаетесь, что Nginx отвечает на порту 80, используете Certbot для запроса сертификата Let's Encrypt, тестируете сгенерированную конфигурацию Nginx, перезагружаете, а затем проверяете обновление. Именно этому пути следует данное руководство.

Я буду использовать example.com и www.example.com ниже. Замените их на ваши реальные имена и не пропускайте проверки перед перезагрузкой Nginx.

Перед запросом сертификата

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

Проверьте DNS извне сервера:

dig +short example.com
dig +short www.example.com

Оба имени должны разрешаться в публичный адрес, который достигает вашего хоста Nginx или балансировщика нагрузки.

Убедитесь, что порты 80 и 443 открыты на каждом уровне: группа безопасности облака, брандмауэр хоста, сетевой брандмауэр и любой балансировщик нагрузки перед хостом.

sudo ss -tulnp | grep nginx
sudo ufw status

На облачной виртуальной машине также проверьте консоль провайдера. Я много раз видел, как чистые конфиги Nginx не работали, потому что брандмауэр экземпляра разрешал 443, но группа безопасности облака все еще блокировала его.

Наконец, подтвердите, что Nginx уже обслуживает домен по обычному HTTP:

curl -I http://example.com
curl -I http://www.example.com

Ответ не обязательно должен быть красивым. Это может быть страница-заполнитель. Главное, чтобы он доказывал, что запросы к этому имени хоста достигают этого сервера Nginx.

Установка Certbot

Для Debian/Ubuntu:

sudo apt update
sudo apt install certbot python3-certbot-nginx

Для систем, совместимых с RHEL:

sudo dnf install certbot python3-certbot-nginx

Старые системы CentOS могут использовать yum и могут потребовать предварительного включения EPEL. Имена пакетов также различаются в зависимости от версии дистрибутива, поэтому используйте документацию по пакетам вашего дистрибутива, если эти команды не находят плагин.

Запрос сертификата

Плагин Nginx может запросить сертификат и отредактировать соответствующий серверный блок:

sudo certbot --nginx -d example.com -d www.example.com

Certbot запросит адрес электронной почты, согласие с условиями, а иногда и перенаправление HTTP на HTTPS. Для обычного публичного веб-сайта выберите перенаправление. Для API или внутреннего сервиса сначала проверьте клиентов. Некоторые старые клиенты или проверки работоспособности могут все еще вызывать http:// и ожидать определенного ответа.

Если Certbot сообщает, что не может найти соответствующий серверный блок, проверьте server_name. Блок, подобный этому, дает Certbot четкую основу для работы:

server {
    listen 80;
    server_name example.com www.example.com;

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

    location / {
        try_files $uri $uri/ =404;
    }
}

Выполните проверку синтаксиса перед тем, как просить Certbot что-либо редактировать:

sudo nginx -t

Если текущая конфигурация уже сломана, сначала исправьте ее.

Как должна выглядеть конфигурация Nginx

После успешного запуска вы обычно увидите один HTTP-блок, который перенаправляет, и один HTTPS-блок, который обслуживает сайт:

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

server {
    listen 443 ssl;
    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;

    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

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

    location / {
        try_files $uri $uri/ =404;
    }
}

Не копируйте это вслепую в рабочую конфигурацию. Сохраните существующие правила location, настройки прокси, журналы и ограничения на загрузку. Важными частями являются listen 443 ssl, пути к сертификатам и поведение перенаправления на порту 80.

Тестирование, перезагрузка и проверка

Всегда тестируйте перед перезагрузкой:

sudo nginx -t

Затем перезагрузите:

sudo systemctl reload nginx

Проверьте из командной строки:

curl -I http://example.com
curl -I https://example.com
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates

HTTP-запрос должен перенаправляться, если вы выбрали этот вариант. HTTPS-запрос должен возвращать ожидаемый статус. Команда openssl должна показывать сертификат, чей субъект или альтернативные имена субъекта охватывают домен, а даты актуальны.

Тестирование в браузере все еще важно. Откройте сайт в приватном окне и щелкните значок замка, чтобы проверить сертификат. Если ваш сайт загружает ресурсы со старых URL http://, страница может показывать предупреждения о смешанном содержимом, даже если основной сертификат в порядке. Исправьте эти URL ресурсов в приложении, CMS или слое шаблонов.

Обновление

Сертификаты Let's Encrypt имеют короткий срок действия, поэтому обновление должно работать без вашего запоминания. Certbot обычно устанавливает системный таймер или задание cron. Проверьте это:

systemctl list-timers | grep certbot
sudo certbot renew --dry-run

Пробный запуск — это полезная часть. Он выполняет симуляцию обновления и выявляет распространенные проблемы, такие как сломанная HTTP-проверка, изменения DNS, отсутствующие плагины или конфигурация, которая не может перезагрузиться.

Если вы завершаете TLS на балансировщике нагрузки или CDN, а не непосредственно на хосте Nginx, обновление может потребовать DNS-вызова или другого пути развертывания. Не предполагайте, что HTTP-вызов по умолчанию сработает, если публичный трафик никогда не достигает этого сервера.

Настройки TLS, которые стоит проверить

Для большинства современных публичных сайтов TLS 1.2 и TLS 1.3 являются практическим базовым уровнем:

ssl_protocols TLSv1.2 TLSv1.3;

Избегайте ручной настройки списков шифров, если вы не знаете зачем. Включенный options-ssl-nginx.conf от Certbot и генератор конфигурации SSL от Mozilla являются лучшими отправными точками, чем скопированная строка шифров из старого поста в блоге. Рекомендации по шифрам со временем меняются, и требования к совместимости различаются между публичным маркетинговым сайтом и внутренним устаревшим API.

HSTS полезен, но требует осторожности:

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

Начните с короткого значения во время тестирования:

add_header Strict-Transport-Security "max-age=300" always;

Используйте includeSubDomains только тогда, когда каждый поддомен может обслуживать действительный HTTPS. Если old.example.com, mail.example.com или поддомен, специфичный для клиента, не готов, этот параметр может сломать реальных пользователей.

Распространенные сбои

Если Certbot не может проверить домен, сначала проверьте DNS, затем порт 80, затем серверный блок Nginx. HTTP-01 вызов требует, чтобы Let's Encrypt достиг токена по адресу /.well-known/acme-challenge/. Перенаправления работают нормально при правильной настройке, но прокси, CDN или блок catch-all могут случайно отправить вызов в другое место.

Если Nginx не перезагружается после изменений Certbot, выполните:

sudo nginx -t
sudo journalctl -u nginx -n 80 --no-pager

Проверка синтаксиса обычно указывает точный файл и строку. Распространенные причины — дублирующиеся блоки listen 443 ssl, удаленный путь к сертификату или включенный фрагмент из пути, который не существует на этом сервере.

Если HTTPS работает локально, но не для пользователей, проверьте публичный путь. Балансировщик нагрузки может все еще указывать на старую целевую группу. CDN мог кэшировать перенаправление. IPv6 DNS может указывать на другой хост, чем IPv4. Проверьте оба:

curl -4 -I https://example.com
curl -6 -I https://example.com

Самая чистая настройка HTTPS скучна: DNS указывает в правильное место, Nginx имеет один очевидный серверный блок для домена, обновление Certbot проходит в пробном запуске, а заголовки добавляются только после того, как основы заработают.