DevOps

Как исправить зависание сайта при первом доступе через HTTPS

Решение проблемы зависания Django-сайта при первом доступе через HTTPS. Устранение ошибки SSL handshake 'bad key share' в Nginx.

3 ответа 3 просмотра

Сайт висит при первом заходе на него. Как исправить проблему с зависанием сайта при первом доступе? У меня сайт на Django с Nginx, который виснет более минуты при первом заходе с новых браузеров, но работает нормально после первого доступа. При отключении HTTPS сайт загружается без проблем. В логах Nginx появляется ошибка: SSL_do_handshake() failed (SSL: error:0A00006C:SSL routines::bad key share). Уже пробовал отключать JavaScript, заменять Gunicorn на uWSGI и менять сертификат - ничего не помогло. В чем может быть причина и как это исправить?

Проблема с зависанием вашего Django-сайта при первом доступе через HTTPS, связанная с ошибкой tls handshake “SSL_do_handshake() failed (SSL: error:0A00006C:SSL routines::bad key share)”, является распространенной проблемой конфигурации SSL/TLS. Эта ssl handshake error возникает из-за несовместимости параметров TLS между браузером клиента и вашим сервером Nginx, но после первого успешного соединения сайт работает нормально благодаря кэшированию SSL-сессий.


Содержание


Анализ проблемы SSL handshake при первом доступе к сайту

Проблема, с которой вы столкнулись, характерна для конфигураций с использованием HTTPS и связана с процессом tls handshake. Когда сайт виснет при первом доступе через HTTPS, но работает нормально после первого обращения и без HTTPS, это указывает на специфическую проблему с установлением защищенного соединения.

Ошибка SSL_do_handshake() failed с сообщением “SSL: error:0A00006C:SSL routines::bad key share” в логах Nginx является ключевым указанием на то, что происходит сбой во время согласования параметров TLS между браузером клиента и вашим сервером. Эта ошибка обычно проявляется при первом обращении с нового устройства или браузера, но исчезает после успешного соединения, так как происходит кэширование SSL-сессии.

Интересно, что вы уже предприняли несколько шагов для устранения проблемы - отключение JavaScript, замена Gunicorn на uWSGI и замена сертификата. Это показывает, что проблема находится на более глубоком уровне взаимодействия между клиентом и сервером в процессе tls handshake.

Причины ошибки “bad key share” в Nginx

Ошибка “bad key share” в Nginx указывает на проблему с согласованием параметров ключевого обмена (key exchange) в процессе TLS handshake. Эта ошибка может возникать по нескольким причинам:

  1. Несовместимость версий TLS: Ваш сервер Nginx может использовать параметры TLS, не поддерживаемые некоторыми браузерами или версиями ОС клиентов. Например, старые браузеры или мобильные устройства могут не поддерживать современные версии TLS (1.3) или определенные параметры шифрования.

  2. Проблемы с алгоритмами подписи: Ошибка “tls_choose_sigalg:internal error”, которую вы могли наблюдать в логах, указывает на внутреннюю ошибку выбора алгоритма подписи. Это может быть связано с настройками SSL-сертификата или конфигурацией Nginx.

  3. Кэширование SSL-сессий: После первого успешного соединения устанавливается кэш SSL-сессии, который позволяет последующим соединениям устанавливаться быстрее. Именно поэтому сайт работает нормально после первого доступа.

  4. Конфигурация SSL-параметров в Nginx: Неправильная настройка ssl_protocols, ssl_ciphers или других SSL-параметров может вызывать проблемы с tls handshake.

  5. Конфликт между клиентом и сервером: Некоторые браузеры или клиенты могут отправлять запросы, которые не обрабатываются корректно вашей конфигурацией Nginx.

Конфигурация Nginx для решения проблем с SSL handshake

Для решения проблемы tls handshake и ошибки “bad key share” в Nginx необходимо оптимизировать SSL-конфигурацию. Вот ключевые параметры, которые следует проверить и, возможно, изменить:

1. Настройка SSL-протоколов

Отредактируйте вашу конфигурацию Nginx, явно указав поддерживаемые протоколы TLS:

nginx
ssl_protocols TLSv1.2 TLSv1.3;

Это отключит устаревшие протоколы TLS 1.0 и 1.1, которые могут вызывать проблемы с tls handshake, но при этом оставит современные и безопасные версии.

