Перейти к содержанию

ECH

ECH (Encrypted Client Hello) шифрует TLS ClientHello, включая SNI (Server Name Indication), так что промежуточным устройствам виден только подставное «публичное имя» (public name).

Без ECH SNI передаётся в открытом виде в каждом рукопожатии, что позволяет промежуточным устройствам анализировать и блокировать его. С ECH настоящее имя сервера находится внутри зашифрованных данных.

Обратите внимание, что ECH защищает только SNI в QUIC/TLS-рукопожатии. Если вы уже используете обфускацию, всё соединение и так не распознаётся как QUIC, поэтому ECH не даёт дополнительной выгоды. ECH наиболее полезен в «голом» режиме, где QUIC-рукопожатие стандартное, а SNI — основной открытый отпечаток.

Как это работает

Развёртывание ECH включает два артефакта, генерируемых вместе как пара ключей:

  • Приватный ключ, который остаётся на сервере и используется для расшифровки настоящего ClientHello.
  • Config list (публичный), который клиенты используют для шифрования своего ClientHello. Он также содержит public name — подставной SNI, который отображается в открытом виде.

Когда клиент подключается с ECH, он отправляет ClientHello, видимый SNI которого — это public name (например, decoy.example.com), тогда как настоящий SNI и остальная часть рукопожатия зашифрованы внутри расширения ECH.

Генерация ключей

Hysteria не генерирует ключи ECH самостоятельно. Мы рекомендуем использовать sing-box для создания пары ключей:

sing-box generate ech-keypair decoy.example.com

Аргумент — это public name. Он НЕ обязан быть доменом, которым вы владеете, но для лучшей маскировки это должно быть безобидное имя, которое правдоподобно обслуживает обычный трафик. Команда выводит два PEM-блока:

-----BEGIN ECH CONFIGS-----
...
-----END ECH CONFIGS-----
-----BEGIN ECH KEYS-----
...
-----END ECH KEYS-----

Сохраните весь вывод в файл (например, ech.pem). Сервер считывает из него блок ECH KEYS; вам не нужно вручную разделять блоки.

sing-box generate ech-keypair decoy.example.com > ech.pem

Настройка сервера

Добавьте блок ech, указывающий на файл ключа.

ech:
  keyPath: ech.pem

При запуске сервер выводит в лог config list, который нужен клиентам:

INFO ECH enabled, set the following config list on clients (tls.ech) {"configList": "AEz+DQBIAAAg..."}

Скопируйте эту строку в base64 — именно её вы передаёте клиентам. (Это то же значение, что и блок ECH CONFIGS, только закодированное в base64 в одну строку.)

Настройка клиента

Установите tls.ech равным config list из лога сервера. Значением может быть непосредственно строка base64 или путь к файлу, содержащему её (либо сырой base64, либо PEM-блок ECH CONFIGS):

tls:
  sni: real.example.com # (1)!
  ech: AEz+DQBIAAAg... # (2)!
  1. Ваше настоящее имя сервера, используемое для проверки сертификата.
  2. Config list из лога сервера или путь к файлу, содержащему его.

Config list также можно передать в URI для обмена через параметр запроса ech.

Важные особенности поведения

  • Включение ECH обратно совместимо. Сервер с включённым ECH по-прежнему принимает клиентов, которые не используют ECH; такие клиенты просто отправляют свой SNI в открытом виде, как раньше. Это означает, что вы можете включить ECH на сервере, не ломая существующих клиентов.

  • Fail-closed. Если клиент настроен на ECH, но сервер его отклоняет (например, потому что config list устарел после повторной генерации ключей или на сервере ECH вообще не настроен), соединение завершается неудачей.

  • insecure не применяется к отклонению ECH. Когда ECH отклоняется, TLS-стек выполняет обязательную проверку сертификата по public name и игнорирует tls.insecure. Если вы тестируете с самоподписанным сертификатом, а сервер на самом деле не принимает ECH, вы увидите ошибку проверки сертификата.