Предисловие

От скуки я решил глубже разобраться в криптографии и посмотреть, какие изменения нас ожидают в ближайшем будущем. С первых же поисковых запросов стало ясно, что идёт активная стандартизация пост-квантового шифрования (далее — PQ). Так появилась идея реализовать собственный прокси-сервер с нативной поддержкой PQ-TLS.

Идея и проблематика

На рынке практически отсутствуют готовые прокси или шлюзы с «из коробки» поддержкой PQ. Некоторые решения предлагают отдельные модули, но они расположены не в main-ветках, а детальных инструкций по установке и настройке нет.


Поэтому я сформулировал типовую задачу:

«У меня есть back-end-сервис, работающий по TLS 1.2/1.3. Мне нужно подключиться к сервису, использующему PQ-TLS, но у меня нет времени и ресурсов мигрировать код. Требуется рабочее решение прямо сейчас».

Отсюда требования:

  1. Быстрое развёртывание.

  2. Поддержка всех доступных PQ-KEM.

  3. Производительность > 600 RPS на одно ядро.

Проблемы, с которыми я столкнулся

1. Сборка OpenSSL + OQS

Главная задача — собрать классический OpenSSL с OQS-provider. Готовая сборка с нужными библиотеками есть, но, к сожалению, проект заморожен, что в репозитории не указано.

В результате я собрал связку: OpenSSL 3.5.1 + liboqs 0.14.0 + oqs-provider 0.9.0 на Linux. Все попытки собрать под Windows пока безуспешны; возможно, нужно глубже изучить процесс.

2. Отсутствие ряда методов в OpenSSL 3.5.1

В собранной библиотеке отсутствовали вызовы SSL_SET1_GROUPS_LIST SSL_SET_MIN_PROTO_VERSION и SSL_SET_TLSEXT_HOSTNAME, хотя они описаны в официальной документации. Пришлось использовать:

SSL_CTX_ctrl(_ctx, SSL_CTRL_SET_GROUPS_LIST, 0, groupsPtr);
SSL_ctrl(_ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, hostPtr);
SSL_CTX_ctrl(_ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, TLS1_3_VERSION, NULL);

3. Генерация сертификатов «на лету»

Разрывы соединений из-за несоответствия сертификата домену оказались самой трудоёмкой частью. Позже выяснилось, что проблема типична для тех, кто недостаточно глубоко разобрался в TLS-рукопожатии и самом процессе установления соединения.

Проверка работоспособности

  1. TShark-анализ
    Сначала я прослушивал трафик и анализировал tls.handshake через tshark. Запуская curl к сервису Post-Quantum Key Agreement at Cloudflare

    проверял следующие поля:

    • Supported Group

    • Key Share Entry: Group

    В них должны появляться значения Unknown (0x11ec) или Unknown (4588). При использовании ML-KEM-768 (правильная форма, а не «MLKEM768») с вспомогательной группой дополнительно виден x25519 (0x001d). Наличие Unknown (4588) подтверждает PQ-рукопожатие. (подробней о ClientHello при использовании PQ)

  2. Тест через системный прокси
    Затем я назначил прокси системным в Windows и использовал Microsoft Edge (он берёт настройки OS, в отличие от DuckDuckGo, которым я обычно пользуюсь). Тест выявил ошибки чтения/записи байтов при ответе на рукопожатие (в Linux-версии curl их не было). После исправлений все режимы — both (ML-KEM + x25519), pqonly (ML-KEM-768) и classic (x25519) — прошли успешно.

    Итог

    Сейчас есть рабочий прокси с PQ-TLS, который можно задать как системный или указать сервису для вывода трафика, но пока что. производительность ниже цели ≈ 150 RPS и не реализован https:// обращение к pq proxy от back-end. Пока что продолжается оптимизация кода.

    Подробные инструкции по сборке и исходники доступны на GitHub / GitVerse

    Статьи и источники