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.
Генерация ключей
Начиная с версии 2.12.3, используйте встроенный генератор Hysteria:
Параметр --public-name обязателен: это внешний SNI, передаваемый в открытом виде, а не настоящее имя сервера.
Команда создаёт ech.pem и выводит готовые для вставки блоки конфигурации сервера и клиента.
Файл содержит оба PEM-блока:
-----BEGIN ECH KEYS-----
...
-----END ECH KEYS-----
-----BEGIN ECH CONFIGS-----
...
-----END ECH CONFIGS-----
Не публикуйте ech.pem. Он содержит приватный ключ. Передавайте другим только значение base64, выведенное в настройке клиента tls.ech. Сервер считывает блок ECH KEYS и на его основе формирует соответствующий публичный список конфигураций.
Параметры:
| Параметр | По умолчанию | Описание |
|---|---|---|
--public-name |
Обязателен | Внешний SNI, передаваемый в открытом виде. |
--output, -o |
ech.pem |
Выходной PEM-файл с приватным ключом. |
--config-id |
Случайный байт | Идентификатор конфигурации, 0-255; -1 выбирает случайный ID. При ротации используйте разные ID для одновременно действующих ключей. |
--max-name-length |
0 |
Подсказка о длине внутреннего имени для расчёта дополнения (padding), 0-255. Ноль означает, что длина неизвестна; это не ограничивает длину настоящего имени сервера. |
--aead |
aes-128-gcm |
Алгоритмы HPKE AEAD через запятую, в порядке предпочтения: aes-128-gcm, aes-256-gcm, chacha20-poly1305. |
--overwrite |
Выключен | Явно заменить существующий файл ключа. |
Сгенерированные ключи не заменяют TLS-сертификат сервера. Сохраните существующий сертификат и настройки проверки на клиенте. При замене ключей ECH необходимо передать клиентам новую публичную конфигурацию; клиенты, использующие только старую конфигурацию, не смогут подключиться после того, как сервер перестанет её принимать.
Файлы ключей, созданные командой sing-box generate ech-keypair, также совместимы с Hysteria.
Настройка сервера
Добавьте блок ech, указывающий на файл ключа.
При запуске сервер выводит в лог 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, выведенному командой hysteria ech или в логе сервера. Значением может быть непосредственно строка base64 или путь к файлу, содержащему её (либо сырой base64, либо PEM-блок ECH CONFIGS):
- Ваше настоящее имя сервера, используемое для проверки сертификата.
- Config list, выведенный командой
hysteria echили в логе сервера, либо путь к файлу, содержащему его.
Config list также можно передать в URI для обмена через параметр запроса ech.
Важные особенности поведения
-
Включение ECH обратно совместимо. Сервер с включённым ECH по-прежнему принимает клиентов, которые не используют ECH; такие клиенты просто отправляют свой SNI в открытом виде, как раньше. Это означает, что вы можете включить ECH на сервере, не ломая существующих клиентов.
-
Fail-closed. Если клиент настроен на ECH, но сервер его отклоняет (например, потому что config list устарел после повторной генерации ключей или на сервере ECH вообще не настроен), соединение завершается неудачей.
-
insecureне применяется к отклонению ECH. Когда ECH отклоняется, TLS-стек выполняет обязательную проверку сертификата по public name и игнорируетtls.insecure. Если вы тестируете с самоподписанным сертификатом, а сервер на самом деле не принимает ECH, вы увидите ошибку проверки сертификата.