2. Настройка SSL-шифров

Оптимизируйте список шифров для обеспечения совместимости:

nginx
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384';
ssl_prefer_server_ciphers off;

Эта конфигурация фокусируется на современных и безопасных шифрах, но исключает потенциально проблемные.

3. Включение и настройка кэширования SSL-сессий

Улучшите производительность tls handshake, настроив кэширование сессий:

nginx
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;

Это позволит быстрее устанавливать последующие соединения, используя ранее согласованную сессию.

4. Оптимизация таймаутов

Увеличьте таймауты для tls handshake, чтобы дать больше времени для установления соединения:

nginx
proxy_connect_timeout 60s;
proxy_read_timeout 60s;

5. Отладка SSL-соединений

Для диагностики проблем с tls handshake включите отладочный режим SSL в Nginx:

nginx
ssl_debug on;

Это создаст подробные логи для анализа tls handshake, но может замедлить производительность, поэтому используйте только для диагностики.

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

bash
sudo nginx -t
sudo systemctl restart nginx

Проверьте логи Nginx на предмет ошибок tls handshake после перезапуска.

Оптимизация Django и Gunicorn/uWSGI для HTTPS

Проблема с tls handshake может быть связана не только с Nginx, но и с настройкой бэкенда Django. Вот несколько аспектов, которые стоит оптимизировать:

1. Настройка Gunicorn/uWSGI для HTTPS

Убедитесь, что ваше приложение Django правильно обрабатывает HTTPS-запросы. Если вы используете Gunicorn, проверьте его конфигурацию:

bash
gunicorn --workers 3 --bind 0.0.0.0:8000 --timeout 120 yourproject.wsgi:application

Обратите внимание на параметр --timeout - увеличьте его значение, чтобы избежать таймаутов при tls handshake.

2. Настройка Django для HTTPS

В файле settings.py вашего Django-проекта убедитесь, что правильно настроены параметры для HTTPS:

python
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_SSL_REDIRECT = True

Эти параметры помогут Django правильно обрабатывать HTTPS-запросы, передаваемые через Nginx.

3. Оптимизация статических файлов

Проблема с tls handshake может усугубляться медленной загрузкой статических файлов. Убедитесь, что Nginx правильно обрабатывает статические файлы:

nginx
location /static/ {
 alias /path/to/your/static/;
 expires 30d;
 add_header Cache-Control "public, no-transform";
}

4. Настройка заголовков безопасности

Правильно настроенные заголовки безопасности могут улучшить производительность tls handshake:

nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

5. Мониторинг производительности

Используйте инструменты для мониторинга tls handshake и общей производительности:

bash
# Проверка tls handshake с помощью curl
curl -v --tlsv1.2 --tlsauthtype SRP https://yourdomain.com

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

Эти команды помогут диагностировать проблемы с tls handshake и проверить состояние SSL-соединения.

Практические шаги по устранению зависания сайта

Для решения проблемы зависания Django-сайта при первом доступе через HTTPS с ошибкой “bad key share” в tls handshake, выполните следующие шаги:

1. Диагностика текущей конфигурации

Начните с анализа текущей конфигурации Nginx:

bash
sudo nginx -t
sudo nginx -V

Проверьте, какие SSL-параметры и версии TLS используются.

2. Тестирование tls handshake

Используйте инструменты для тестирования tls handshake:

bash
# Проверка с помощью openssl
openssl s_client -connect localhost:443 -tls1_2

# Проверка с помощью curl
curl -v --tlsv1.2 https://yourdomain.com

Эти команды помогут определить, есть ли проблемы с tls handshake.

3. Обновление SSL-сертификата

Если вы еще не использовали Let’s Encrypt, получите свежий сертификат:

bash
sudo certbot certonly --nginx -d yourdomain.com

Проверьте, что сертификат поддерживает современные алгоритмы подписи.

4. Оптимизация конфигурации Nginx

Создайте оптимизированную конфигурацию SSL для Nginx:

nginx
server {
 listen 443 ssl http2;
 server_name yourdomain.com;

 ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/yourdomain.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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384';
 ssl_prefer_server_ciphers off;
 
 ssl_session_cache shared:SSL:10m;
 ssl_session_timeout 1d;
 ssl_session_tickets off;

 proxy_connect_timeout 60s;
 proxy_read_timeout 60s;
 proxy_send_timeout 60s;

 location / {
 proxy_pass http://localhost:8000;
 proxy_set_header Host $host;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Forwarded-Proto $scheme;
 }
}

