Комментарий пользователя
Здравствуйте! После обновления OpenSSL часть HTTPS-вызовов к внешним сервисам начала падать с ошибкой ssl.SSLError. Подскажите, как правильно настроить Python, чтобы handshake проходил успешно и соединение оставалось безопасным?
Ответ специалиста
Здравствуйте, Максим! После апдейтов OpenSSL часто отключают старые протоколы и слабые шифры — старые сервера не проходят handshake. Решение на клиенте — явно создать ssl.SSLContext, задать минимальную версию TLS и, при необходимости, набор шифров, а затем передать этот контекст в HTTP-клиент (например, httpx).
import ssl
import httpx
ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
ctx.set_ciphers('ECDHE+AESGCM:!ECDSA:!aNULL:!eNULL')
with httpx.Client(verify=ctx, timeout=10.0) as client:
r = client.get('https://api.example.com')
r.raise_for_status()
print(r.status_code)
В коде мы указываем TLSv1_2 как минимальный порог. Это удобно: если сервер уже поддерживает TLS 1.3, все само заработает на самой новой версии. Но если какой-то внешний сервис еще не успел обновиться, соединение не разорвется, и все продолжит работать на стабильном 1.2. Так мы получаем универсальный код, который не сломается при работе со старыми API.
Для отладки TLS handshake применяйте openssl s_client -connect host:443 -tls1_2 чтобы увидеть, какие шифры поддерживает сервер. Временное ослабление minimum_version даст совместимость, но хуже для безопасности — лучше апгрейдить серверную часть. Сертификаты и ключи храните вне кода (секреты/volumes), не логируйте их, и при работе в контейнерах используйте безопасные механизмы передачи секретов.
Надеюсь, этот материал был вам полезен. Мы регулярно делимся подобными наработками. Будем рады видеть вас среди читателей Академии Selectel.