Ошибка SSL handshake в Nginx: почему сайт зависает при первом заходе
Вы столкнулись с ситуацией, когда сайт на Django, работающий через HTTPS, зависает на минуту при первом обращении из нового браузера, а затем работает стабильно. При этом HTTP-версия грузится мгновенно. В логах Nginx появляется ошибка SSL: error:0A00006C:SSL routines::bad key share. Это типичная проблема конфигурации SSL/TLS, связанная с несовместимостью параметров шифрования. В этой статье мы подробно разберём причины и предложим пошаговое решение.
Почему возникает ошибка bad key share в Nginx
Ошибка bad key share появляется при попытке установить TLS-соединение, когда клиент и сервер не могут согласовать параметры протокола Key Exchange (обмена ключами). Это часто случается при использовании современных версий OpenSSL (3.x) с устаревшими или неправильно настроенными директивами ssl_ciphers и ssl_protocols. В вашем конфиге явно не заданы протоколы и шифры, поэтому Nginx использует значения по умолчанию, которые могут не поддерживаться некоторыми браузерами (например, новыми версиями Chrome или Firefox).
Как исправить ошибку SSL handshake в Nginx
Шаг 1. Добавьте явные настройки протоколов и шифров
Откройте файл конфигурации Nginx и в блок server для HTTPS добавьте следующие строки:
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;Эти настройки ограничивают использование только безопасных протоколов TLS 1.2 и 1.3, исключая устаревшие TLS 1.0 и 1.1, которые могут вызывать конфликты. Список шифров гарантирует поддержку современных алгоритмов.
Шаг 2. Убедитесь, что директива ssl_dhparam указана корректно
В вашем конфиге уже есть ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;, но проверьте, существует ли этот файл и не повреждён ли он. Сгенерируйте новый, если необходимо:
sudo openssl dhparam -out /etc/letsencrypt/ssl-dhparams.pem 2048После этого перезагрузите Nginx: sudo systemctl reload nginx.
Шаг 3. Проверьте настройки uWSGI и Gunicorn
Хотя вы пробовали менять сервер приложений, убедитесь, что в конфигурации uWSGI или Gunicorn не заданы параметры, конфликтующие с SSL. Например, в uWSGI проверьте, что опция buffer-size достаточно велика (рекомендуется 32768), а http-timeout не слишком мал. Для Gunicorn проверьте настройки worker_connections и keepalive.
Шаг 4. Добавьте кэширование SSL-сессий
Чтобы ускорить повторные подключения, включите кэширование сессий:
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;Это позволит браузеру при повторном заходе не выполнять полный handshake, а использовать сохранённые параметры.
Почему сайт зависает только при первом заходе
Когда браузер впервые подключается к серверу по HTTPS, происходит полный TLS-handshake, включающий согласование версии протокола, шифров и обмен ключами. Если сервер предлагает неподдерживаемые параметры, браузер может зависнуть в ожидании ответа. После успешного первого соединения браузер кэширует сессию, и последующие запросы выполняются быстрее. Отключение HTTPS решает проблему, так как HTTP не требует такого согласования.
Дополнительные рекомендации
- Обновите OpenSSL до последней стабильной версии (3.0.x или 1.1.1w).
- Проверьте сертификат - убедитесь, что цепочка сертификатов полная (fullchain.pem).
- Используйте онлайн-тестеры (например, SSL Labs) для анализа конфигурации.
- Перезапустите сервисы после изменений:
sudo systemctl restart nginxиsudo systemctl restart your-django-app.
Следуя этим шагам, вы устраните ошибку bad key share и обеспечите стабильную работу сайта при первом заходе с любого браузера.