REALITY — sing-box
sing-box реализует обе стороны REALITY. Входящий (подблок reality: внутри встроенного блока tls:) выдаёт себя за сторонний сайт во время TLS-рукопожатия; исходящий (также вложенный в tls:) содержит лишь публичную половину ключа и short ID.
Входящий reality
Располагается в tls.reality. У входящего и tls.enabled, и tls.reality.enabled должны быть равны true.
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
enabled | bool | false | true | false | Включить REALITY для этого входящего. При true обычное TLS-рукопожатие заменяется рукопожатием REALITY. |
handshake | InboundRealityHandshakeOptions | (required) | InboundRealityHandshakeOptions | Цель маскировки. Неавторизованные соединения (неверный SNI / неверный short_id) прозрачно проксируются на этот адрес, так что наблюдатель видит трафик к легитимному сайту. |
private_key | string | (required) | <base64 X25519 private key> | Приватный ключ X25519 сервера. Генерируется командой `sing-box generate reality-keypair`. |
short_id | badoption.Listable[string] | [] | [<hex string>] | Список разрешённых short ID (hex, чётная длина, ≤ 16 символов). Одна запись `""` разрешает клиентов без short ID. |
max_time_difference | badoption.Duration | 0 (no limit) | <duration> | Максимально допустимое расхождение часов клиента и сервера. Соединения вне этого окна отклоняются. 0 отключает проверку. |
Исходный код: option/tls.go:193-199 · зафиксировано на v1.13.15 (3708fa1)
handshake
Подблок handshake встраивает ServerOptions (server, server_port) и DialerOptions для маскировочного апстрима:
"handshake": {
"server": "www.cloudflare.com",
"server_port": 443,
"bind_interface": "eth0"
}Исходящий reality
Располагается в tls.reality внутри встроенного блока tls: исходящего.
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
enabled | bool | false | true | false | Включить REALITY для этого исходящего. |
public_key | string | (required) | <base64 X25519 public key> | Публичный ключ X25519 сервера. Составляет пару с `private_key` на сервере. |
short_id | string | "" | <hex string> | Short ID, объявляемый серверу. Должен совпадать с одной из записей `short_id` на сервере (или быть пустым, если сервер это разрешает). |
Исходный код: option/tls.go:234-238 · зафиксировано на v1.13.15 (3708fa1)
Генерация ключей
$ sing-box generate reality-keypair
PrivateKey: <base64-private-key>
PublicKey: <base64-public-key>Приватный ключ помещается в private_key на сервере; публичный — в public_key у клиентов. Short ID — произвольные hex-строки, которые вы назначаете каждому клиенту.
Примеры
Сервер — VLESS поверх REALITY, маскирующийся под www.cloudflare.com:
{
"inbounds": [{
"type": "vless",
"tag": "vless-reality",
"listen": "::",
"listen_port": 443,
"users": [{ "uuid": "...", "flow": "xtls-rprx-vision" }],
"tls": {
"enabled": true,
"server_name": "www.cloudflare.com",
"reality": {
"enabled": true,
"handshake": {
"server": "www.cloudflare.com",
"server_port": 443
},
"private_key": "<base64-private-key>",
"short_id": ["", "0123456789abcdef"]
}
}
}]
}Клиент:
{
"outbounds": [{
"type": "vless",
"server": "your.server.example",
"server_port": 443,
"uuid": "...",
"flow": "xtls-rprx-vision",
"tls": {
"enabled": true,
"server_name": "www.cloudflare.com",
"utls": { "enabled": true, "fingerprint": "chrome" },
"reality": {
"enabled": true,
"public_key": "<base64-public-key>",
"short_id": "0123456789abcdef"
}
}
}]
}Примечания
handshake.serverиhandshake.server_portвместе образуют цель маскировки — в Xray это называетсяdest. Неавторизованные соединения прозрачно проксируются на этот адрес, поэтому картина в канале выглядит как обращение к этому сайту.- Исходящий намеренно минимален — только
public_keyиshort_id. Всё остальное (SNI, ALPN, отпечаток) берётся из объемлющего блокаtls. tls.utlsпочти всегда задаётся вместе сtls.realityна исходящем. Без uTLS у ClientHello отпечаток стандартной библиотеки Go, который не похож на браузерный и сводит маскировку на нет.max_time_difference— окно отклонения по расхождению часов. Задавайте его с запасом (например, 1 минута) там, где серверы и клиенты не используют общий источник NTP.
Сравнение с другими ядрами
- Xray-core держит все поля REALITY в одной структуре
REALITYConfig(серверные и клиентские поля вместе). Цель маскировки — полеdest. См. REALITY — Xray-core. - mihomo разделяет структуры на входящую/исходящую и использует kebab-case в именах полей (
public-key,private-key,short-id,server-names). См. REALITY — mihomo.
Исходный код: option/tls.go:193-238 · v1.13.15 (3708fa1)
