Ssl.create default context: примеры (PYTHON)

Использование create_default_context для SSL в Python
Раздел: SSL, Безопасность
ssl.create_default_context(purpose): ssl.SSLContext

Описание функции

Функция ssl.create_default_context является частью стандартного модуля ssl в Python. Она создает объект SSLContext с настройками, которые считаются разумными по умолчанию для клиентских и серверных соединений. Эта функция упрощает создание безопасных соединений, минимизируя необходимость ручной настройки параметров безопасности.

Основное применение функции связано с созданием SSL/TLS-контекста для безопасного обмена данными через сеть, например, для HTTPS-запросов с помощью модуля http.client или для защиты сокетов.

Аргументы функции

  • purpose (по умолчанию ssl.Purpose.SERVER_AUTH): Определяет цель использования контекста. Доступные варианты:
    • ssl.Purpose.SERVER_AUTH – для клиентов, которые подключаются к серверу (проверяет сертификат сервера).
    • ssl.Purpose.CLIENT_AUTH – для серверов, которые требуют аутентификацию клиента (проверяет сертификат клиента).
  • cafile (строка, необязательный): Путь к файлу с одним или несколькими сертификатами CA в формате PEM, которые используются для проверки сертификата пира.
  • capath (строка, необязательный): Путь к директории, содержащей несколько файлов сертификатов CA в формате PEM.
  • cadata (байты или строка ASCII, необязательный): Сертификаты CA в формате PEM в виде байтовой строки или строки ASCII.

Возвращаемое значение

Функция возвращает объект ssl.SSLContext, настроенный с параметрами безопасности по умолчанию для указанной цели. Этот контекст можно использовать для методов wrap_socket, wrap_bio или передавать в другие API, требующие SSL-контекст.

Короткие примеры использования

Создание контекста для клиента с настройками по умолчанию.

import ssl

context = ssl.create_default_context()
print(type(context))
<class 'ssl.SSLContext'>

Создание контекста для сервера, который будет запрашивать сертификат у клиента.

import ssl

server_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
print(server_context.verify_mode)
<VerifyMode.CERT_REQUIRED: 2>

Создание клиентского контекста с использованием пользовательского файла CA.

import ssl

client_context = ssl.create_default_context(cafile='/path/to/custom_ca.pem')
print(client_context.verify_mode)
<VerifyMode.CERT_REQUIRED: 2>

Создание контекста с данными CA, переданными в виде строки.

import ssl

ca_data = '''-----BEGIN CERTIFICATE-----
... (содержимое сертификата CA) ...
-----END CERTIFICATE-----'''
context = ssl.create_default_context(cadata=ca_data)
print(context.cert_store_stats())
{'x509_ca': 1, 'x509': 1}

Похожие функции в Python

В модуле ssl существуют и другие способы создания SSL-контекстов.

  • ssl.SSLContext(protocol): Конструктор для создания пустого контекста с указанием протокола (например, ssl.PROTOCOL_TLS_CLIENT). Требует ручной настройки всех параметров безопасности, таких как проверка сертификатов и выбор шифров. Используется, когда нужен полный контроль над настройками.
  • ssl._create_unverified_context(): Создает контекст, который не проверяет сертификаты хоста. Не рекомендуется для производственного использования из-за соображений безопасности. Может применяться для тестирования или в закрытых сетях.

Функция create_default_context является предпочтительной для большинства сценариев, так как обеспечивает безопасные настройки по умолчанию, соответствующие современным стандартам.

Альтернативы в других языках программирования

PHP

Используется функция stream_context_create с опциями SSL.

$context = stream_context_create([
    'ssl' => [
        'verify_peer' => true,
        'cafile' => '/path/to/ca.pem'
    ]
]);
$result = file_get_contents('https://example.com', false, $context);

JavaScript (Node.js)

Используется модуль tls и функция tls.createSecureContext.

const tls = require('tls');
const context = tls.createSecureContext({
    ca: require('fs').readFileSync('/path/to/ca.pem')
});

Java

Создание SSLContext через SSLContext.getInstance и инициализация с TrustManager.

import javax.net.ssl.*;

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{new X509TrustManager() {
    public void checkClientTrusted(X509Certificate[] chain, String authType) {}
    public void checkServerTrusted(X509Certificate[] chain, String authType) {}
    public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
}}, null);

C#