5. Проверка совместимости браузеров

Проверьте, как сайт работает в разных браузерах и на разных устройствах. Используйте браузерные инструменты разработчика для анализа tls handshake.

6. Мониторинг после изменений

После внесения изменений внимательно следите за логами Nginx:

bash
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.log

Проверьте, исчезли ли ошибки tls handshake.

7. Создание резервной копии

Перед внесением значительных изменений в конфигурацию всегда создавайте резервные копии:

bash
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
sudo cp -r /etc/nginx/sites-available/ /etc/nginx/sites-available.bak/

8. Финальная проверка

После всех изменений выполните финальную проверку:

bash
# Проверка tls handshake с разных браузеров
# Проверка производительности сайта
# Проверка логов на наличие ошибок

Если проблема сохраняется, рассмотр возможность использования профессионального аудита SSL-конфигурации или консультации с специалистом по безопасности.


Источники

  1. Stack Overflow SSL Handshake Analysis — Разбор ошибки SSL_do_handshake() failed и причины bad key share: https://stackoverflow.com/questions/79327547/nginx-apache-ssl-errors-ssl-do-handshake-failed-and-modsecurity-access-den

  2. OpenSSL SSL_do_handshake Documentation — Официальная документация по функции SSL_do_handshake и работе с SSL/TLS сессиями: https://www.openssl.org/docs/manmaster/man3/SSL_do_handshake.html

  3. Nginx SSL Configuration Guide — Руководство по настройке SSL в Nginx для оптимизации tls handshake: https://nginx.org/en/docs/http/ngx_http_ssl_module.html

  4. Django HTTPS Configuration — Официальная документация Django по настройке HTTPS и проксированию: https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/#https

  5. Let’s Encrypt SSL Certificate Setup — Инструкция по получению и настройке SSL-сертификатов от Let’s Encrypt: https://certbot.eff.org/docs/using.html#nginx


Заключение

Проблема зависания Django-сайта при первом доступе через HTTPS с ошибкой “bad key share” в tls handshake обычно связана с конфигурацией Nginx или совместимостью TLS между клиентом и сервером. Ключевые решения включают оптимизацию SSL-параметров Nginx, настройку кэширования сессий и правильную конфигурацию Django для работы с HTTPS.

В большинстве случаев проблема решается путем явного указания поддерживаемых версий TLS (TLSv1.2 и TLSv1.3), оптимизации списка шифров и включения кэширования SSL-сессий. После первого успешного соединения сайт работает нормально из-за кэширования, что объясняет, почему проблема проявляется только при первом доступе.

Если предложенные решения не помогли, стоит глубже исследовать логи, проверить совместимость с конкретными браузерами или устройствами пользователей и, возможно, обратиться к профессиональному аудиту SSL-конфигурации.

E

Ошибка SSL_do_handshake() failed с кодом SSL: error:0A00006C:SSL routines::bad key share указывает на проблему с TLS handshake в Nginx. Эта ошибка обычно связана с несовместимостью версий TLS или проблемами с ключевыми обменами между клиентом и сервером. Периодические SSL handshake ошибки могут быть вызваны старыми или сломанными клиентами, которые не поддерживают современные TLS параметры. Ошибка tls_choose_sigalg:internal error указывает на внутреннюю ошибку выбора алгоритма подписи во время TLS handshake.

SSL_do_handshake() будет ожидать завершения SSL/TLS рукопожатия. Если базовый BIO является blocking, SSL_do_handshake() вернется только после завершения рукопожатия или возникновения ошибки. Для nonblocking BIO ошибки SSL_do_handshake() возвращают SSL_ERROR_WANT_READ или SSL_ERROR_WANT_WRITE, что требует повторного вызова после соответствующих действий. Первоначальная медленная загрузка сайта при первом доступе через HTTPS может быть связана с кэшированием сессий SSL, которое устанавливается после первого успешного соединения.

Авторы
E
Пользователь Stack Overflow
S
IT-Специалист
A
Пользователь Stack Overflow
Источники
Stack Overflow / Платформа вопросов и ответов
Платформа вопросов и ответов
Портал документации
Проверено модерацией
НейроОтветы
Модерация
Как исправить зависание сайта при первом доступе через HTTPS