Сообщение об ошибке
[SSL: DH_KEY_TOO_SMALL] dh key too small
Далее следует место в исходном коде, например «(_ssl.c:1082)». curl и другие клиенты на OpenSSL выводят ту же причину как «dh key too small».
Python ssl module (OpenSSL, security level 2) — ssl.SSLError, SSL_R_DH_KEY_TOO_SMALL
Что это означает
Сервер выбрал обмен ключами Диффи — Хеллмана в конечном поле (DHE) с группой меньше, чем допускает клиент, обычно 1024 бита. Python 3.10 и новее используют в OpenSSL уровень безопасности 2, который требует DH длиной не менее 2048 бит, поэтому клиент прерывает рукопожатие. Сертификат сервера здесь ни при чём.
Почему это происходит
Сервер использует 1024-битную группу DH
частоСтарые релизы Apache httpd (до 2.4.7 они использовали фиксированные 1024-битные параметры), старые серверы на Java и конфигурации, которые до сих пор загружают файл dhparam, сгенерированный много лет назад. Исследование Logjam (2015) показало, что 1024-битный DH по силам злоумышленникам с хорошим финансированием.
Более строгий уровень безопасности по умолчанию в Python
частоВ Python 3.10 уровень безопасности OpenSSL по умолчанию повышен до 2. Код, который без проблем подключался на Python 3.9, после обновления может выдавать ошибку, хотя сервер не менялся.
Встраиваемые и специализированные устройства
иногдаИнтерфейсы управления принтеров, офисных АТС и промышленного оборудования часто предлагают только DHE с маленькими группами.
Как исправить
- 1.
Проверьте размер параметров обмена ключами
Подключитесь один раз через openssl s_client на уровне безопасности 1 и посмотрите строку «Server Temp Key».
bash # "Server Temp Key: DH, 1024 bits" confirms the weak group openssl s_client -connect legacy.example.com:443 -servername legacy.example.com \ -cipher 'DEFAULT:@SECLEVEL=1' </dev/null 2>/dev/null | grep 'Server Temp Key' - 2.
Владельцам серверов: используйте ECDHE или 2048-битную группу
Отдавайте предпочтение наборам шифров с ECDHE (и TLS 1.3); если DHE необходим, настройте группу из RFC 7919 размером не менее 2048 бит.
text # nginx: prefer ECDHE; if DHE must stay, use a 2048-bit (or larger) group ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_dhparam /etc/nginx/ffdhe2048.pem; # RFC 7919 group - 3.
Временное решение: понизьте уровень безопасности для одного хоста
Строка «DEFAULT:@SECLEVEL=1» в отдельном контексте разрешает 1024-битный DH только для этого хоста. Не задавайте её в общих контекстах и контекстах по умолчанию: она разрешает и другие слабые параметры.
python # Temporary workaround for one legacy host: security level 1 accepts 1024-bit DH import ssl, urllib.request ctx = ssl.create_default_context() ctx.set_ciphers("DEFAULT:@SECLEVEL=1") urllib.request.urlopen("https://legacy.example.com/", context=ctx)
Связанные ошибки
[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] ssl/tls alert handshake failurePython ssl module (OpenSSL)[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabledPython ssl module (OpenSSL 3)curl: (35) TLS connect error: error:0A000410:SSL routines::ssl/tls alert handsh…curl (OpenSSL backend)