Используется SslStream с SslClientAuthenticationOptions.

using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

var sslStream = new SslStream(stream, false, (sender, certificate, chain, errors) => true);

Go

Настройка tls.Config в пакете crypto/tls.

import "crypto/tls"

config := &tls.Config{
    RootCAs:    x509.NewCertPool(),
}
// Добавление CA сертификата в пул

Kotlin

На платформе JVM используется SSLContext аналогично Java.

import javax.net.ssl.SSLContext

val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, null, null)

В отличие от Python, где create_default_context предлагает готовые безопасные настройки, во многих языках требуется более подробная ручная конфигурация.

Типичные ошибки

Ошибка при указании несуществующего файла CA.

import ssl

try:
    context = ssl.create_default_context(cafile='/nonexistent.pem')
except Exception as e:
    print(f'Ошибка: {e}')
Ошибка: [Errno 2] No such file or directory

Ошибка при передаче некорректных данных в cadata.

import ssl

try:
    context = ssl.create_default_context(cadata='invalid data')
except Exception as e:
    print(f'Ошибка: {e}')
Ошибка: could not decode the PEM data

Попытка использовать клиентский контекст для серверного сокета без корректной настройки сертификатов.

import ssl, socket

context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Не установлены сертификаты сервера
try:
    wrapped = context.wrap_socket(sock, server_side=True)
except ssl.SSLError as e:
    print(f'Ошибка SSL: {e}')
Ошибка SSL: [SSL: NO_PRIVATE_KEY] no private key (_ssl.c:1007)

Изменения в последних версиях Python

  • В Python 3.10 были обновлены наборы шифров по умолчанию для контекстов, созданных create_default_context, чтобы отключить слабые шифры и повысить безопасность.
  • Начиная с Python 3.7, протоколом по умолчанию для create_default_context стал PROTOCOL_TLS, который выбирает наивысшую версию протокола, поддерживаемую клиентом и сервером.
  • В Python 3.8 было добавлено автоматическое использование системных хранилищ сертификатов CA на Windows и macOS при вызове create_default_context, если не указаны cafile, capath или cadata.

Расширенные примеры использования

Настройка минимальной и максимальной версий TLS в созданном контексте.

Пример python
import ssl

context = ssl.create_default_context()
context.minimum_version = ssl.TLSVersion.TLSv1_2
context.maximum_version = ssl.TLSVersion.TLSv1_3
print(f'Минимум: {context.minimum_version}, Максимум: {context.maximum_version}')
Минимум: <TLSVersion.TLSv1_2: 769>, Максимум: <TLSVersion.TLSv1_3: 772>

Использование контекста с asyncio для безопасного соединения.

Пример python
import asyncio, ssl

async def tls_client():
    context = ssl.create_default_context()
    reader, writer = await asyncio.open_connection('example.com', 443, ssl=context)
    writer.write(b'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n')
    await writer.drain()
    data = await reader.read(100)
    print(data[:50])
    writer.close()

asyncio.run(tls_client())
b'HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n'

Отключение проверки сертификата для целей тестирования (небезопасно).

Пример python
import ssl, urllib.request

context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE

req = urllib.request.Request('https://example.com')
response = urllib.request.urlopen(req, context=context)
print(response.status)
200

Настройка контекста для взаимной аутентификации (mTLS), где клиент также представляет сертификат.

Пример python
import ssl

client_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
client_context.load_cert_chain(certfile='client.crt', keyfile='client.key')
# Теперь контекст можно использовать для соединения с сервером, который требует сертификат клиента

Использование с конкретным набором шифров.

Пример python
import ssl

context = ssl.create_default_context()
context.set_ciphers('ECDHE+AESGCM:ECDHE+CHACHA20')
print(context.get_ciphers()[0]['name'])
'ECDHE-ECDSA-AES256-GCM-SHA384'

Создание контекста для сервера с загрузкой сертификатов и настройкой параметров.

Пример python
import ssl, socket

server_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
server_context.load_cert_chain(certfile='server.crt', keyfile='server.key')
server_context.verify_mode = ssl.CERT_OPTIONAL  # Проверять клиентский сертификат, если он представлен

sock = socket.socket()
sock.bind(('localhost', 8443))
sock.listen()
# Далее accept и wrap_socket с server_side=True

питон ssl.create_default_context function comments

En
Ssl.create default context Create SSL context