From 6ad465c38984c3f7a9fc94c1a7288f668f195717 Mon Sep 17 00:00:00 2001 From: Meow <197331664+Meo597@users.noreply.github.com> Date: Sat, 9 May 2026 06:47:48 +0800 Subject: [PATCH] RU Refactor Transports --- .vitepress/menus/nav.ru.mts | 2 +- .vitepress/menus/sidebar.ru.mts | 49 +- docs/ru/about/news.md | 2 +- docs/ru/config/features/fallback.md | 4 +- docs/ru/config/inbound.md | 6 +- docs/ru/config/inbounds/tunnel.md | 2 +- docs/ru/config/inbounds/vless.md | 2 +- docs/ru/config/outbound.md | 16 +- docs/ru/config/outbounds/freedom.md | 2 +- docs/ru/config/outbounds/hysteria.md | 2 +- docs/ru/config/outbounds/vless.md | 2 +- docs/ru/config/transport.md | 1306 +--------------------- docs/ru/config/transports/finalmask.md | 404 +++++++ docs/ru/config/transports/httpupgrade.md | 4 +- docs/ru/config/transports/index.md | 16 +- docs/ru/config/transports/mkcp.md | 2 +- docs/ru/config/transports/reality.md | 203 ++++ docs/ru/config/transports/sockopt.md | 296 +++++ docs/ru/config/transports/tls.md | 338 ++++++ 19 files changed, 1365 insertions(+), 1293 deletions(-) create mode 100644 docs/ru/config/transports/finalmask.md create mode 100644 docs/ru/config/transports/reality.md create mode 100644 docs/ru/config/transports/sockopt.md create mode 100644 docs/ru/config/transports/tls.md diff --git a/.vitepress/menus/nav.ru.mts b/.vitepress/menus/nav.ru.mts index 8e5042cb..44e613c2 100644 --- a/.vitepress/menus/nav.ru.mts +++ b/.vitepress/menus/nav.ru.mts @@ -9,7 +9,7 @@ export const nav: DefaultTheme.Config["nav"] = [ { text: "Базовая конфигурация", link: "/ru/config/" }, { text: "Входящие подключения", link: "/ru/config/inbounds/" }, { text: "Исходящие подключения", link: "/ru/config/outbounds/" }, - { text: "Транспортный уровень", link: "/ru/config/transports/" } + { text: "Конфигурация транспорта", link: "/ru/config/transports/" } ] }, { diff --git a/.vitepress/menus/sidebar.ru.mts b/.vitepress/menus/sidebar.ru.mts index 6e17889e..b9cc1dfd 100644 --- a/.vitepress/menus/sidebar.ru.mts +++ b/.vitepress/menus/sidebar.ru.mts @@ -47,7 +47,7 @@ export const sidebar: DefaultTheme.Config["sidebar"] = { { text: "Маршрутизация", link: "/ru/config/routing.md" }, { text: "Статистика", link: "/ru/config/stats.md" }, { - text: "Способы передачи", + text: "Конфигурация транспорта", link: "/ru/config/transport.md" }, { text: "Метрики", link: "/ru/config/metrics.md" }, @@ -125,28 +125,47 @@ export const sidebar: DefaultTheme.Config["sidebar"] = { ] }, { - text: "Способы передачи", + text: "Конфигурация транспорта", link: "/ru/config/transports/", collapsed: true, items: [ - { text: "RAW", link: "/ru/config/transports/raw.md" }, { - text: "XHTTP: За пределами REALITY", - link: "/ru/config/transports/xhttp.md" - }, - { text: "mKCP", link: "/ru/config/transports/mkcp.md" }, - { text: "gRPC", link: "/ru/config/transports/grpc.md" }, - { - text: "WebSocket", - link: "/ru/config/transports/websocket.md" + text: "Способы передачи", + items: [ + { text: "RAW", link: "/ru/config/transports/raw.md" }, + { + text: "XHTTP: За пределами REALITY", + link: "/ru/config/transports/xhttp.md" + }, + { text: "mKCP", link: "/ru/config/transports/mkcp.md" }, + { text: "gRPC", link: "/ru/config/transports/grpc.md" }, + { + text: "WebSocket", + link: "/ru/config/transports/websocket.md" + }, + { + text: "HTTPUpgrade", + link: "/ru/config/transports/httpupgrade.md" + }, + { + text: "Hysteria", + link: "/ru/config/transports/hysteria.md" + } + ] }, { - text: "HTTPUpgrade", - link: "/ru/config/transports/httpupgrade.md" + text: "Безопасность транспорта", + items: [ + { text: "REALITY", link: "/ru/config/transports/reality.md" }, + { text: "TLS", link: "/ru/config/transports/tls.md" } + ] }, { - text: "Hysteria", - link: "/ru/config/transports/hysteria.md" + text: "Дополнительные настройки", + items: [ + { text: "FinalMask", link: "/ru/config/transports/finalmask.md" }, + { text: "Sockopt", link: "/ru/config/transports/sockopt.md" } + ] } ] } diff --git a/docs/ru/about/news.md b/docs/ru/about/news.md index e6198ed5..c483397f 100644 --- a/docs/ru/about/news.md +++ b/docs/ru/about/news.md @@ -348,7 +348,7 @@ Winter cannot cover the NEXT FUTURE... ## 2022.8.28 [v1.5.10](https://github.com/XTLS/Xray-core/releases/tag/v1.5.10) -Нижний транспорт поддерживает более разумную конфигурацию TCP Keepalive. +`sockopt` теперь поддерживает более разумную конфигурацию TCP Keepalive. ## 2022.6.20 [v1.5.8](https://github.com/XTLS/Xray-core/releases/tag/v1.5.8) diff --git a/docs/ru/config/features/fallback.md b/docs/ru/config/features/fallback.md index d61c25cf..78f55325 100644 --- a/docs/ru/config/features/fallback.md +++ b/docs/ru/config/features/fallback.md @@ -38,7 +38,7 @@ Fallback также может разделять трафик различны Элемент `fallbacks` является необязательным и может использоваться только для комбинации транспорта TCP+TLS. -- Если этот элемент имеет дочерние элементы, в [Inbound TLS](../transport.md#tlsobject) необходимо установить `"alpn":["http/1.1"]`. +- Если этот элемент имеет дочерние элементы, в [Inbound TLS](../transports/tls.md#tlsobject) необходимо установить `"alpn":["http/1.1"]`. Обычно сначала нужно настроить набор резервных путей по умолчанию с опущенными или пустыми `alpn` и `path`, а затем настроить другие разделения по мере необходимости. @@ -56,7 +56,7 @@ VLESS будет перенаправлять трафик с длиной пе При необходимости VLESS попытается прочитать результат согласования TLS ALPN, и в случае успеха выведет в лог `realAlpn =`. Назначение: решает проблему несовместимости службы h2c Nginx с http/1.1, для которой в Nginx требуется написать две строки listen, по одной для 1.1 и h2c. -Примечание: если в `fallbacks alpn` присутствует `"h2"`, в [Inbound TLS](../transport.md#tlsobject) необходимо установить `"alpn":["h2","http/1.1"]` для поддержки доступа h2. +Примечание: если в `fallbacks alpn` присутствует `"h2"`, в [Inbound TLS](../transports/tls.md#tlsobject) необходимо установить `"alpn":["h2","http/1.1"]` для поддержки доступа h2. ::: tip `alpn`, установленный в Fallback, соответствует фактически согласованному ALPN, а `alpn`, установленный в Inbound TLS, - это список дополнительных ALPN во время рукопожатия. Это разные вещи. diff --git a/docs/ru/config/inbound.md b/docs/ru/config/inbound.md index ce98d4d3..cdb59567 100644 --- a/docs/ru/config/inbound.md +++ b/docs/ru/config/inbound.md @@ -38,7 +38,7 @@ Можно добавить `@` в начало пути, чтобы использовать [абстрактный сокет](https://www.man7.org/linux/man-pages/man7/unix.7.html), или `@@`, чтобы использовать абстрактный сокет с заполнением. При указании Unix domain socket параметры `port` и `allocate` игнорируются. -В настоящее время поддерживаются протоколы VLESS, VMess, Trojan и типы транспорта TCP, WebSocket, HTTP/2, gRPC. +В настоящее время поддерживаются протоколы VLESS, VMess и Trojan, а также только транспортные способы на базе TCP, например `tcp`, `websocket`, `grpc`. Транспорт на базе UDP, такой как `mkcp`, не поддерживается. При указании Unix domain socket можно указать права доступа к сокету, добавив запятую и индикатор прав доступа, например `"/dev/shm/domain.socket,0666"`. Это может помочь решить проблемы с правами доступа к сокету, которые возникают по умолчанию. @@ -68,9 +68,9 @@ Конкретные настройки зависят от протокола. См. описание `InboundConfigurationObject` для каждого протокола. -> `streamSettings`: [StreamSettingsObject](./transport.md#streamsettingsobject) +> `streamSettings`: [StreamSettingsObject](./transport.md) -Тип транспорта (transport) - это способ взаимодействия текущего узла Xray с другими узлами. +Конфигурация транспорта для этого входящего подключения. > `tag`: string diff --git a/docs/ru/config/inbounds/tunnel.md b/docs/ru/config/inbounds/tunnel.md index e55a887e..c03f4b53 100644 --- a/docs/ru/config/inbounds/tunnel.md +++ b/docs/ru/config/inbounds/tunnel.md @@ -52,7 +52,7 @@ Если значение равно `true`, dokodemo-door будет распознавать данные, перенаправленные iptables, и пересылать их на соответствующий целевой адрес. -См. настройку `tproxy` в разделе [Конфигурация транспорта](../transport.md#sockoptobject). +См. настройку `tproxy` в разделе [Sockopt](../transports/sockopt.md#sockoptobject). > `userLevel`: number diff --git a/docs/ru/config/inbounds/vless.md b/docs/ru/config/inbounds/vless.md index 4d672c0f..dd87c3d6 100644 --- a/docs/ru/config/inbounds/vless.md +++ b/docs/ru/config/inbounds/vless.md @@ -131,7 +131,7 @@ VLESS - это легкий транспортный протокол без с XTLS доступен только в следующих комбинациях -- TCP+TLS/Reality В этом случае зашифрованные данные копируются напрямую на низком уровне (если передается TLS 1.3). +- TCP+TLS/REALITY В этом случае зашифрованные данные копируются напрямую на низком уровне (если передается TLS 1.3). - VLESS Encryption Нет ограничений на транспорт нижнего уровня; если транспорт не поддерживает прямое копирование (см. выше), то выполняется только проброс Encryption. > `reverse`: struct diff --git a/docs/ru/config/outbound.md b/docs/ru/config/outbound.md index ed9cb8f3..ccd4218b 100644 --- a/docs/ru/config/outbound.md +++ b/docs/ru/config/outbound.md @@ -66,9 +66,9 @@ Xray будет использовать случайный IP-адрес из Если это поле не пустое, его значение должно быть **уникальным** среди всех тегов. ::: -> `streamSettings`: [StreamSettingsObject](./transport.md#streamsettingsobject) +> `streamSettings`: [StreamSettingsObject](./transport.md) -Тип транспорта (transport) - это способ взаимодействия текущего узла Xray с другими узлами. +Конфигурация транспорта для этого исходящего подключения. > `proxySettings`: [ProxySettingsObject](#proxysettingsobject) @@ -82,10 +82,10 @@ Xray будет использовать случайный IP-адрес из Если при исходящем подключении отправляется запрос к доменному имени, эта опция управляет тем, будет ли оно разрешено (и каким образом) в IP-адрес для отправки. -Значение по умолчанию — `AsIs`, то есть отправка на удаленный сервер «как есть». Значения всех параметров примерно соответствуют `domainStrategy` в [sockopt](./transport.md#sockoptobject). +Значение по умолчанию — `AsIs`, то есть отправка на удаленный сервер «как есть». Значения всех параметров примерно соответствуют `domainStrategy` в [Sockopt](./transports/sockopt.md#sockoptobject). ::: tip -Здесь контролируются **проксируемые запросы**. Если адресом исходящего прокси-сервера является доменное имя, и для этого домена необходимо выбрать стратегию разрешения, следует настроить `domainStrategy` в [sockopt](./transport.md#sockoptobject). +Здесь контролируются **проксируемые запросы**. Если адресом исходящего прокси-сервера является доменное имя, и для этого домена необходимо выбрать стратегию разрешения, следует настроить `domainStrategy` в [Sockopt](./transports/sockopt.md#sockoptobject). ::: ### ProxySettingsObject @@ -102,15 +102,15 @@ Xray будет использовать случайный IP-адрес из Если указан тег другого Outbound, данные, исходящие из этого Outbound, будут перенаправлены через указанный Outbound. ::: danger -Эта опция конфликтует с [SockOpt.dialerProxy](./transport.md#sockoptobject), используйте только один из этих вариантов по необходимости. +Эта опция конфликтует с [Sockopt.dialerProxy](./transports/sockopt.md#sockoptobject), используйте только один из этих вариантов по необходимости. -По умолчанию этот метод перенаправления **не проходит** через транспортный уровень (REALITY/XHTTP/gRPC...), то есть `streamSettings` данного Outbound не будут иметь эффекта.
-Если вам требуется перенаправление с поддержкой транспортного уровня, используйте `SockOpt.dialerProxy` или установите `transportLayer` в `true`. +По умолчанию этот способ пересылки **игнорирует** собственную конфигурацию транспорта этого outbound (например XHTTP, REALITY или Sockopt), поэтому `streamSettings` у данного outbound не будут работать.
+Если вам нужна пересылка с поддержкой `streamSettings`, используйте `Sockopt.dialerProxy` или установите здесь `transportLayer` в `true`. ::: > `transportLayer`: true | false -`true` преобразует эту настройку в `SockOpt.dialerProxy` для поддержки перенаправления на транспортном уровне. По умолчанию `false` (преобразование не выполняется). +`true` преобразует эту настройку в `Sockopt.dialerProxy`, чтобы пересылка использовала `streamSettings` этого outbound. По умолчанию `false`. ### MuxObject diff --git a/docs/ru/config/outbounds/freedom.md b/docs/ru/config/outbounds/freedom.md index f2e34330..ad26343b 100644 --- a/docs/ru/config/outbounds/freedom.md +++ b/docs/ru/config/outbounds/freedom.md @@ -57,7 +57,7 @@ Freedom — это исходящий протокол, который можн Значение по умолчанию — `"AsIs"`. -Все параметры по смыслу аналогичны `domainStrategy` в [sockopt](../transport.md#sockoptobject). +Все параметры по смыслу аналогичны `domainStrategy` в [Sockopt](../transports/sockopt.md#sockoptobject). Только использование `AsIs` в этом разделе позволяет передать доменное имя в последующий модуль `sockopt`. Если установить значение, отличное от `AsIs`, домен будет разрешен в конкретный IP, что сделает последующие настройки `sockopt.domainStrategy` и связанный с ними механизм `happyEyeballs` недействительными. (Если вы не изменяли эти настройки, негативного влияния не будет). diff --git a/docs/ru/config/outbounds/hysteria.md b/docs/ru/config/outbounds/hysteria.md index e29d41aa..0bd7ef89 100644 --- a/docs/ru/config/outbounds/hysteria.md +++ b/docs/ru/config/outbounds/hysteria.md @@ -2,7 +2,7 @@ Реализация клиента протокола Hysteria. -Эта страница очень проста, так как протокол hysteria фактически разделен на простой протокол управления прокси и оптимизированный низкоуровневый транспорт QUIC. В Xray протокол прокси и низкоуровневый транспорт разделены, подробности см. в разделе [hysteriaSettings](../transports/hysteria.md) [finalmask.quicParams](../transport.md#quicParams) низкоуровневого транспорта. +Эта страница очень проста, так как протокол hysteria фактически состоит из простого протокола управления прокси и оптимизированной QUIC-реализации транспорта. В Xray прокси-протокол и конфигурация транспорта разделены. Подробности, включая `brutal`, см. в параметрах транспорта [hysteriaSettings](../transports/hysteria.md) и [FinalMask.quicParams](../transports/finalmask.md#quicparams). ::: tip Сам протокол `hysteria` не имеет аутентификации. При использовании с транспортным уровнем, отличным от `hysteria`, он не сможет выступать в качестве прокси для `udp`, и его использование с другими транспортными уровнями не рекомендуется. diff --git a/docs/ru/config/outbounds/vless.md b/docs/ru/config/outbounds/vless.md index 4d1bc877..b2d2a23b 100644 --- a/docs/ru/config/outbounds/vless.md +++ b/docs/ru/config/outbounds/vless.md @@ -84,7 +84,7 @@ VLESS - это легкий транспортный протокол без с XTLS доступен только в следующих комбинациях -- TCP+TLS/Reality: если в данный момент передаётся TLS 1.3, ядро попытается выполнить Splice на зашифрованных данных нижнего уровня; в случае успеха это позволит сэкономить все IO-затраты ядра. +- TCP+TLS/REALITY: если в данный момент передаётся TLS 1.3, ядро попытается выполнить Splice на зашифрованных данных нижнего уровня; в случае успеха это позволит сэкономить все IO-затраты ядра. - VLESS Encryption: не имеет ограничений по нижнему уровню транспорта. Если нижний уровень не TCP, будет предпринята только попытка «прозрачного» прохождения Encryption, что сэкономит накладные расходы Encryption; если же используется TCP, всё равно будет предпринята попытка выполнения Splice. ::: tip О Splice diff --git a/docs/ru/config/transport.md b/docs/ru/config/transport.md index dbaf84d7..52be5644 100644 --- a/docs/ru/config/transport.md +++ b/docs/ru/config/transport.md @@ -1,26 +1,33 @@ -# Способы передачи (uTLS, REALITY) +# Конфигурация транспорта -Способ передачи (transport) — это способ взаимодействия текущего узла Xray с другими узлами. +Конфигурация транспорта определяет, как текущий экземпляр Xray взаимодействует с другой стороной. Этой стороной может быть как другой узел Xray, так и обычный публичный сетевой адрес. -Транспорт определяет способ передачи данных. Обычно оба конца сетевого подключения должны использовать одинаковый транспорт. -Например, если один конец использует WebSocket, то другой конец также должен использовать WebSocket, иначе соединение не будет установлено. +Она описывает часть ниже самого прокси-протокола: способ переноса потока, защиту транспорта и дополнительные низкоуровневые настройки. + +Эти три группы относятся к разным уровням и в определенных пределах могут комбинироваться: + +- Способы передачи определяют, как именно переносится поток данных, например через RAW, WebSocket, gRPC или Hysteria. +- Безопасность транспорта определяет механизм защиты, например TLS или REALITY. +- Дополнительные настройки управляют низкоуровневым сетевым поведением и финальной маскировкой трафика. + +Часть параметров транспорта напрямую влияет на способ установления соединения с удаленной стороной. Для параметров, которые требуют согласования, обе стороны обычно должны использовать совместимые настройки. Например, если одна сторона использует WebSocket, другая тоже должна использовать WebSocket, иначе соединение не будет установлено. + +Для прямых исходящих соединений, таких как [Freedom](./outbounds/freedom.md), другой стороной может быть не другой узел Xray, а просто публичный адрес назначения. В этом случае конфигурация транспорта не используется для согласования с другим Xray, а управляет локальным исходящим соединением. В таком сценарии доступен только `sockopt`. ## StreamSettingsObject -`StreamSettingsObject` соответствует элементу `streamSettings` в [`InboundObject`](./inbound.md) или [`OutboundObject`](./outbound.md). +`StreamSettingsObject` соответствует полю `streamSettings` в [`InboundObject`](./inbound.md) или [`OutboundObject`](./outbound.md). Каждый inbound или outbound может иметь собственную конфигурацию транспорта. ```json { - // outbound example; also applies to inbound + // пример для outbound, аналогично применимо к inbound "outbounds": [ { // ... "streamSettings": { - // [!code focus:34] + // [!code focus:16] + // Способы передачи "network": "raw", - "security": "none", - "tlsSettings": {}, - "realitySettings": {}, "rawSettings": {}, "xhttpSettings": {}, "kcpSettings": {}, @@ -28,1290 +35,83 @@ "wsSettings": {}, "httpupgradeSettings": {}, "hysteriaSettings": {}, - "finalmask": { - "tcp": [], - "udp": [], - "quicParams": {} - }, - "sockopt": { - "mark": 0, - "tcpMaxSeg": 1440, - "tcpFastOpen": false, - "tproxy": "off", - "domainStrategy": "AsIs", - "happyEyeballs": {}, - "dialerProxy": "", - "acceptProxyProtocol": false, - "tcpKeepAliveInterval": 0, - "tcpKeepAliveIdle": 300, - "tcpUserTimeout": 10000, - "tcpCongestion": "bbr", - "interface": "wg0", - "v6only": false, - "tcpWindowClamp": 600, - "tcpMptcp": false - } + // Безопасность транспорта + "security": "none", + "realitySettings": {}, + "tlsSettings": {}, + // Дополнительные настройки + "finalmask": {}, + "sockopt": {} } } ] } ``` -> `network`: "raw" | "xhttp" | "kcp" | "grpc" | "ws" | "httpupgrade" | "hysteria" +> `network`: "raw" | "xhttp" | "mkcp" | "grpc" | "websocket" | "httpupgrade" | "hysteria" -Тип способа передачи, используемого потоком данных соединения, по умолчанию `"raw"`. - -::: tip -**Начиная с версии v24.9.30**, для более точного отражения фактического поведения, тип передачи `tcp` был переименован в `raw`. Для обеспечения совместимости `"network": "raw"` и `"network": "tcp"`, `rawSettings` и `tcpSettings` являются синонимами. -::: - -> `security`: "none" | "tls" | "reality" - -Включено ли шифрование транспортного уровня, поддерживаемые опции: - -- `"none"` означает отсутствие шифрования (значение по умолчанию) -- `"tls"` означает использование [TLS](https://ru.wikipedia.org/wiki/Протокол_защиты_транспортного_уровня). -- `"reality"` означает использование REALITY. - -> `tlsSettings`: [TLSObject](#tlsobject) - -Конфигурация TLS. TLS предоставляется Golang, обычно результатом согласования TLS является использование TLS 1.3, DTLS не поддерживается. - -> `realitySettings`: [RealityObject](#realityobject) - -Конфигурация Reality. Reality — это оригинальная технология Xray. Reality обеспечивает более высокий уровень безопасности, чем TLS, и настраивается так же, как TLS. - -::: tip -Reality — это самое безопасное на данный момент решение для шифрования передачи данных, и внешний вид трафика такой же, как и при обычном просмотре веб-страниц. Включение Reality и настройка подходящего режима управления потоком XTLS Vision может повысить производительность в несколько раз или даже в десятки раз. -::: +Способ передачи, используемый потоком данных. Значение по умолчанию — `raw`. > `rawSettings`: [RawObject](./transports/raw.md) -Конфигурация RAW для текущего соединения, действительна только если это соединение использует RAW. +Настройки RAW для потока данных. Действуют только когда `network` равно `raw`. -> `xhttpSettings`: [XHTTP: Beyond REALITY](https://github.com/XTLS/Xray-core/discussions/4113#discussioncomment-11468947) +> `xhttpSettings`: [XHTTPObject](./transports/xhttp.md) -Конфигурация XHTTP для текущего соединения, действительна только если это соединение использует XHTTP. +Настройки XHTTP для потока данных. Действуют только когда `network` равно `xhttp`. > `kcpSettings`: [KcpObject](./transports/mkcp.md) -Конфигурация mKCP для текущего соединения, действительна только если это соединение использует mKCP. +Настройки mKCP для потока данных. Действуют только когда `network` равно `mkcp`. > `grpcSettings`: [GRPCObject](./transports/grpc.md) -Конфигурация gRPC для текущего соединения, действительна только если это соединение использует gRPC. +Настройки gRPC для потока данных. Действуют только когда `network` равно `grpc`. > `wsSettings`: [WebSocketObject](./transports/websocket.md) -Конфигурация WebSocket для текущего соединения, действительна только если это соединение использует WebSocket. +Настройки WebSocket для потока данных. Действуют только когда `network` равно `websocket`. -> `httpupgradeSettings`: [HttpUpgradeObject](./transports/httpupgrade.md) +> `httpupgradeSettings`: [HTTPUpgradeObject](./transports/httpupgrade.md) -Конфигурация HTTPUpgrade для текущего соединения, действительна только если это соединение использует HTTPUpgrade. +Настройки HTTPUpgrade для потока данных. Действуют только когда `network` равно `httpupgrade`. > `hysteriaSettings`: [HysteriaObject](./transports/hysteria.md) -Конфигурация Hysteria для текущего соединения, действительна только если это соединение использует Hysteria. +Настройки Hysteria для потока данных. Действуют только когда `network` равно `hysteria`. -> `sockopt`: [SockoptObject](#sockoptobject) +--- -Конкретные настройки, связанные с прозрачным проксированием. +> `security`: "none" | "reality" | "tls" -> `finalmask`: [FinalMaskObject](#finalmaskobject) +Включать ли защиту транспорта. Поддерживаются следующие значения: -Конфигурация FinalMask, используемая для универсальной маскировки трафика. +- `"none"` означает, что защита отключена (значение по умолчанию) +- `"reality"` означает использование REALITY +- `"tls"` означает использование [TLS](https://ru.wikipedia.org/wiki/Протокол_защиты_транспортного_уровня) -### TLSObject +> `realitySettings`: [RealityObject](./transports/reality.md) -```json -{ - "serverName": "xray.com", - "verifyPeerCertByName": "", - "rejectUnknownSni": false, - "allowInsecure": false, - "alpn": ["h2", "http/1.1"], - "minVersion": "1.2", - "maxVersion": "1.3", - "cipherSuites": "Здесь укажите названия необходимых вам наборов шифров, разделяя их двоеточиями", - "certificates": [], - "disableSystemRoot": false, - "enableSessionResumption": false, - "fingerprint": "chrome", - "pinnedPeerCertSha256": "", - "curvePreferences": [""], - "masterKeyLog": "", - "echConfigList": "", - "echServerKeys": "", - "echSockopt": {} -} -``` +Настройки REALITY. REALITY — это модификация TLS, которая использует внешний вид и характеристики рукопожатия целевого сайта как маскировку. -> `serverName`: string - -Указывает доменное имя сертификата сервера, полезно, когда соединение устанавливается по IP-адресу. - -Если оставить пустым, автоматически используется значение из адреса (если это доменное имя), это значение также используется для проверки действительности сертификата сервера. - -Специальное значение `"FromMitM"`. Это заставит использовать SNI, содержащийся в TLS, который был расшифрован входящим соединением dokodemo-door. - -> `verifyPeerCertByName`: string - -Только для клиента. Используется для SNI при проверке сертификата. Можно указать несколько доменов, разделяя их `,` (достаточно, чтобы хотя бы один SAN сертификата присутствовал в этом списке). Это переопределит `serverName`, используемый для проверки; применяется для маскировки домена (Domain Fronting) и других специальных целей. - -Специальное значение `"FromMitM"`: при его использовании в список будет дополнительно добавлен SNI из TLS-трафика, расшифрованного входящим соединением `dokodomo-door`. - -> `rejectUnknownSni`: bool - -Если значение равно `true`, то сервер отклонит рукопожатие TLS, если полученный SNI не соответствует доменному имени сертификата. По умолчанию равно `false`. - -> `alpn`: \[ string \] - -Массив строк, указывающий значения ALPN, указанные во время рукопожатия TLS. Значение по умолчанию: `["h2", "http/1.1"]`. - -Специальное значение: `["FromMitM"]` (когда это единственный элемент) заставит исходящий TLS использовать ALPN из TLS-соединения, расшифрованного входящим `dokodemo-door`. - -> `minVersion`: string - -`minVersion` — это минимально допустимая версия TLS. - -> `maxVersion`: string - -`maxVersion` — это максимально допустимая версия TLS. - -> `cipherSuites`: string - -`CipherSuites` используется для настройки списка поддерживаемых наборов шифров, разделенных двоеточиями. - -Вы можете найти список наборов шифров Golang и их описания [здесь](https://golang.org/src/crypto/tls/cipher_suites.go#L500) или [здесь](https://golang.org/src/crypto/tls/cipher_suites.go#L44). - -::: danger -Эти два параметра конфигурации не являются обязательными и обычно не влияют на безопасность. Если они не настроены, Golang автоматически выберет их в зависимости от устройства. Если вы не знакомы с ними, пожалуйста, не настраивайте эти параметры, вы несете ответственность за проблемы, вызванные неправильным заполнением. -::: - -> `allowInsecure`: true | false - -Разрешить ли небезопасные соединения (только для клиента). Значение по умолчанию: `false`. - -Если значение равно `true`, то Xray не будет проверять действительность сертификата TLS, предоставленного удаленным хостом. - -::: danger -~~Из соображений безопасности этот параметр не следует устанавливать в значение `true` в реальных сценариях, иначе вы можете подвергнуться атаке типа «человек посередине».~~ - -Эта опция устарела. Используйте `pinnedPeerCertSha256` для ручного указания необходимого сертификата. -::: - -> `disableSystemRoot`: true | false - -Отключить ли корневые сертификаты операционной системы. Значение по умолчанию: `false`. - -Если значение равно `true`, то Xray будет использовать только сертификаты, указанные в `certificates`, для рукопожатия TLS. Если значение равно `false`, то Xray будет использовать только корневые сертификаты операционной системы для рукопожатия TLS. - -> `enableSessionResumption`: true | false - -Включить ли восстановление сессии. По умолчанию отключено, и оно будет работать только в том случае, если как сервер, так и клиент поддерживают эту функцию и активировали её. - -Если восстановление сессии будет успешно согласовано, передача сертификатов во время рукопожатия станет необязательной. Это может немного сократить время на рукопожатие (разница практически незаметна). - -Обратите внимание, что это не TLS 0RTT. Функция TLS 0RTT пока не поддерживается в gotls, и это не уменьшит количество RTT в процессе TLS-рукопожатия. - -> `fingerprint` : string - -Этот параметр используется для настройки указанного отпечатка `TLS Client Hello`. - -Значение по умолчанию `chrome` . - -При включении Xray будет **эмулировать** отпечаток `TLS` через библиотеку uTLS или генерировать его случайным образом. -Поддерживаются четыре режима настройки: - -1. Отпечатки TLS последних версий популярных браузеров, включая: - -- `"chrome"` -- `"firefox"` -- `"safari"` -- `"ios"` -- `"android"` -- `"edge"` -- `"360"` -- `"qq"` - -2. Автоматическая генерация отпечатка при запуске Xray: - -- `"random"`: случайный выбор из новых версий браузеров. -- `"randomized"`: полная случайная генерация уникального отпечатка (100% поддержка TLS 1.3 с использованием X25519) - -3. Использование имени переменной отпечатка uTLS, например, `"HelloRandomizedNoALPN"` `"HelloChrome_106_Shuffle"`. Полный список см. в [библиотеке uTLS](https://github.com/refraction-networking/utls/blob/master/u_common.go#L434). - -4. Отключение **эмуляции** отпечатка `TLS Client Hello` - -::: danger -Из соображений безопасности этот параметр не следует устанавливать в значение `unsafe`. -::: - -- `"unsafe"`: отпечаток go/tls +Действуют только когда `security` равно `reality`. ::: tip -Эта функция только **эмулирует** отпечаток `TLS Client Hello`, поведение и другие отпечатки такие же, как у Golang. Если вам нужна более полная эмуляция отпечатка и поведения браузера `TLS`, используйте [Browser Dialer](./transports/websocket.md#browser-dialer). +REALITY сейчас является одной из самых сильных схем защиты транспорта, а снаружи такой трафик выглядит максимально похоже на обычный веб-трафик. В сочетании с подходящим режимом XTLS Vision можно также получить прирост производительности в несколько раз или даже больше чем в десять раз. ::: -::: tip -При использовании этой функции некоторые параметры TLS, влияющие на отпечаток TLS, будут переопределены библиотекой utls и не будут действовать, например, ALPN. -Передаваемые параметры: -`"serverName" "disableSystemRoot" "pinnedPeerCertSha256" "masterKeyLog"` -::: +> `tlsSettings`: [TLSObject](./transports/tls.md) -> `pinnedPeerCertSha256`: string +Настройки TLS. Реализация TLS предоставляется Go. В обычных условиях переговоры обычно приходят к TLS 1.3. DTLS не поддерживается. -Используется для указания SHA256-хеша сертификата удаленного сервера. Используется шестнадцатеричный формат (hex), регистр не важен. Например: `e8e2d387fdbffeb38e9c9065cf30a97ee23c0e3d32ee6f78ffae40966befccc9`. Можно перечислить несколько хешей через запятую `,`; проверка считается пройденной при совпадении любого из них. +Действуют только когда `security` равно `tls`. -Эта кодировка совпадает с отпечатком SHA-256 в просмотрщике сертификатов Chrome, а также с форматом Certificate Fingerprints SHA-256 на сайте crt.sh. Значение можно вычислить с помощью команды `xray tls hash --cert ` или `openssl x509 -noout -fingerprint -sha256 -in cert.pem` (формат с двоеточиями, который она генерирует, также поддерживается). Команда `xray tls ping` также выводит SHA256-хеш удаленного сертификата. +--- -Эта проверка переопределяет стандартную валидацию сертификатов. Возможны два сценария: +> `finalmask`: [FinalMaskObject](./transports/finalmask.md) -- 1. Если ядро находит совпадающий хеш для конечного (leaf) сертификата, проверка сразу же проходит успешно. -- 2. Если ядро находит совпадающий хеш для сертификата CA (это может быть корневой или промежуточный сертификат), оно проверит, подписан ли конечный сертификат этим CA, используя для валидации значение из `serverName`. +Настройки FinalMask для финальной маскировки трафика. -> `certificates`: \[ [CertificateObject](#certificateobject) \] +> `sockopt`: [SockoptObject](./transports/sockopt.md) -Список сертификатов, каждый элемент которого представляет собой сертификат (рекомендуется fullchain). - -::: tip -Если вам нужно получить оценку A/A+ в ssllibs или myssl, -пожалуйста, обратитесь к [этому](https://github.com/XTLS/Xray-core/discussions/56#discussioncomment-215600). -::: - -> `curvePreferences`: \[ string \] - -Массив строк, задающий предпочтительные кривые для выполнения ECDHE во время TLS-рукопожатия. Список поддерживаемых кривых приведён ниже (регистр не имеет значения): -CurveP256 -CurveP384 -CurveP521 -X25519 -X25519MLKEM768 -SecP256r1MLKEM768* -SecP384r1MLKEM1024* - -\*: Не поддерживается utls - -Значение по умолчанию начиная с go1.26 включает все вышеперечисленные кривые. Изменение порядка не заставляет клиента или сервер отдавать предпочтение конкретной кривой; фактическая кривая будет согласована самим механизмом обмена ключами. - -> `masterKeyLog` : string - -Файл журнала (Pre)-Master-Secret, путь к которому задаётся здесь, может быть использован в Wireshark и других программах для расшифровки TLS-соединений, устанавливаемых Xray. - -> `echConfigList` : string - -Только для клиента. Задаёт ECHConfig; если значение задано — клиент включает Encrypted Client Hello. Поддерживаются два формата. - -Фиксированный ECHConfig, например `"AF7+DQBaAAAgACA51i3Ssu4wUMV4FNCc8iRX5J+YC4Bhigz9sacl2lCfSQAkAAEAAQABAAIAAQADAAIAAQACAAIAAgADAAMAAQADAAIAAwADAAtleGFtcGxlLmNvbQAA"` - -Получение через DNS. Удобно при использовании CDN: по HTTPS-записи можно динамически получить ECHConfig; Xray будет соблюдать TTL, возвращённый сервером. Запрашивается SNI из конфигурации или доменное имя сервера (если SNI пуст и целью является домен). - -Базовый вид строки: `"udp://1.1.1.1"` — запрос по UDP DNS к 1.1.1.1. `"https://1.1.1.1/dns-query"` — запрос по DoH (пример; замените на доступный сервер). В обоих случаях можно указать порт, например `udp://1.1.1.1:53`; если порт не указан, берутся значения по умолчанию 53/443. - -Особый случай: можно задать домен, из чьей записи будет браться ECHConfig, например `"example.com+https://1.1.1.1/dns-query"`. Тогда Xray принудительно использует ECHConfig из DNS-записи example.com, что полезно, если нужно получить ECHConfig через DNS, но не хочется светить целевой домен в HTTPS-запросе или публиковать у него HTTPS-запись. - -> `echServerKeys` : string - -Только для сервера. Включает Encrypted Client Hello на стороне сервера. - -Создайте ключи командой `xray tls ech --serverName example.com` где `example.com` — SNI, который будет открыт наружу (можно указать любой). Server Key содержит и ECHConfig; если клиентский Config потерян, его можно восстановить командой `xray tls ech -i "ваш server key"`. -Полученный Config можно опубликовать в HTTPS-записи DNS (см. пример в [Google DNS](https://dns.google/query?name=encryptedsni.com&rr_type=HTTPS) или RFC 9460). - -Учтите: сервер, настроенный на использование ECH, всё ещё принимает обычные не-ECH-соединения. Но клиент, настроенный на ECH, при неудачной ECH-рукопожатии сразу завершит соединение, не откатываясь к открытому SNI. - -> `echSockopt` : [SockoptObject](#sockoptobject) - -Настраивает параметры базового `socket` для соединения, используемого при выполнении DNS-запросов для записей `ECH`. - -### RealityObject - -```json -{ - "show": false, - "target": "example.com:443", - "xver": 0, - "serverNames": ["example.com", "www.example.com"], - "privateKey": "", - "minClientVer": "", - "maxClientVer": "", - "maxTimeDiff": 0, - "shortIds": ["", "0123456789abcdef"], - "mldsa65Seed": "", - "limitFallbackUpload": { - "afterBytes": 0, - "bytesPerSec": 0, - "burstBytesPerSec": 0 - }, - "limitFallbackDownload": { - "afterBytes": 0, - "bytesPerSec": 0, - "burstBytesPerSec": 0 - }, - "fingerprint": "chrome", - "serverName": "", - "password": "", - "shortId": "", - "mldsa65Verify": "", - "spiderX": "" -} -``` - -::: tip -Дополнительную информацию см. в проекте [REALITY](https://github.com/XTLS/REALITY). -::: - -::: tip -Reality лишь модифицирует TLS, и для реализации на стороне клиента достаточно незначительных изменений — полностью случайного session id и кастомной проверки сертификатов. Теоретически это полностью совместимо с большинством TLS-реализаций. -::: - -> `show` : true | false - -Если значение равно `true`, выводить отладочную информацию. - -::: tip -Ниже приведена конфигурация для **входящего** подключения (**сервера**). -::: - -> `target` : string - -Обязательный параметр, формат такой же, как у [dest](./features/fallback.md#fallbackobject) в VLESS `fallbacks`. - -Прежнее название — `dest`. В текущей версии оба поля являются взаимными псевдонимами. - -Если целевой сервер поддерживает пост-квантовый алгоритм обмена ключами X25519MLKEM768, то клиент reality автоматически применит этот алгоритм для согласования ключей. Чтобы проверить поддержку, выполните команду `xray tls ping cloudflare.com` (замените адрес на `dest`, при необходимости добавьте номер порта). - -Ядро по наличию этого поля определяет, является ли текущая конфигурация клиентской или серверной. Не указывайте его на стороне клиента, иначе возникнут ошибки распознавания. - -::: warning -Из соображений маскировки Xray будет **непосредственно перенаправлять** трафик с неудачной аутентификацией (недопустимый запрос REALITY) на `dest`. -Если IP-адрес сайта `dest` особый (например, сайт использует CloudFlare CDN), это равносильно тому, что ваш сервер действует как port forward для CloudFlare, что может привести к злоупотреблению. - -Чтобы этого избежать, можно рассмотреть возможность использования Nginx и других методов для фильтрации нежелательных SNI. -Или вы также можете рассмотреть настройку соответствующих параметров `limitFallbackUpload` и `limitFallbackDownload`, чтобы ограничить скорость. -::: - -> `xver` : number - -Необязательный параметр, формат такой же, как у [xver](./features/fallback.md#fallbackobject) в VLESS `fallbacks`. - -> `serverNames` : \[string\] - -Обязательный параметр, список доступных `serverName` для клиента, подстановочные знаки \* пока не поддерживаются. - -Обычно он совпадает с `dest`, фактическое допустимое значение — это любой SNI, принимаемый сервером (в зависимости от конфигурации `dest`), в качестве справки можно использовать [SAN](https://ru.wikipedia.org/wiki/Subject_Alternative_Name) возвращаемого сертификата. - -Может содержать пустое значение `""`, что означает принятие соединений без SNI. - -> `privateKey` : string - -Обязательный параметр, генерируется с помощью команды `./xray x25519`. - -> `minClientVer` : string - -Необязательный параметр, минимальная версия Xray клиента, формат: `x.y.z`. - -> `maxClientVer` : string - -Необязательный параметр, максимальная версия Xray клиента, формат: `x.y.z`. - -> `maxTimeDiff` : number - -Необязательный параметр, максимально допустимая разница во времени в миллисекундах. - -> `shortIds` : \[string\] - -Обязательный параметр, список доступных `shortId` для клиента, можно использовать для различения разных клиентов. - -Требования к формату см. в `shortId`. - -Если содержит пустое значение, `shortId` клиента может быть пустым. - -> `mldsa65Seed` : string - -Только для сервера. Приватный ключ, применяемый для добавления к сертификату, выдаваемому клиенту Reality, дополнительной пост-квантовой подписи по схеме ML-DSA-65. Назначение — защитить соединение на случай появления квантового компьютера, способного взломать X25519: даже если пароль будет скомпрометирован, MITM-атака останется невозможной. - -Сгенерировать пару ключей можно командой `xray mldsa65`. После того как приватный ключ внесён в конфигурацию сервера, подпись добавляется в расширение сертификата; на старые клиенты или клиенты без поддержки этой функции это не влияет. - -После включения этой функции длина сертификата, возвращаемого целевым сервером (target), **обязательно** должна превышать 3500 байт. Пост-квантовая подпись увеличивает размер временного сертификата Reality; чтобы не создавать отличительную особенность, сертификат target тоже должен быть крупным. Проверить размер можно командой `xray tls ping example.com`. -Для полной пост-квантовой защиты сам target также должен поддерживать ключевой обмен X25519MLKEM768. Поддержку можно проверить той же командой, указанной выше. - -> `limitFallbackUpload`/`limitFallbackDownload` - -::: warning -Предупреждение: Лучшей практикой для REALITY всегда является использование сертификата из той же ASN, поэтому, скорее всего, вам эта функция не понадобится; только если вы вынуждены использовать сертификат CDN, можно рассмотреть включение этой функции, чтобы избежать превращения вашего сервера в узел для других. - -Включение ограничения скорости может ввести новые характеристики, обнаруживаемые GFW! Если вы разработчик GUI/панели/скрипта установки в один клик, обязательно рандомизируйте эти параметры! -::: - -::: tip -`limitFallbackUpload` и `limitFallbackDownload` являются необязательными параметрами. Они позволяют ограничить скорость передачи данных для резервных (fallback) соединений, не прошедших проверку. Параметр `bytesPerSec` по умолчанию равен 0, что означает, что ограничение скорости не включено. - -Принцип работы: Для каждого соединения алгоритм ограничения скорости включается после передачи `afterBytes` байтов. - -Ограничение скорости реализовано с помощью алгоритма "маркерная корзина" (token bucket). Вместимость корзины равна `burstBytesPerSec`. Каждый переданный байт потребляет один маркер, и изначально корзина заполнена до `burstBytesPerSec`. - -Каждую секунду корзина пополняется на `bytesPerSec` маркеров, пока не достигнет своей максимальной вместимости. - -Пример: `afterBytes=10485760`, `burstBytesPerSec=5242880`, `bytesPerSec=1048576` означают, что после передачи 10 МB скорость будет ограничена до 1 МB/с. Если передача приостановится, через 5 секунд скорость может временно вырасти до 5 МB/с (burst), а затем снова вернется к 1 МB/с. - -Рекомендации: Слишком большие значения `afterBytes` и `burstBytesPerSec` не приведут к желаемому эффекту ограничения скорости. Слишком маленькие значения `bytesPerSec` и `burstBytesPerSec` могут быть легко обнаружены. - -Следует разумно подбирать параметры в зависимости от размера ресурсов веб-сайта-источника. Если внезапные скачки скорости нежелательны, установите для `burstBytesPerSec` значение 0. -::: - -> `afterBytes` : number - -Необязательный параметр. Ограничение скорости для резервных соединений REALITY. Ограничение вступает в силу после передачи указанного количества байт. По умолчанию 0. - -> `bytesPerSec` : number - -Необязательный параметр. Ограничение скорости для резервных соединений REALITY. Задаёт базовую скорость (байт/секунду). По умолчанию 0, что означает отключение функции ограничения скорости. - -> `burstBytesPerSec` : number - -Необязательный параметр. Ограничение скорости для резервных соединений REALITY. Задаёт пиковую (burst) скорость (байт/секунду). Действует, когда значение больше `bytesPerSec`. - -::: tip -Ниже приведена конфигурация для **исходящего** подключения (**клиента**). -::: - -> `serverName` : string - -Один из `serverNames` сервера. - -Если `serverNames` сервера содержит пустое значение, то, как и в случае с TLS, клиент может использовать `"serverName": "0.0.0.0"` для установления соединения без SNI. В отличие от TLS, REALITY не требует и не имеет опции разрешения небезопасных соединений для этой функции. При использовании этой функции убедитесь, что `dest` возвращает сертификат по умолчанию при принятии соединений без SNI. - -> `fingerprint` : string - -Обязательный параметр, такой же, как в [TLSObject](#tlsobject). - -> `shortId` : string - -Один из `shortIds` сервера. - -Длина — 8 байт, то есть 16 шестнадцатеричных цифр (0-f), может быть меньше 16, ядро автоматически добавит 0 в конец, но количество цифр должно быть **четным** (потому что один байт состоит из 2 шестнадцатеричных цифр). - -Например, `aa1234` будет автоматически дополнено до `aa12340000000000`, а `aaa1234` приведет к ошибке. - -0 также является четным числом, поэтому, если `shordIDs` сервера содержит пустое значение `""`, клиент также может быть пустым. - -> `password` : string - -Обязательный параметр: публичный ключ, соответствующий приватному ключу сервера. Генерируется командой -`./xray x25519 -i "серверный приватный ключ"`. - -Ранее назывался `publicKey`, однако во избежание недоразумений переименован (формально это X25519-публичный ключ, но в концепции Reality он хранится у клиента и не должен публиковаться). - -> `mldsa65Verify` : string - -Необязательный параметр. Публичный ключ для проверки подписи ML-DSA-65. -Если поле не пустое, клиент будет использовать указанный ключ для валидации сертификата, возвращённого сервером. Подробности см. в описании параметра `"mldsa65Seed"`. - -> `spiderX` : string - -Начальный путь и параметры для краулера, рекомендуется использовать разные для каждого клиента. - -#### CertificateObject - -```json -{ - "ocspStapling": 0, - "oneTimeLoading": false, - "usage": "encipherment", - "buildChain": false, - "certificateFile": "/path/to/certificate.crt", - "keyFile": "/path/to/key.key", - "certificate": [ - "--BEGIN CERTIFICATE--", - "MIICwDCCAaigAwIBAgIRAO16JMdESAuHidFYJAR/7kAwDQYJKoZIhvcNAQELBQAw", - "ADAeFw0xODA0MTAxMzU1MTdaFw0xODA0MTAxNTU1MTdaMAAwggEiMA0GCSqGSIb3", - "DQEBAQUAA4IBDwAwggEKAoIBAQCs2PX0fFSCjOemmdm9UbOvcLctF94Ox4BpSfJ+", - "3lJHwZbvnOFuo56WhQJWrclKoImp/c9veL1J4Bbtam3sW3APkZVEK9UxRQ57HQuw", - "OzhV0FD20/0YELou85TwnkTw5l9GVCXT02NG+pGlYsFrxesUHpojdl8tIcn113M5", - "pypgDPVmPeeORRf7nseMC6GhvXYM4txJPyenohwegl8DZ6OE5FkSVR5wFQtAhbON", - "OAkIVVmw002K2J6pitPuJGOka9PxcCVWhko/W+JCGapcC7O74palwBUuXE1iH+Jp", - "noPjGp4qE2ognW3WH/sgQ+rvo20eXb9Um1steaYY8xlxgBsXAgMBAAGjNTAzMA4G", - "A1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAA", - "MA0GCSqGSIb3DQEBCwUAA4IBAQBUd9sGKYemzwPnxtw/vzkV8Q32NILEMlPVqeJU", - "7UxVgIODBV6A1b3tOUoktuhmgSSaQxjhYbFAVTD+LUglMUCxNbj56luBRlLLQWo+", - "9BUhC/ow393tLmqKcB59qNcwbZER6XT5POYwcaKM75QVqhCJVHJNb1zSEE7Co7iO", - "6wIan3lFyjBfYlBEz5vyRWQNIwKfdh5cK1yAu13xGENwmtlSTHiwbjBLXfk+0A/8", - "r/2s+sCYUkGZHhj8xY7bJ1zg0FRalP5LrqY+r6BckT1QPDIQKYy615j1LpOtwZe/", - "d4q7MD/dkzRDsch7t2cIjM/PYeMuzh87admSyL6hdtK0Nm/Q", - "--END CERTIFICATE--" - ], - "key": [ - "--BEGIN RSA PRIVATE KEY--", - "MIIEowIBAAKCAQEArNj19HxUgoznppnZvVGzr3C3LRfeDseAaUnyft5SR8GW75zh", - "bqOeloUCVq3JSqCJqf3Pb3i9SeAW7Wpt7FtwD5GVRCvVMUUOex0LsDs4VdBQ9tP9", - "GBC6LvOU8J5E8OZfRlQl09NjRvqRpWLBa8XrFB6aI3ZfLSHJ9ddzOacqYAz1Zj3n", - "jkUX+57HjAuhob12DOLcST8np6IcHoJfA2ejhORZElUecBULQIWzjTgJCFVZsNNN", - "itieqYrT7iRjpGvT8XAlVoZKP1viQhmqXAuzu+KWpcAVLlxNYh/iaZ6D4xqeKhNq", - "IJ1t1h/7IEPq76NtHl2/VJtbLXmmGPMZcYAbFwIDAQABAoIBAFCgG4phfGIxK9Uw", - "qrp+o9xQLYGhQnmOYb27OpwnRCYojSlT+mvLcqwvevnHsr9WxyA+PkZ3AYS2PLue", - "C4xW0pzQgdn8wENtPOX8lHkuBocw1rNsCwDwvIguIuliSjI8o3CAy+xVDFgNhWap", - "/CMzfQYziB7GlnrM6hH838iiy0dlv4I/HKk+3/YlSYQEvnFokTf7HxbDDmznkJTM", - "aPKZ5qbnV+4AcQfcLYJ8QE0ViJ8dVZ7RLwIf7+SG0b0bqloti4+oQXqGtiESUwEW", - "/Wzi7oyCbFJoPsFWp1P5+wD7jAGpAd9lPIwPahdr1wl6VwIx9W0XYjoZn71AEaw4", - "bK4xUXECgYEA3g2o9WqyrhYSax3pGEdvV2qN0VQhw7Xe+jyy98CELOO2DNbB9QNJ", - "8cSSU/PjkxQlgbOJc8DEprdMldN5xI/srlsbQWCj72wXxXnVnh991bI2clwt7oYi", - "pcGZwzCrJyFL+QaZmYzLxkxYl1tCiiuqLm+EkjxCWKTX/kKEFb6rtnMCgYEAx0WR", - "L8Uue3lXxhXRdBS5QRTBNklkSxtU+2yyXRpvFa7Qam+GghJs5RKfJ9lTvjfM/PxG", - "3vhuBliWQOKQbm1ZGLbgGBM505EOP7DikUmH/kzKxIeRo4l64mioKdDwK/4CZtS7", - "az0Lq3eS6bq11qL4mEdE6Gn/Y+sqB83GHZYju80CgYABFm4KbbBcW+1RKv9WSBtK", - "gVIagV/89moWLa/uuLmtApyEqZSfn5mAHqdc0+f8c2/Pl9KHh50u99zfKv8AsHfH", - "TtjuVAvZg10GcZdTQ/I41ruficYL0gpfZ3haVWWxNl+J47di4iapXPxeGWtVA+u8", - "eH1cvgDRMFWCgE7nUFzE8wKBgGndUomfZtdgGrp4ouLZk6W4ogD2MpsYNSixkXyW", - "64cIbV7uSvZVVZbJMtaXxb6bpIKOgBQ6xTEH5SMpenPAEgJoPVts816rhHdfwK5Q", - "8zetklegckYAZtFbqmM0xjOI6bu5rqwFLWr1xo33jF0wDYPQ8RHMJkruB1FIB8V2", - "GxvNAoGBAM4g2z8NTPMqX+8IBGkGgqmcYuRQxd3cs7LOSEjF9hPy1it2ZFe/yUKq", - "ePa2E8osffK5LBkFzhyQb0WrGC9ijM9E6rv10gyuNjlwXdFJcdqVamxwPUBtxRJR", - "cYTY2HRkJXDdtT0Bkc3josE6UUDvwMpO0CfAETQPto1tjNEDhQhT", - "--END RSA PRIVATE KEY--" - ] -} -``` - -Сертификат сервера будет автоматически перезагружаться каждые 3600 секунд (то есть каждый час). - -> `ocspStapling`: number - -Интервал обновления OCSP Stapling в секундах, по умолчанию 0. Любое ненулевое значение включит OCSP Stapling и переопределит время горячей перезагрузки сертификата по умолчанию в 3600 секунд (OCSP Stapling выполняется во время перезагрузки). - -> `oneTimeLoading`: true | false - -Загружать только один раз, по умолчанию `false`. Если значение `true`, функции горячей перезагрузки сертификата и OCSP Stapling будут отключены. - -::: warning -Если значение равно `true`, то OCSP-Stapling будет отключено. -::: - -> `usage`: "encipherment" | "verify" | "issue" - -Использование сертификата, значение по умолчанию: `"encipherment"`. - -- `"encipherment"`: сертификат используется для аутентификации и шифрования TLS. -- `"verify"`: сертификат используется для проверки сертификата удаленного TLS. При использовании этого значения текущий сертификат должен быть сертификатом ЦС. -- `"issue"`: сертификат используется для выпуска других сертификатов. При использовании этого значения текущий сертификат должен быть сертификатом ЦС. - -::: tip СОВЕТ 1 -В Windows вы можете установить самоподписанный сертификат ЦС в систему, чтобы проверить сертификат удаленного TLS. -::: - -::: tip СОВЕТ 2 -Когда поступает новый запрос от клиента, предполагая, что указанный `serverName` равен `"xray.com"`, Xray сначала ищет в списке сертификатов сертификат, который можно использовать для `"xray.com"`, и, если он не найден, использует любой сертификат с `usage`, равным `"issue"`, для выпуска сертификата, подходящего для `"xray.com"`, со сроком действия один час. Новый сертификат будет добавлен в список сертификатов для последующего использования. -::: - -::: tip СОВЕТ 3 -Если одновременно указаны `certificateFile` и `certificate`, Xray отдает приоритет `certificateFile`. То же самое касается `keyFile` и `key`. -::: - -::: tip СОВЕТ 4 -Когда `usage` равно `"verify"`, то `keyFile` и `key` могут быть пустыми. -::: - -::: tip СОВЕТ 5 -Используйте `xray tls cert` для генерации самоподписанного сертификата ЦС. -::: - -::: tip СОВЕТ 6 -Если у вас уже есть доменное имя, вы можете использовать инструменты для удобного получения бесплатных сторонних сертификатов, например, [acme.sh](https://github.com/acmesh-official/acme.sh). -::: - -> `buildChain`: true | false - -Вступает в силу только при использовании сертификата `"issue"`, если значение равно `true`, то сертификат ЦС будет встроен в цепочку сертификатов при выпуске сертификата. - -::: tip СОВЕТ 1 -Не следует встраивать корневой сертификат в цепочку сертификатов. Этот параметр следует включать только при подписании сертификата ЦС в качестве промежуточного сертификата. -::: - -> `certificateFile`: string - -Путь к файлу сертификата, например, сгенерированному с помощью OpenSSL, с расширением .crt. - -> `certificate`: \[ string \] - -Массив строк, представляющий содержимое сертификата, формат см. в примере. Используйте либо `certificate`, либо `certificateFile`. - -> `keyFile`: string - -Путь к файлу ключа, например, сгенерированному с помощью OpenSSL, с расширением .key. В настоящее время не поддерживаются файлы ключей, защищенные паролем. - -> `key`: \[ string \] - -Массив строк, представляющий содержимое ключа, формат см. в примере. Используйте либо `key`, либо `keyFile`. - -### SockoptObject - -```json -{ - "mark": 0, - "tcpMaxSeg": 1440, - "tcpFastOpen": false, - "tproxy": "off", - "domainStrategy": "AsIs", - "dialerProxy": "", - "happyEyeballs": {}, - "acceptProxyProtocol": false, - "tcpKeepAliveInterval": 0, - "tcpKeepAliveIdle": 300, - "tcpUserTimeout": 10000, - "tcpcongestion": "bbr", - "interface": "wg0", - "V6Only": false, - "tcpWindowClamp": 600, - "tcpMptcp": false, - "addressPortStrategy": "", - "customSockopt": [] -} -``` - -> `mark`: number - -Целое число. Если значение не равно нулю, то исходящее соединение помечается этим значением с помощью SO_MARK. - -- Работает только в Linux. -- Требуются права CAP_NET_ADMIN. - -> `tcpMaxSeg`: number - -Используется для установки максимального сегмента TCP-пакета (Maximum Segment Size). - -> `tcpFastOpen`: true | false | number - -Включить [TCP Fast Open](https://ru.wikipedia.org/wiki/TCP_Fast_Open). - -Если значение равно `true` или **положительному целому числу**, то TFO включается; если значение равно `false` или **отрицательному числу**, то TFO принудительно отключается; если параметр отсутствует или равен `0`, то используются настройки системы по умолчанию. Можно использовать как для входящих, так и для исходящих подключений. - -- Доступно только в следующих (или более новых) версиях операционных систем: - - Linux 3.16: требуется настройка параметра ядра `net.ipv4.tcp_fastopen`, который представляет собой битовую маску, где `0x1` означает, что клиент может включать TFO, а `0x2` означает, что сервер может включать TFO; значение по умолчанию — `0x1`, если серверу необходимо включить TFO, установите значение этого параметра ядра в `0x3`. - - ~~Windows 10 (1607)~~ (реализовано неправильно) - - Mac OS 10.11 / iOS 9 (требуется тестирование) - - FreeBSD 10.3 (Server) / 12.0 (Client): необходимо установить параметры ядра `net.inet.tcp.fastopen.server_enabled` и `net.inet.tcp.fastopen.client_enabled` в значение `1`. (Требуется тестирование) - -- Для входящих подключений установленное здесь **положительное целое число** представляет собой [максимальное количество ожидающих запросов на подключение TFO](https://tools.ietf.org/html/rfc7413#section-5.1), **обратите внимание, что не все операционные системы поддерживают эту настройку**: - - Linux / FreeBSD: установленное здесь **положительное целое число** представляет собой максимальное значение, максимально допустимое значение — 2147483647, если установлено значение `true`, то используется значение `256`; обратите внимание, что в Linux `net.core.somaxconn` ограничивает максимальное значение, если оно превышает `somaxconn`, то необходимо также увеличить `somaxconn`. - - Mac OS: если здесь установлено значение `true` или **положительное целое число**, это означает только включение TFO, максимальное значение необходимо установить отдельно с помощью параметра ядра `net.inet.tcp.fastopen_backlog`. - - Windows: если здесь установлено значение `true` или **положительное целое число**, это означает только включение TFO. - -- Для исходящих подключений установка значения `true` или **положительного целого числа** в любой операционной системе означает только включение TFO. - -> `tproxy`: "redirect" | "tproxy" | "off" - -Включить ли прозрачное проксирование (только для Linux). - -- `"redirect"`: использовать прозрачное проксирование в режиме перенаправления. Поддерживаются все TCP-соединения на основе IPv4/6. -- `"tproxy"`: использовать прозрачное проксирование в режиме TProxy. Поддерживаются все TCP- и UDP-соединения на основе IPv4/6. -- `"off"`: отключить прозрачное проксирование. - -Для прозрачного проксирования требуются права root или `CAP_NET_ADMIN`. - -::: danger -Если в [Dokodemo-door](./inbounds/tunnel.md) указано `followRedirect: true` и `tproxy` в настройках Sockopt пуст, то значение `tproxy` в настройках Sockopt будет установлено в `"redirect"`. -::: - -> `domainStrategy`: "AsIs" -> "UseIP" | "UseIPv6v4" | "UseIPv6" | "UseIPv4v6" | "UseIPv4" -> "ForceIP" | "ForceIPv6v4" | "ForceIPv6" | "ForceIPv4v6" | "ForceIPv4" - -Значение по умолчанию: `"AsIs"`. - -Если целевой адрес представлен доменным именем, можно настроить соответствующее значение. Поведение Freedom в зависимости от настройки следующее: - -- При использовании `"AsIs"` Xray не выполняет специальную обработку домена. В конечном итоге Xray инициирует соединение, используя встроенный `Dial` из Go. Приоритет выбора адреса фиксирован значениями по умолчанию из RFC6724 (настройки, такие как `gai.conf`, игнорируются). Как правило, приоритет отдается IPv6. -- При использовании другого значения будет применен [встроенный DNS-сервер](dns.md) Xray-core для разрешения доменного имени. - Если объект `DNSObject` отсутствует, будет использоваться системный DNS. Если существует несколько подходящих IP-адресов, ядро выберет один из них случайным образом. -- `"IPv4"` означает попытку подключения только через IPv4, `"IPv4v6"` означает попытку подключения через IPv4 или IPv6, но для доменов dual-stack предпочтение отдается IPv4. (При перестановке v4 и v6 местами логика аналогична, поэтому не описывается повторно). -- Если во встроенном DNS установлен параметр `"queryStrategy"`, то фактическое поведение будет комбинацией с этим параметром, и будут разрешаться только типы IP-адресов, присутствующие в обоих параметрах. Например: - `"queryStrategy": "UseIPv4"` и `"domainStrategy": "UseIP"` фактически эквивалентны `"domainStrategy": "UseIPv4"`. - -::: tip TIP -При использовании режимов `"UseIP"` и `"ForceIP"` и если в [конфигурации исходящего подключения](outbound.md#outboundobject) указан `sendThrough`, ядро автоматически определит необходимый тип IP (IPv4 или IPv6) на основе значения `sendThrough`. Если вручную указан один тип IP (например, UseIPv4), но он не соответствует локальному адресу, указанному в `sendThrough`, подключение завершится неудачно. -::: - -::: danger -Неправильная конфигурация после включения этой функции может привести к бесконечному циклу. - -Кратко: для подключения к серверу необходимо дождаться результата DNS-запроса; для завершения DNS-запроса необходимо подключиться к серверу. - -> Tony: Что было раньше, курица или яйцо? - -Подробное объяснение: - -1. Условие возникновения: прокси-сервер (proxy.com). Встроенный DNS-сервер, режим не Local. -2. Xray пытается установить TCP-соединение с proxy.com **до** того, как запросит proxy.com через встроенный DNS-сервер. -3. Встроенный DNS-сервер устанавливает соединение с dns.com и отправляет запрос для получения IP-адреса proxy.com. -4. **Неправильные** правила маршрутизации приводят к тому, что proxy.com проксирует запрос, отправленный на шаге 3. -5. Xray пытается установить другое TCP-соединение с proxy.com. -6. Перед установкой соединения запрашивает proxy.com через встроенный DNS-сервер. -7. Встроенный DNS-сервер повторно использует соединение с шага 3 и отправляет запрос. -8. Возникает проблема. Установка соединения на шаге 3 требует ожидания результата запроса на шаге 7; завершение запроса на шаге 7 требует полного установления соединения на шаге 3. -9. Игра окончена! - -Решение: - -- Изменить правила маршрутизации для встроенного DNS-сервера. -- Использовать Hosts. -- ~~Если вы все еще не знаете решения, не используйте эту функцию.~~ - -Поэтому **не рекомендуется** неопытным пользователям самостоятельно использовать эту функцию. -::: - -> `dialerProxy`: "" - -Идентификатор исходящего прокси. Если значение не пустое, для установления соединения будет использоваться указанный outbound. Эта опция может быть использована для поддержки цепочной переадресации на уровне транспорта. - -::: danger -Эта опция несовместима с ProxySettingsObject.Tag -::: - -> `acceptProxyProtocol`: true | false - -Только для inbound, указывает, следует ли принимать PROXY protocol. - -[PROXY protocol](https://www.haproxy.org/download/2.2/doc/proxy-protocol.txt) предназначен для передачи реального исходного IP-адреса и порта запроса. **Если вы не знакомы с ним, проигнорируйте этот параметр**. - -Распространенное программное обеспечение обратного прокси (например, HAProxy, Nginx) может быть настроено на его отправку, VLESS fallbacks xver также может его отправлять. - -Если установлено значение `true`, после установления TCP-соединения на самом нижнем уровне, запрашивающая сторона должна сначала отправить PROXY protocol v1 или v2, иначе соединение будет закрыто. - -> `tcpKeepAliveIdle`: number - -Порог времени простоя TCP в секундах. Когда время простоя TCP-соединения достигает этого порога, начинают отправляться Keep-Alive пакеты. - -Для исходящего трафика Xray использует значения по умолчанию из Chrome: как `idle`, так и `interval` равны 45 с. Если этот параметр или `tcpKeepAliveInterval` установить в отрицательное значение, стандартный keep-alive будет отключён; положительное же значение перезапишет настройку по умолчанию. - -Для входящего трафика Keep-Alive по умолчанию отключён; он будет активирован, если любой из этих параметров или `tcpKeepAliveInterval` имеет ненулевое значение. Если указан только один из них, второй примет значение, заданное операционной системой. - -> `tcpKeepAliveInterval`: number - -Интервал (в секундах) между отправками keep-alive-пакетов после того, как TCP-соединение перешло в состояние Keep-Alive. Остальное поведение описано выше. - -> `tcpUserTimeout`: number - -В миллисекундах. Подробнее: https://github.com/grpc/proposal/blob/master/A18-tcp-user-timeout.md - -> `tcpcongestion`: "" - -Алгоритм управления перегрузкой TCP. Поддерживается только в Linux. -Если этот параметр не настроен, используется значение по умолчанию системы. - -::: tip Распространенные алгоритмы - -- bbr (рекомендуется) -- cubic -- reno - -::: - -::: tip -Выполните команду `sysctl net.ipv4.tcp_congestion_control`, чтобы получить значение по умолчанию системы. -::: - -> `interface`: "" - -Указывает имя сетевого интерфейса для исходящего трафика. Поддерживается в Linux, iOS, macOS и Windows. - -> `V6Only`: true | false - -Если установлено значение `true`, адрес `::` принимает только IPv6-соединения. Поддерживается только в Linux. - -> `tcpWindowClamp`: number - -Объявленный размер окна ограничен этим значением. Ядро выберет максимальное значение между этим значением и SOCK_MIN_RCVBUF/2. - -> `tcpMptcp`: true | false - -По умолчанию этот параметр имеет значение `false`. Установите его в `true`, чтобы включить [Multipath TCP](https://en.wikipedia.org/wiki/Multipath_TCP). - -Обратите внимание, что этот параметр действует только на стороне клиента. В Golang версии 1.24 и выше MPTCP уже включен по умолчанию на стороне сервера (при прослушивании соединений). - -Для работы MPTCP требуется Linux с ядром версии 5.6 или новее. - -> `tcpNoDelay`: true | false - -Этот параметр удален, так как golang по умолчанию включает TCP no delay. Если вы хотите отключить его, используйте customSockopt. - -> `addressPortStrategy`: "none" | "SrvPortOnly" | "SrvAddressOnly" | "SrvPortAndAddress" | "TxtPortOnly" | "TxtAddressOnly" | "TxtPortAndAddress" - -Использование SRV или TXT записей для определения целевого адреса/порта исходящего трафика. По умолчанию `none` (отключено). - -Запросы DNS выполняются через системный DNS (не через встроенный DNS Xray). Домен для DNS запроса определяется настройками исходящего подключения. Если DNS запрос не удался, трафик отправляется по исходному адресу и порту. - -Префикс `Srv` указывает на запрос SRV-записей (стандартный формат), префикс `Txt` - на запрос TXT-записей (формат вида `127.0.0.1:80`). - -`PortOnly`: Сброс только порта. -`AddressOnly`: Сброс только адреса. -`PortAndAddress`: Сброс адреса и порта. - -Важно! Данная настройка применяется _до_ этапа выбора стратегии разрешения доменов (`domainStrategy`) в `sockopt`. После сброса адреса продолжает действовать `domainStrategy` (если она активна), но _после_ того, как `domainStrategy` в `Freedom` уже отработала. Если в `Freedom` настроено явное разрешение в IP-адрес, данная опция не оказывает никакого эффекта. - -PS: Если трафик домена, например, обычный веб-трафик, маршрутизируется через `Freedom` с установленной стратегией `AsIs`, то при активации этой опции будет предпринята попытка разрешить домен и сбросить адрес/порт в соответствии с полученными данными. Например, ядро Xray попытается запросить SRV-запись для `google.com` и перенаправить трафик, опираясь на информацию из этой записи. - -> `customSockopt`: [] - -Массив, позволяющий опытным пользователям указывать любые необходимые sockopt. Теоретически все вышеперечисленные настройки, связанные с соединением, могут быть эквивалентно настроены здесь. В настоящее время поддерживаются операционные системы Linux, Windows, Darwin. Приведенный ниже пример эквивалентен `"tcpcongestion": "bbr"` в ядре. - -Перед использованием убедитесь, что вы понимаете программирование сокетов Linux. - -```json -"customSockopt": [ - { - "system": "linux", - "type": "str", - "level":"6", - "opt": "13", - "value": "bbr" - } -] -``` - -> `system`: "" - -Необязательное поле. Указывает операционную систему, для которой будет применяться данная опция. Если текущая операционная система не совпадает с указанной, эта опция (`sockopt`) будет пропущена. В настоящее время доступны значения: `linux`, `windows`, `darwin` (все в нижнем регистре). Если оставить пустым, опция будет применена независимо от операционной системы. - -> `type`: "" - -Обязательный параметр. Тип настройки. Допустимые значения: int или str. - -> `level`: "" - -Необязательный параметр. Уровень протокола, определяющий область действия. По умолчанию: 6 (TCP). - -> `opt`: "" - -Название опции, которую нужно установить. Используется десятичное представление (в примере, значение TCP_CONGESTION, определенное как 0xd, преобразуется в десятичное 13). - -> `value`: "" - -Значение, которое нужно установить для опции. В примере устанавливается значение bbr. - -Если `type` указан как int, значение должно быть десятичным числом. - -> `happyEyeballs`: [HappyEyeballsObject](#happyeyeballsobject) - -Реализация Happy Eyeballs (RFC-8305), применима только для TCP. Когда целью является домен, выполняется «гонка» подключений к полученным IP-адресам, и выбирается первый успешный результат. Работает только в том случае, если `Sockopt.domainStrategy` установлен в значение, отличное от `AsIs`. - -Внимание: `UseIPv4v6` / `ForceIPv4v6` сокращают список доступных IP только до IPv4; запрос IPv6 выполняется только в случае сбоя (fallback). Такое использование не рекомендуется. Рекомендуется использовать `UseIP` / `ForceIP` в сочетании с `HappyEyeballs.interleave`. - -::: warning -При использовании этой функции не используйте `domainStrategy` для исходящего соединения `Freedom`, так как это приведет к тому, что `Sockopt` будет видеть только конечный, уже выбранный IP-адрес. -::: - -#### HappyEyeballsObject - -```json -"happyEyeballs": { - "tryDelayMs": 250, - "prioritizeIPv6": false, - "interleave": 1, - "maxConcurrentTry": 4 -} -``` - -> `tryDelayMs`: number - -Интервал времени между каждым запросом "гонки", в миллисекундах. По умолчанию 0 (что означает, что функция отключена), рекомендуемое значение — 250. - -> `prioritizeIPv6`: bool - -Тип первого IP-адреса при сортировке IP-адресов. По умолчанию `false` (то есть IPv4 будет первым). - -> `interleave`: number - -"First Address Family count" из RFC-8305, значение по умолчанию — 1. Этот параметр определяет чередование при сортировке IP-адресов разных версий. - -Например, очередь IP-адресов для набора номера будет отсортирована как 46464646 (при значении 1) или 44664466 (при значении 2) (где 6 — это IPv6-адрес, а 4 — IPv4-адрес). - -> `maxConcurrentTry`: number - -Максимальное количество одновременных попыток. Используется для предотвращения ситуации, когда ядро создает большое количество соединений, если разрешено много IP-адресов и ни одно из соединений не увенчалось успехом. По умолчанию 4, установка значения 0 отключает happyEyeballs. - -### FinalMaskObject - -FinalMask применяет последний слой маскировки к трафику после того, как ядро завершит обработку шифрования транспортного уровня, включая TLS/REALITY. - -```json -{ - "tcp": [ - { - "type": "", - "settings": {} - } - ], - "udp": [ - { - "type": "", - "settings": {} - } - ], - "quicParams": { - "congestion": "force-brutal", - "debug": false, - "brutalUp": "60 mbps", - "brutalDown": 0, - "udpHop": { - "ports": "20000-50000", - "interval": "5-10" - }, - "initStreamReceiveWindow": 8388608, - "maxStreamReceiveWindow": 8388608, - "initConnectionReceiveWindow": 20971520, - "maxConnectionReceiveWindow": 20971520, - "maxIdleTimeout": 30, - "keepAlivePeriod": 0, - "disablePathMTUDiscovery": false, - "maxIncomingStreams": 1024 - } -} -``` - -> `tcp[n].type`: header-custom | fragment | sudoku - -Первый элемент в массиве — это самый внешний камуфляж. - -Используется совместно с транспортными уровнями raw | httpupgarde | websocket | gRPC | xhttp. - -`header-custom`: - -`fragment`: - -`sudoku`: - -> `tcp[n].settings`: header-custom | fragment | sudoku - -#### header-custom - -```json -{ - "clients": [ - [ - { - "delay": 0, - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ] - ], - "servers": [ - [ - { - "delay": 0, - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ] - ], - "errors": [ - [ - { - "delay": 0, - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ] - ] -} -``` - -`clients[n][m].delay`: Единица измерения — миллисекунды; значение 0 указывает на то, что пакет ранее был отправлен фрагментарно. - -`clients[n][m].rand`: Добавляет заданную длину случайных байтов, что конфликтует с функцией `packet`. - -`clients[n][m].randRange`: Диапазон случайных байтов, по умолчанию 0-255. - -`clients[n][m].type`: Тип `packet` может быть `array | str | hex | base64`, по умолчанию используется `array`. - -`clients[n][m].packet`: Добавление фиксированных данных конфликтует с `rand`. - -#### fragment - -```json -{ - "packets": "tlshello", - "length": "100-200", - "delay": "10-20", - "maxSplit": "3-6" -} -``` - -#### sudoku - -```json -{ - "password": "", - "ascii": "", - - "customTable": "", // custom_table в официальной документации - "customTables": [""], // custom_tables в официальной документации - - "paddingMin": 0, // padding_min в официальной документации - "paddingMax": 0 // padding_max в официальной документации -} -``` - -См. [официальную документацию](https://github.com/SUDOKU-ASCII/sudoku/blob/main/configs/README.md) для описания полей. - -> `udp[n].type`: header-custom | header-dns | header-dtls | header-srtp | header-utp | header-wechat | header-wireguard | mkcp-original | mkcp-aes128gcm | noise | salamander | sudoku | xdns | xicmp - -Первый элемент в массиве — это самый внешний камуфляж. - -Используется совместно с транспортными слоями raw udp | kcp | hysteria | xhttp h3. - -`header-custom`: Всегда объединяйте пакеты данных в заголовок пакета. - -`header-dns`: DNS-маскировка оригинального mKCP. Некоторые кампусные сети разрешают DNS-запросы без входа; добавляет DNS-заголовок к KCP. - -`header-dtls`: DTLS-маскировка оригинального mKCP. Маскирует как пакеты DTLS 1.2. Без дополнительных настроек. - -`header-srtp`: SRTP-маскировка оригинального mKCP. Маскирует как пакеты SRTP, будет распознаваться как данные видеозвонков (например, FaceTime). Без дополнительных настроек. - -`header-utp`: Маскировка uTP оригинального mKCP. Маскирует как uTP-пакеты, будет распознаваться как данные загрузок BT. Без дополнительных настроек. - -`header-wechat`: Маскировка под WeChat Video оригинального mKCP. Маскирует как данные видеозвонков WeChat. Без дополнительных настроек. - -`header-wireguard`: WireGuard-маскировка оригинального mKCP. Маскирует как пакеты WireGuard. (Не настоящий протокол WireGuard) Без дополнительных настроек. - -`mkcp-original`: Простая обфускация, которая раньше применялась в mKCP по умолчанию; возможно, вам понадобится настроить её для подключения к старым серверам mKCP. Без дополнительных настроек. - -`mkcp-aes128gcm`: Соответствует функции `seed` оригинального mKCP. Использует AES-128-GCM для обфускации. - -`noise`: Перед передачей данных отправляется шум. - -`salamander`: Обфускация Salamander (из Hysteria2). - -`sudoku`: - -`xdns`: использующая DNS-запросы для передачи данных (похоже на DNSTT). Она выполняет стандартные запросы DNS TXT для передачи полезной нагрузки. - -Из-за технических ограничений предоставляемый MTU очень мал, использование QUIC невозможно, рекомендуется использовать в паре с mKCP. Рекомендуемые значения MTU: клиент — 130, сервер — 900. - -`domain` — домен, используемый для запросов. - -Поскольку выполняемые запросы являются стандартными, они могут пересылаться через любой UDP DNS-сервер, хотя эффективность может быть крайне низкой. - -Чтобы использовать эту функцию, сервер должен слушать порт 53, затем протокол прокси должен указывать цель на DNS-сервер (например, 8.8.8.8:53), и вы должны владеть доменом `domain` и направить его NS-запись на сервер. - -Например, если вы являетесь владельцем example.com, вы можете установить запись A для a.example.com, указывающую на IP-адрес, установить запись NS для t.example.com, указывающую на t.example.com, и в конечном итоге использовать t.example.com. Запись A не может быть поддоменом записи NS. - -`xicmp`: Для этого требуются как минимум права доступа `CAP_NET_RAW`, и он должен находиться на самом внешнем уровне, то есть первым элементом массива. Его нельзя использовать с `udpHop` или `dialerProxy`. - -> `udp[n].settings`: header-custom | header-dns | mkcp-aes128gcm | noise | salamander | sudoku | xdns | xicmp - -#### header-custom - -```json -{ - "client": [ - { - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ], - "server": [ - { - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ] -} -``` - -`client[n].rand`: Добавляет заданную длину случайных байтов, что конфликтует с функцией `packet`. - -`client[n].randRange`: Диапазон случайных байтов, по умолчанию 0-255. - -`client[n].type`: Тип `packet` может быть `array | str | hex | base64`, по умолчанию используется `array`. - -`client[n].packet`: Добавление фиксированных данных конфликтует с `rand`. - -#### header-dns - -```json -{ - "domain": "www.example.com" -} -``` - -#### mkcp-aes128gcm - -```json -{ - "password": "your-password" -} -``` - -#### noise - -```json -{ - "reset": 0, - "noise": [ - { - "rand": "1-8192", - "randRange": "0-255", - "type": "", - "packet": [], - "delay": "10-20" - } - ] -} -``` - -`noise[n].rand`: Добавляет случайные или заданные по длине случайные байты, что конфликтует с `packet`. - -`noise[n].randRange`: Диапазон случайных байтов, по умолчанию 0-255. - -`noise[n].type`: Тип `packet` может быть `array | str | hex | base64`, по умолчанию используется `array`. - -`noise[n].packet`: Добавление фиксированных данных конфликтует с `rand`. - -`noise[n].delay`: Единица измерения — миллисекунды. После отправки одного шумового сигнала перед отправкой следующего проходит заданное время задержки. - -#### salamander - -```json -{ - "password": "your-password" -} -``` - -#### sudoku - -```json -{ - "password": "", - "ascii": "", - - "customTable": "", - "customTables": [""], - - "paddingMin": 0, - "paddingMax": 0 -} -``` - -Аналогично версии TCP. - -#### xdns - -```json -{ - "domain": "www.example.com" -} -``` - -#### xicmp - -```json -{ - "listenIp": "0.0.0.0", - "id": 0 -} -``` - -`listenIp`: IP-адрес, на котором будет осуществляться прослушивание. - -`id`: Если под одним и тем же IP-адресом находится несколько клиентов, рекомендуется установить значение 0 на сервере. - -> `quicParams`: [quicParamsObject](#quicParams) - -#### quicParams - -```json -{ - "congestion": "force-brutal", - "debug": false, - "brutalUp": "60 mbps", - "brutalDown": 0, - "udpHop": { - "ports": "20000-50000", - "interval": "5-10" - }, - "initStreamReceiveWindow": 8388608, - "maxStreamReceiveWindow": 8388608, - "initConnectionReceiveWindow": 20971520, - "maxConnectionReceiveWindow": 20971520, - "maxIdleTimeout": 30, - "keepAlivePeriod": 0, - "disablePathMTUDiscovery": false, - "maxIncomingStreams": 1024 -} -``` - -Используется для настройки параметров QUIC для XHTTP H3 и Hysteria. - -> `congestion`: reno | bbr | brutal | force-brutal - -Алгоритм управления перегрузкой. Hysteria по умолчанию использует `brutal`, XHTTP H3 по умолчанию использует `bbr`. - -`reno`/`bbr`: Известные алгоритмы. - -`brutal`: Согласовывает фиксированную скорость отправки пакетов с другой стороной или переключается на BBR. Поддерживается только в транспорте Hysteria (поскольку XHTTP не имеет механизма согласования). - -`force-brutal`: Аналогично `brutal`, но принудительно использует фиксированную скорость отправки `brutalUp` для исходящего трафика, игнорируя согласование с другой стороной. - -> `debug`: false | true - -Включить логирование в режиме bbr/brutal congestal control. - -> `brutalUp`: string - -> `brutalDown`: string - -Ограничение скорости загрузки/скачивания (upload/download). Значение по умолчанию 0. - -Формат удобен для пользователя, поддерживает различные распространенные записи бит в секунду, включая `1000000`, `100kb`, `20 mb`, `100 mbps`, `1g`, `1 tbps` и т.д. Регистр не важен, пробелы между единицами необязательны. Без единиц измерения по умолчанию используется bps (бит в секунду), значение не может быть ниже 65535 bps. - -Поведение согласования соответствует Hysteria brutal: - -Значение на сервере ограничивает максимальную скорость режима Brutal, которую может выбрать клиент; 0 означает отсутствие ограничений для клиента. - -Если на клиенте 0, используется режим BBR; если не 0, используется режим Brutal, который будет ограничен сервером. - -Обратите внимание на относительность: загрузка (upload) сервера — это скачивание (download) клиента, а скачивание (download) сервера — это загрузка (upload) клиента. - -> `udpHop`: {"ports": string, "interval": number} - -`ports` — это диапазон портов для скачков. Может быть строкой с числом, например `"1234"`; или числовым диапазоном, например `"1145-1919"`, что означает 775 портов от 1145 до 1919. Можно использовать запятые для разделения, например `11,13,15-17` означает 5 портов: 11, 13, и с 15 по 17. - -`interval` — это интервал переключения портов в секундах. Минимальное значение — 5, значение по умолчанию — 30 секунд. - -> `initStreamReceiveWindow`: number - -> `maxStreamReceiveWindow`: number - -> `initConnectionReceiveWindow`: number - -> `maxConnectionReceiveWindow`: number - -Эти четыре параметра являются конкретными параметрами окна QUIC. **Не рекомендуется изменять эти значения, если вы не понимаете полностью, что делаете**. Если вы все же меняете их, рекомендуется сохранять соотношение окна приема потока к окну приема соединения как 2:5. - -> `maxIdleTimeout`: number - -Максимальное время ожидания простоя (в секундах). Через какое время сервер закроет соединение, если не получит никаких данных от клиента. Диапазон 4~120 секунд, по умолчанию 30 секунд. - -> `keepAlivePeriod`: number - -Интервал QUIC KeepAlive (в секундах). Диапазон 2~60 секунд. По умолчанию отключено. - -> `disablePathMTUDiscovery`: bool - -Отключить ли обнаружение Path MTU Discovery. - -В других реализациях команды !linux && !windows && !darwin OS принудительно отключены, тогда как в xray это не является обязательным. Если ваша ОС не (linux || windows || darwin), вам может потребоваться отключить их вручную. - -> `maxIncomingStreams`: number - -Если заданы параметры на стороне сервера, их количество не должно быть меньше 8. +Настройки низкоуровневого сетевого поведения. diff --git a/docs/ru/config/transports/finalmask.md b/docs/ru/config/transports/finalmask.md new file mode 100644 index 00000000..ee3b31a4 --- /dev/null +++ b/docs/ru/config/transports/finalmask.md @@ -0,0 +1,404 @@ +# FinalMask + +FinalMask добавляет последний слой маскировки после того, как ядро уже обработало защиту транспорта, включая TLS и REALITY. + +Он используется для разных вариантов TCP- и UDP-маскировки, а также для настройки параметров QUIC. + +## FinalMaskObject + +`FinalMaskObject` соответствует полю `finalmask` в [`StreamSettingsObject`](../transport.md#streamsettingsobject). + +```json +{ + // пример для outbound, аналогично применимо к inbound + "outbounds": [ + { + // ... + "streamSettings": { + "finalmask": { + // [!code focus:30] + "tcp": [ + { + "type": "", + "settings": {} + } + ], + "udp": [ + { + "type": "", + "settings": {} + } + ], + "quicParams": { + "congestion": "force-brutal", + "debug": false, + "brutalUp": "60 mbps", + "brutalDown": 0, + "udpHop": { + "ports": "20000-50000", + "interval": "5-10" + }, + "initStreamReceiveWindow": 8388608, + "maxStreamReceiveWindow": 8388608, + "initConnectionReceiveWindow": 20971520, + "maxConnectionReceiveWindow": 20971520, + "maxIdleTimeout": 30, + "keepAlivePeriod": 0, + "disablePathMTUDiscovery": false, + "maxIncomingStreams": 1024 + } + } + } + } + ] +} +``` + +> `tcp[n].type`: header-custom | fragment | sudoku + +Первый элемент массива является самым внешним слоем маскировки. + +Используется вместе с `raw`, `httpupgrade`, `websocket`, `grpc` и `xhttp`. + +`header-custom`: + +`fragment`: + +`sudoku`: + +> `tcp[n].settings`: header-custom | fragment | sudoku + +### header-custom + +```json +{ + "clients": [ + [ + { + "delay": 0, + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] + ], + "servers": [ + [ + { + "delay": 0, + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] + ], + "errors": [ + [ + { + "delay": 0, + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] + ] +} +``` + +`clients[n][m].delay`: задержка в миллисекундах. Если значение равно `0`, данные отправляются слитно с предыдущим пакетом. + +`clients[n][m].rand`: добавить заданное число случайных байт. Несовместимо с `packet`. + +`clients[n][m].randRange`: диапазон значений случайных байт. По умолчанию `0-255`. + +`clients[n][m].type`: тип `packet`. Поддерживаются `array`, `str`, `hex` и `base64`. Значение по умолчанию — `array`. + +`clients[n][m].packet`: добавить фиксированные данные. Несовместимо с `rand`. + +### fragment + +```json +{ + "packets": "tlshello", + "length": "100-200", + "delay": "10-20", + "maxSplit": "3-6" +} +``` + +### sudoku + +```json +{ + "password": "", + "ascii": "", + + "customTable": "", // в upstream документации поле называется custom_table + "customTables": [""], // в upstream документации поле называется custom_tables + + "paddingMin": 0, // в upstream документации поле называется padding_min + "paddingMax": 0 // в upstream документации поле называется padding_max +} +``` + +Смысл этих полей описан в [upstream-документации](https://github.com/SUDOKU-ASCII/sudoku/blob/main/configs/README.md). + +> `udp[n].type`: header-custom | header-dns | header-dtls | header-srtp | header-utp | header-wechat | header-wireguard | mkcp-original | mkcp-aes128gcm | noise | salamander | sudoku | xdns | xicmp + +Первый элемент массива является самым внешним слоем маскировки. + +Используется вместе с `raw` UDP, `kcp`, `hysteria` и `xhttp` H3. + +`header-custom`: всегда добавляется как объединенный заголовок пакета. + +`header-dns`: старая DNS-маскировка mKCP. В некоторых кампусных сетях DNS-запросы разрешены до авторизации, поэтому этот режим добавляет DNS-заголовок к KCP. + +`header-dtls`: старая DTLS-маскировка mKCP. Имитирует пакеты DTLS 1.2. Дополнительных настроек нет. + +`header-srtp`: старая SRTP-маскировка mKCP. Похожа на трафик видеозвонков вроде FaceTime. Дополнительных настроек нет. + +`header-utp`: старая uTP-маскировка mKCP. Похожа на BitTorrent-трафик. Дополнительных настроек нет. + +`header-wechat`: старая маскировка под WeChat Video из mKCP. Дополнительных настроек нет. + +`header-wireguard`: старая WireGuard-маскировка mKCP. Выглядит как пакеты WireGuard, хотя реальным протоколом WireGuard не является. Дополнительных настроек нет. + +`mkcp-original`: простая обфускация, которая раньше была значением по умолчанию в mKCP. Может понадобиться для подключения к старым mKCP-серверам. Дополнительных настроек нет. + +`mkcp-aes128gcm`: старый режим `seed` в mKCP. Использует AES-128-GCM для обфускации. + +`noise`: шум, отправляемый перед реальной полезной нагрузкой. + +`salamander`: обфускация Salamander из Hysteria2. + +`sudoku`: + +`xdns`: передает данные через DNS-запросы по схеме, похожей на DNSTT. Для переноса полезной нагрузки выполняются обычные DNS TXT-запросы. + +Из-за технических ограничений эффективный MTU очень маленький, поэтому QUIC здесь непрактичен. Рекомендуется сочетать режим с mKCP. Рекомендуемые MTU — 130 на клиенте и 900 на сервере. + +Так как запросы являются стандартными DNS-запросами, их может пересылать любой UDP DNS-сервер, хотя эффективность будет низкой. + +Для использования этого режима сервер должен слушать порт 53, прокси-протокол должен указывать целью DNS-сервер вроде `8.8.8.8:53`, а вы должны владеть доменом `domain` и направить его NS-запись на сервер. + +Например, если у вас есть `example.com`, можно создать A-запись вроде `a.example.com`, указывающую на IP сервера, затем NS-запись вроде `t.example.com`, указывающую на `t.example.com`, и использовать `t.example.com` как рабочий домен. A-запись не должна быть поддоменом NS-записи. + +`xicmp`: требует как минимум `CAP_NET_RAW`, должен быть самым внешним слоем, то есть первым элементом массива, и несовместим с `udpHop` и `dialerProxy`. + +> `udp[n].settings`: header-custom | header-dns | mkcp-aes128gcm | noise | salamander | sudoku | xdns | xicmp + +### header-custom + +```json +{ + "client": [ + { + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ], + "server": [ + { + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] +} +``` + +`client[n].rand`: добавить заданное число случайных байт. Несовместимо с `packet`. + +`client[n].randRange`: диапазон значений случайных байт. По умолчанию `0-255`. + +`client[n].type`: тип `packet`. Поддерживаются `array`, `str`, `hex` и `base64`. Значение по умолчанию — `array`. + +`client[n].packet`: добавить фиксированные данные. Несовместимо с `rand`. + +### header-dns + +```json +{ + "domain": "www.example.com" +} +``` + +### mkcp-aes128gcm + +```json +{ + "password": "your-password" +} +``` + +### noise + +```json +{ + "reset": 0, + "noise": [ + { + "rand": "1-8192", + "randRange": "0-255", + "type": "", + "packet": [], + "delay": "10-20" + } + ] +} +``` + +`noise[n].rand`: добавить случайные байты или случайное число байт. Несовместимо с `packet`. + +`noise[n].randRange`: диапазон значений случайных байт. По умолчанию `0-255`. + +`noise[n].type`: тип `packet`. Поддерживаются `array`, `str`, `hex` и `base64`. Значение по умолчанию — `array`. + +`noise[n].packet`: добавить фиксированные данные. Несовместимо с `rand`. + +`noise[n].delay`: задержка в миллисекундах. После отправки одного элемента шума Xray ждет указанное время перед следующим. + +### salamander + +```json +{ + "password": "your-password" +} +``` + +### sudoku + +```json +{ + "password": "", + "ascii": "", + + "customTable": "", + "customTables": [""], + + "paddingMin": 0, + "paddingMax": 0 +} +``` + +Здесь действуют те же значения, что и в TCP-версии. + +### xdns + +```json +{ + "domain": "www.example.com" +} +``` + +### xicmp + +```json +{ + "listenIp": "0.0.0.0", + "id": 0 +} +``` + +`listenIp`: IP-адрес, на котором выполняется прослушивание. + +`id`: если несколько клиентов используют один IP, серверу рекомендуется оставлять здесь `0`. + +> `quicParams`: [quicParamsObject](#quicParams) + +### quicParams + +```json +{ + "congestion": "force-brutal", + "debug": false, + "brutalUp": "60 mbps", + "brutalDown": 0, + "udpHop": { + "ports": "20000-50000", + "interval": "5-10" + }, + "initStreamReceiveWindow": 8388608, + "maxStreamReceiveWindow": 8388608, + "initConnectionReceiveWindow": 20971520, + "maxConnectionReceiveWindow": 20971520, + "maxIdleTimeout": 30, + "keepAlivePeriod": 0, + "disablePathMTUDiscovery": false, + "maxIncomingStreams": 1024 +} +``` + +Используется для настройки параметров QUIC в XHTTP H3 и Hysteria. + +> `congestion`: reno | bbr | brutal | force-brutal + +Алгоритм управления перегрузкой. В Hysteria по умолчанию используется `brutal`, в XHTTP H3 — `bbr`. + +`reno` и `bbr` — обычные известные алгоритмы. + +`brutal` согласует фиксированную скорость отправки пакетов с другой стороной или откатывается к BBR. Поддерживается только в Hysteria, потому что у XHTTP нет механизма согласования. + +`force-brutal` работает так же, как `brutal`, но принудительно использует фиксированную исходящую скорость из `brutalUp`, игнорируя переговоры с другой стороной. + +> `debug`: false | true + +Включает логирование для реализаций `bbr` и `brutal`. + +> `brutalUp`: string + +> `brutalDown`: string + +Ограничения исходящей и входящей скорости. Значение по умолчанию — `0`. + +Формат дружелюбный: поддерживаются записи вроде `1000000`, `100kb`, `20 mb`, `100 mbps`, `1g`, `1 tbps`. Регистр неважен, пробелы необязательны. Если единицы измерения не указаны, используется `bps`. Значение не может быть ниже 65535 bps. + +Переговоры работают так же, как у Hysteria Brutal: + +Серверное значение ограничивает максимальную скорость режима Brutal, которую клиент может выбрать. `0` означает отсутствие ограничения со стороны сервера. + +Если на клиенте указано `0`, используется режим BBR. Если значение не нулевое, используется Brutal-режим, но он все равно ограничивается серверной стороной. + +Не забывайте про относительность направлений: серверный upload — это клиентский download, а серверный download — это клиентский upload. + +> `udpHop`: {"ports": string, "interval": number} + +Настройка прыжков по UDP-портам. + +`ports` задает диапазон портов. Это может быть одиночная строка вроде `"1234"`, диапазон вроде `"1145-1919"` или несколько сегментов через запятую, например `11,13,15-17`. + +`interval` — интервал переключения портов в секундах. Минимум — 5, значение по умолчанию — 30 секунд. + +> `initStreamReceiveWindow`: number + +> `maxStreamReceiveWindow`: number + +> `initConnectionReceiveWindow`: number + +> `maxConnectionReceiveWindow`: number + +Это низкоуровневые параметры QUIC-окон. **Не меняйте их, если не понимаете точно, что делаете.** Если менять их все же нужно, рекомендуется сохранять соотношение окна потока и окна соединения на уровне 2:5. + +> `maxIdleTimeout`: number + +Максимальный таймаут простоя в секундах. Это время, после которого сервер закроет соединение, если не получает данные от клиента. Допустимый диапазон — от 4 до 120 секунд. Значение по умолчанию — 30 секунд. + +> `keepAlivePeriod`: number + +Интервал QUIC KeepAlive в секундах. Допустимый диапазон — от 2 до 60 секунд. По умолчанию выключено. + +> `disablePathMTUDiscovery`: bool + +Отключать ли Path MTU Discovery. + +Во многих других реализациях на системах вне Linux, Windows и Darwin этот режим отключается принудительно, тогда как Xray не делает этого автоматически. Если ваша ОС не входит в эти три, возможно, придется отключить его вручную. + +> `maxIncomingStreams`: number + +Только для сервера. Если параметр задан, он не должен быть меньше `8`. diff --git a/docs/ru/config/transports/httpupgrade.md b/docs/ru/config/transports/httpupgrade.md index a1509b27..d4e03638 100644 --- a/docs/ru/config/transports/httpupgrade.md +++ b/docs/ru/config/transports/httpupgrade.md @@ -8,9 +8,9 @@ **Рекомендуется переключиться на [XHTTP](https://github.com/XTLS/Xray-core/discussions/4113#discussioncomment-11468947), чтобы избежать значительных характеристик трафика, таких как HTTPUpgrade «ALPN is http/1.1».** ::: -## HttpUpgradeObject +## HTTPUpgradeObject -`HttpUpgradeObject` соответствует элементу `httpupgradeSettings` в [`StreamSettingsObject`](../transport.md#streamsettingsobject). +`HTTPUpgradeObject` соответствует элементу `httpupgradeSettings` в [`StreamSettingsObject`](../transport.md#streamsettingsobject). ```json { diff --git a/docs/ru/config/transports/index.md b/docs/ru/config/transports/index.md index 09dd2a83..117c67fc 100644 --- a/docs/ru/config/transports/index.md +++ b/docs/ru/config/transports/index.md @@ -1,6 +1,8 @@ -# Список транспортных слоев Xray +# Список конфигурации транспорта Xray -Xray поддерживает следующие транспортные слои: +Xray поддерживает следующие категории конфигурации транспорта: + +## Способы передачи - [RAW](raw.md) - [XHTTP: Beyond REALITY](xhttp.md) @@ -9,3 +11,13 @@ Xray поддерживает следующие транспортные сло - [WebSocket](websocket.md) - [HTTPUpgrade](httpupgrade.md) - [Hysteria](hysteria.md) + +## Безопасность транспорта + +- [REALITY](reality.md) +- [TLS](tls.md) + +## Дополнительные настройки + +- [FinalMask](finalmask.md) +- [Sockopt](sockopt.md) diff --git a/docs/ru/config/transports/mkcp.md b/docs/ru/config/transports/mkcp.md index bc7f3dd2..2fbaebb2 100644 --- a/docs/ru/config/transports/mkcp.md +++ b/docs/ru/config/transports/mkcp.md @@ -37,7 +37,7 @@ mKCP жертвует пропускной способностью ради у ``` ::: tip -Поля `header` и `seed` были удалены, пожалуйста, используйте [FinalMask](../transport.md#finalmaskobject) для настройки. +Поля `header` и `seed` были удалены, пожалуйста, используйте [FinalMask](./finalmask.md#finalmaskobject) для настройки. Также была удалена стандартная обфускация mKCP; для подключения к старым версиям серверов необходимо настроить `mkcp-original` в FinalMask. ::: diff --git a/docs/ru/config/transports/reality.md b/docs/ru/config/transports/reality.md new file mode 100644 index 00000000..982947e7 --- /dev/null +++ b/docs/ru/config/transports/reality.md @@ -0,0 +1,203 @@ +# REALITY + +REALITY — это модификация TLS, которая использует внешний вид и характеристики рукопожатия целевого сайта как маскировку. + +:::: tip +REALITY сейчас является одной из самых сильных схем защиты транспорта, а снаружи такой трафик выглядит как обычный веб-трафик.
+Включение REALITY вместе с подходящим режимом управления потоком XTLS Vision может дать прирост производительности в несколько раз или даже больше чем в десять раз. + +::: details Для разработчиков +REALITY модифицирует только TLS. На стороне клиента в основном требуется легкая обработка полностью случайного session ID и пользовательской проверки сертификата, поэтому теоретически оно совместимо с большинством TLS-комбинаций. +Подробнее см. в [проекте REALITY](https://github.com/XTLS/REALITY). +::: +:::: + +## RealityObject + +`RealityObject` соответствует полю `realitySettings` в [`StreamSettingsObject`](../transport.md#streamsettingsobject). + +```json +{ + // пример для outbound, аналогично применимо к inbound + "outbounds": [ + { + // ... + "streamSettings": { + "security": "reality", + "realitySettings": { + // [!code focus:28] + // Входящие настройки (сервер) + "show": false, + "target": "example.com:443", + "xver": 0, + "serverNames": ["example.com", "www.example.com"], + "privateKey": "", + "minClientVer": "", + "maxClientVer": "", + "maxTimeDiff": 0, + "shortIds": ["", "0123456789abcdef"], + "mldsa65Seed": "", + "limitFallbackUpload": { + "afterBytes": 0, + "bytesPerSec": 0, + "burstBytesPerSec": 0 + }, + "limitFallbackDownload": { + "afterBytes": 0, + "bytesPerSec": 0, + "burstBytesPerSec": 0 + }, + // Исходящие настройки (клиент) + "serverName": "", + "fingerprint": "chrome", + "password": "", + "shortId": "", + "mldsa65Verify": "", + "spiderX": "" + } + } + } + ] +} +``` + +> `show`: true | false + +Если значение равно `true`, выводится отладочная информация. + +::: tip +Ниже идут параметры **inbound** (**серверной стороны**). +::: + +> `target`: string + +Обязательный параметр. Формат такой же, как у [dest](../features/fallback.md#fallbackobject) в fallback VLESS. + +Старое имя поля — `dest`. В текущих версиях оба поля являются алиасами. + +Если `target` поддерживает постквантовый алгоритм обмена ключами X25519MLKEM768, клиент REALITY также автоматически будет использовать его при согласовании ключей. Проверить поддержку можно командой `xray tls ping cloudflare.com`, подставив вместо домена ваш `target` и при необходимости порт. + +Ядро отличает серверную и клиентскую конфигурацию по наличию этого поля. Не заполняйте его на клиенте, иначе определение роли будет неправильным. + +::: warning +Для маскировки Xray **напрямую пересылает** трафик, который не прошел проверку, то есть не является корректным REALITY-запросом, на `target`. +Если IP-адрес `target` особый, например это сайт за Cloudflare CDN, ваш сервер фактически превращается в порт-форвардер для Cloudflare и после сканирования может использоваться посторонними. + +Чтобы этого избежать, можно поставить перед Xray Nginx или другой фильтр по SNI. +Также можно рассмотреть `limitFallbackUpload` и `limitFallbackDownload`. +::: + +> `xver`: number + +Необязательный параметр. Формат такой же, как у [xver](../features/fallback.md#fallbackobject) в fallback VLESS. + +> `serverNames`: [string] + +Обязательный параметр. Список допустимых для клиента значений `serverName`. Подстановочный символ `*` не поддерживается. + +Обычно достаточно держать этот список согласованным с `target`. На практике допустимы любые SNI, которые принимает сервер в соответствии с поведением `target`, обычно ориентируясь на [SAN](https://ru.wikipedia.org/wiki/Subject_Alternative_Name) сертификата, который возвращает целевой сайт. + +В списке может присутствовать пустая строка `""`, что означает разрешение соединений без SNI. Для этого не требуется IP-сертификат у `target`; достаточно, чтобы он не отклонял Client Hello без SNI. При использовании этого режима клиентский `serverName` не должен быть пустым, вместо этого нужно указать любой корректный IP-адрес как заглушку. + +Поведение сервера на запросы без SNI можно посмотреть через `xray tls ping`. + +> `privateKey`: string + +Обязательный параметр. Генерируется командой `./xray x25519`. + +> `minClientVer`: string + +Необязательный параметр. Минимальная версия клиента Xray в формате `x.y.z`. + +> `maxClientVer`: string + +Необязательный параметр. Максимальная версия клиента Xray в формате `x.y.z`. + +> `maxTimeDiff`: number + +Необязательный параметр. Максимально допустимая разница времени в миллисекундах. + +> `shortIds`: [string] + +Обязательный параметр. Список допустимых `shortId`, которыми можно различать клиентов. + +Требования к формату описаны у поля `shortId`. + +Если список содержит пустую строку, клиентский `shortId` тоже может быть пустым. + +> `mldsa65Seed`: string + +Только для сервера. Приватный ключ, который используется для добавления дополнительной постквантовой подписи к сертификату, отправляемому клиенту REALITY, по алгоритму ML-DSA-65. Если когда-нибудь появится квантовый компьютер, способный ломать x25519, утечка `password` может позволить MITM-атаку; эта функция предназначена для защиты от такого будущего риска. + +Сгенерировать пару ключей можно командой `xray mldsa65`. После настройки приватного ключа на сервере подпись добавляется только как расширение сертификата и не влияет на старых клиентов или клиентов, которые не включали эту возможность. + +После включения этой функции сертификат, который возвращает `target`, **должен** быть длиннее 3500 байт, потому что постквантовая подпись делает временный сертификат REALITY больше. Чтобы это само не превратилось в отпечаток, сертификат `target` тоже должен быть большим. Проверить это можно через `xray tls ping example.com`. Для полной постквантовой устойчивости `target` также должен поддерживать X25519MLKEM768. + +> `limitFallbackUpload` / `limitFallbackDownload` + +::: warning +Лучшая практика для REALITY по-прежнему состоит в том, чтобы брать сертификаты у ресурса в том же ASN, поэтому в большинстве случаев эта функция вам не понадобится. Имеет смысл рассматривать ее только если вы вынуждены использовать сертификат чего-то вроде бесплатного CDN Cloudflare и хотите не допустить превращения сервера в ускоритель для посторонних. + +Само ограничение fallback-трафика тоже является отпечатком, поэтому не рекомендуется. Если вы делаете панель или one-click скрипт, такие параметры стоит рандомизировать. +::: + +::: tip +`limitFallbackUpload` и `limitFallbackDownload` необязательны и позволяют ограничивать скорость fallback-соединений, не прошедших проверку. Значение `bytesPerSec` по умолчанию равно `0`, то есть ограничение выключено. + +Механизм такой: для каждого непрошедшего проверку fallback-соединения ограничение включается после передачи `afterBytes` байт. +Используется алгоритм token bucket. Размер корзины равен `burstBytesPerSec`. Каждый переданный байт тратит один токен. Изначально корзина заполнена полностью. +Каждую секунду в нее добавляется `bytesPerSec` токенов, пока она снова не заполнится. + +Пример: `afterBytes=10485760`, `burstBytesPerSec=5242880`, `bytesPerSec=1048576` означает ограничение до 1 МБ/с после передачи 15 МБ. Если передача приостановится, через 5 секунд можно снова кратковременно выйти на 5 МБ/с. + +Если `afterBytes` и `burstBytesPerSec` слишком большие, практического эффекта почти не будет. Если `bytesPerSec` и `burstBytesPerSec` слишком маленькие, поведение становится слишком легко отличимым. +Подбирать эти параметры нужно с учетом размера ресурсов у сайта, чей сертификат используется. Если всплески не нужны, установите `burstBytesPerSec` в `0`. +::: + +> `afterBytes`: number + +Необязательный параметр. Ограничение скорости для fallback-соединения REALITY начинает действовать только после передачи указанного числа байт. По умолчанию `0`. + +> `bytesPerSec`: number + +Необязательный параметр. Базовая скорость ограничения для fallback-соединения REALITY, в байтах в секунду. По умолчанию `0`, то есть отключено. + +> `burstBytesPerSec`: number + +Необязательный параметр. Пиковая скорость ограничения для fallback-соединения REALITY, в байтах в секунду. Работает, когда значение больше `bytesPerSec`. + +::: tip +Ниже идут параметры **outbound** (**клиентской стороны**). +::: + +> `serverName`: string + +Одно из серверных значений `serverNames`. + +Клиент также может указать здесь любой IP-адрес. Тогда Xray отправит Client Hello без SNI. Для этого в серверном `serverNames` должна присутствовать пустая строка `""`. + +> `fingerprint`: string + +Обязательный параметр. Работает так же, как [TLSObject](./tls.md#tlsobject). Значение `unsafe`, отключающее uTLS для обычного TLS, здесь не поддерживается, потому что REALITY опирается на эту библиотеку для управления низкоуровневыми параметрами TLS. + +> `shortId`: string + +Одно из серверных значений `shortIds`. + +Длина составляет 8 байт, то есть до 16 шестнадцатеричных символов в диапазоне `0`-`f`. Поле может быть короче 16 символов, тогда ядро автоматически дополнит его нулями справа, но количество символов обязательно должно быть **четным**, потому что один байт задается двумя hex-символами. + +Например, `aa1234` автоматически превратится в `aa12340000000000`, а `aaa1234` вызовет ошибку. + +Ноль тоже четный, поэтому если в серверном `shortIds` есть пустая строка `""`, клиентское значение тоже может быть пустым. + +> `password`: string + +Обязательный параметр. Публичный ключ, соответствующий приватному ключу сервера. Генерируется командой `./xray x25519 -i "приватный ключ сервера"`. Раньше поле называлось `publicKey`, но было переименовано, чтобы не вводить в заблуждение: формально это действительно x25519 public key, но в модели REALITY он хранится у клиента и не должен восприниматься как что-то публично публикуемое. + +> `mldsa65Verify` + +Необязательный параметр. Публичный ключ для проверки подписи `mldsa65`. Если значение не пустое, Xray использует его для проверки сертификата, полученного от сервера. Подробности см. у `mldsa65Seed`. + +> `spiderX`: string + +Начальный путь и параметры краулера. Рекомендуется использовать разные значения для разных клиентов. diff --git a/docs/ru/config/transports/sockopt.md b/docs/ru/config/transports/sockopt.md new file mode 100644 index 00000000..040c4cd8 --- /dev/null +++ b/docs/ru/config/transports/sockopt.md @@ -0,0 +1,296 @@ +# Sockopt + +Sockopt используется для настройки низкоуровневого сетевого поведения. + +С его помощью можно управлять прозрачным проксированием, стратегией DNS-разрешения и различными параметрами socket. + +## SockoptObject + +`SockoptObject` соответствует полю `sockopt` в [`StreamSettingsObject`](../transport.md#streamsettingsobject). + +```json +{ + // пример для outbound, аналогично применимо к inbound + "outbounds": [ + { + // ... + "streamSettings": { + "sockopt": { + // [!code focus:18] + "mark": 0, + "tcpMaxSeg": 1440, + "tcpFastOpen": false, + "tproxy": "off", + "domainStrategy": "AsIs", + "happyEyeballs": {}, + "dialerProxy": "", + "acceptProxyProtocol": false, + "tcpKeepAliveInterval": 0, + "tcpKeepAliveIdle": 300, + "tcpUserTimeout": 10000, + "tcpcongestion": "bbr", + "interface": "wg0", + "V6Only": false, + "tcpWindowClamp": 600, + "tcpMptcp": false, + "addressPortStrategy": "", + "customSockopt": [] + } + } + } + ] +} +``` + +> `mark`: number + +Целое число. Если значение не равно нулю, исходящие соединения помечаются через `SO_MARK`. + +- Только Linux. +- Требуются права `CAP_NET_ADMIN`. + +> `tcpMaxSeg`: number + +Используется для задания максимального размера сегмента TCP. + +> `tcpFastOpen`: true | false | number + +Включает или отключает [TCP Fast Open](https://ru.wikipedia.org/wiki/TCP_Fast_Open). + +Если указано `true` или положительное число, TFO включается. Если указано `false` или отрицательное число, TFO принудительно отключается. Если поле отсутствует или равно `0`, используется поведение системы по умолчанию. Параметр доступен и для inbound, и для outbound. + +- Работает только на следующих версиях ОС и новее: + - Linux 3.16: требует настройки `net.ipv4.tcp_fastopen`. Это bitmap, где `0x1` разрешает клиентскую сторону, а `0x2` — серверную. По умолчанию используется `0x1`. Если TFO нужно на сервере, задайте `0x3`. + - ~~Windows 10 (1607)~~, но реализация некорректна + - Mac OS 10.11 / iOS 9, требуется проверка + - FreeBSD 10.3 на сервере / 12.0 на клиенте: нужны `net.inet.tcp.fastopen.server_enabled=1` и `net.inet.tcp.fastopen.client_enabled=1`, тоже требуется проверка + +- Для inbound положительное число означает [максимальное число ожидающих TFO-соединений](https://tools.ietf.org/html/rfc7413#section-5.1). **Не все ОС позволяют задавать это здесь**: + - Linux / FreeBSD: положительное число используется как лимит. Максимум — 2147483647. Если задано `true`, используется `256`. В Linux сверху это также ограничивает `net.core.somaxconn`. + - Mac OS: `true` или положительное число лишь включает TFO. Размер очереди задается отдельно через `net.inet.tcp.fastopen_backlog`. + - Windows: `true` или положительное число только включает TFO. + +- Для outbound `true` или положительное число просто означает включение TFO на поддерживаемой ОС. + +> `tproxy`: "redirect" | "tproxy" | "off" + +Включать ли прозрачное проксирование. Только Linux. + +- `"redirect"`: режим Redirect, поддерживает все IPv4/IPv6 TCP-соединения +- `"tproxy"`: режим TProxy, поддерживает все IPv4/IPv6 TCP- и UDP-соединения +- `"off"`: прозрачное проксирование отключено + +Для прозрачного проксирования нужны root или `CAP_NET_ADMIN`. + +::: danger +Если в [Dokodemo-door](../inbounds/tunnel.md) параметр `followRedirect` равен `true`, а `tproxy` в Sockopt пустой, то значение `tproxy` будет автоматически установлено в `"redirect"`. +::: + +> `domainStrategy`: "AsIs"
+> "UseIP" | "UseIPv6v4" | "UseIPv6" | "UseIPv4v6" | "UseIPv4"
+> "ForceIP" | "ForceIPv6v4" | "ForceIPv6" | "ForceIPv4v6" | "ForceIPv4" + +Значение по умолчанию — `"AsIs"`. + +Когда целевой адрес является доменным именем, это поле управляет тем, как outbound будет его разрешать и использовать: + +- При `"AsIs"` Xray никак специально не обрабатывает доменное имя и в конце использует обычный dialer Go. Приоритет фиксирован правилами RFC 6724 и обычно приводит к предпочтению IPv6. +- При любом другом значении Xray использует [встроенный DNS](../dns.md). Если `DNSObject` отсутствует, используется системный DNS. Если есть несколько подходящих IP-адресов, ядро случайным образом выбирает один. +- `"IPv4"` означает попытку использовать только IPv4. `"IPv4v6"` означает использование IPv4 или IPv6, но для dual-stack домена предпочитается IPv4. Аналогично работают и IPv6-first варианты. +- Если во встроенном DNS также задан `"queryStrategy"`, фактическое поведение определяется пересечением двух настроек. Например, `"queryStrategy": "UseIPv4"` вместе с `"domainStrategy": "UseIP"` фактически эквивалентно `"domainStrategy": "UseIPv4"`. +- Варианты `"Use*"` делают fallback к `"AsIs"`, если результат разрешения не соответствует нужному семейству адресов. +- Варианты `"Force*"` завершают соединение ошибкой, если получить нужный тип адреса не удалось. + +::: tip TIP +Если используется `"UseIP"` или `"ForceIP"` и в [OutboundObject](../outbound.md#outboundobject) задан `sendThrough`, ядро автоматически определяет нужное семейство адресов по локальному адресу. Если вручную зафиксировать, например, `UseIPv4`, а `sendThrough` указывает на IPv6-адрес, соединение завершится ошибкой. +::: + +::: danger +Неправильная настройка этой функции может привести к бесконечному циклу. + +Коротко: чтобы подключиться к серверу, нужно дождаться DNS-результата, а чтобы завершить DNS-запрос, нужно подключиться к серверу. + +Подробно: + +1. Есть прокси-сервер `proxy.com` и встроенный DNS в не-Local режиме. +2. Перед подключением к `proxy.com` Xray сначала пытается разрешить `proxy.com` через встроенный DNS. +3. Встроенный DNS устанавливает соединение с `dns.com`, чтобы узнать IP-адрес `proxy.com`. +4. Неудачные правила маршрутизации отправляют запрос из шага 3 через `proxy.com`. +5. Xray снова пытается подключиться к `proxy.com`. +6. Перед этим он опять пытается разрешить `proxy.com` через встроенный DNS. +7. Встроенный DNS переиспользует соединение из шага 3 и отправляет новый запрос. +8. Возникает тупик: соединение из шага 3 ждет результат запроса из шага 7, а запрос из шага 7 не завершится, пока соединение из шага 3 не установится полностью. +9. Game over. + +Возможные решения: + +- Исправить маршрутизацию для встроенного DNS. +- Использовать hosts. +- ~~Если вы до сих пор не понимаете решение, не включайте эту функцию.~~ + +Поэтому неопытным пользователям использовать эту возможность без понимания маршрутизации не рекомендуется. +::: + +> `dialerProxy`: "" + +Идентификатор outbound. Если поле не пустое, для установления соединения используется указанный outbound. Это позволяет делать цепочку с учетом транспортных настроек. + +::: danger +Эта настройка несовместима с `ProxySettingsObject.Tag`. +::: + +> `acceptProxyProtocol`: true | false + +Только для inbound. Определяет, принимать ли PROXY protocol. + +[PROXY protocol](https://www.haproxy.org/download/2.2/doc/proxy-protocol.txt) используется для передачи реального IP-адреса и порта источника. Если вы не знаете, что это такое, просто игнорируйте параметр. + +Его умеют отправлять обычные reverse proxy, например HAProxy и Nginx, а также VLESS fallback с `xver`. + +Если значение равно `true`, после установления TCP-соединения удаленная сторона обязана сразу отправить PROXY protocol v1 или v2, иначе соединение будет закрыто. + +> `tcpKeepAliveIdle`: number + +Порог простоя TCP в секундах. После такого времени бездействия начинают отправляться Keep-Alive пакеты. + +Для outbound Xray использует такие же значения по умолчанию, как Chrome: и idle, и interval равны 45 секундам. Если установить этот параметр или `tcpKeepAliveInterval` в отрицательное значение, keepalive по умолчанию отключается; положительное значение его переопределяет. + +Для inbound Keep-Alive по умолчанию выключен. Он включается, если этот параметр или `tcpKeepAliveInterval` не равны нулю. Если задан только один из них, второй берется из настроек ОС. + +> `tcpKeepAliveInterval`: number + +Интервал в секундах между Keep-Alive пакетами после перехода TCP в keepalive-состояние. Остальное поведение описано выше. + +> `tcpUserTimeout`: number + +В миллисекундах. См.: https://github.com/grpc/proposal/blob/master/A18-tcp-user-timeout.md + +> `tcpcongestion`: "" + +Алгоритм управления перегрузкой TCP. Только Linux. +Если значение не задано, используется системное значение по умолчанию. + +::: tip Часто используемые алгоритмы + +- `bbr` (рекомендуется) +- `cubic` +- `reno` + +::: + +::: tip +Текущее системное значение можно посмотреть командой `sysctl net.ipv4.tcp_congestion_control`. +::: + +> `interface`: "" + +Привязывает исходящее соединение к конкретному имени сетевого интерфейса. Поддерживается в Linux, iOS, Mac OS и Windows. + +> `V6Only`: true | false + +Если значение равно `true`, прослушивание на `::` принимает только IPv6-соединения. Только Linux. + +> `tcpWindowClamp`: number + +Ограничивает объявляемый размер TCP-окна этим значением. Ядро выбирает максимум между ним и `SOCK_MIN_RCVBUF / 2`. + +> `tcpMptcp`: true | false + +Значение по умолчанию — `false`. Если установить `true`, включается [Multipath TCP](https://en.wikipedia.org/wiki/Multipath_TCP). Параметр относится только к клиентской стороне, поскольку начиная с Go 1.24 прослушивание уже включает MPTCP по умолчанию. Требуется Linux kernel 5.6 или новее. + +> `tcpNoDelay`: true | false + +Этот параметр удален, потому что Go и так включает TCP no delay по умолчанию. Если вам нужно отключить его, используйте `customSockopt`. + +> `addressPortStrategy`: "none" | "SrvPortOnly" | "SrvAddressOnly" | "SrvPortAndAddress" | "TxtPortOnly" | "TxtAddressOnly" | "TxtPortAndAddress" + +Позволяет использовать SRV- или TXT-записи для задания адреса и или порта цели для outbound. По умолчанию используется `none`, то есть функция выключена. + +Эти запросы идут через системный DNS, а не через встроенный DNS Xray. В качестве имени для запроса берется домен outbound. Если запрос не удался, используется исходный адрес и порт. + +Префикс `Srv` означает стандартный запрос SRV-записи. Префикс `Txt` означает TXT-запись в формате вроде `127.0.0.1:80`. + +`PortOnly` заменяет только порт. `AddressOnly` — только адрес. `PortAndAddress` — и адрес, и порт. + +Эта настройка применяется раньше `domainStrategy` внутри `sockopt`. После подмены адрес по-прежнему проходит через `domainStrategy`, если он задан. Но применяется она уже после `Freedom.domainStrategy`, поэтому если `Freedom` заранее разрешил домен в IP, этот механизм уже не сработает. + +На практике это означает, что если обычный доменный трафик попадает в `Freedom` с `AsIs`, после включения этого параметра ядро начнет пытаться переписать адрес и порт, например через SRV-запись `google.com`. + +> `customSockopt`: [] + +Массив для продвинутых пользователей, которым нужно вручную задать произвольные socket options. Теоретически через него можно воспроизвести все связанные с соединением настройки выше, а также выставить параметры, которые существуют на уровне socket, но не вынесены напрямую в ядре. Сейчас поддерживаются Linux, Windows и Darwin. Пример ниже эквивалентен `"tcpcongestion": "bbr"`. + +Используйте этот механизм только если понимаете socket programming. + +```json +"customSockopt": [ + { + "system": "linux", + "type": "str", + "level": "6", + "opt": "13", + "value": "bbr" + } +] +``` + +> `system`: "" + +Необязательный параметр. Ограничивает применение конкретной ОС. Если текущая система не совпадает, эта настройка пропускается. Поддерживаются `linux`, `windows` и `darwin`, все в нижнем регистре. Если поле пустое, настройка применяется напрямую. + +> `type`: "" + +Обязательный параметр. Тип значения. Сейчас поддерживаются `int` и `str`. + +> `level`: "" + +Необязательный параметр. Уровень протокола. По умолчанию используется `6`, то есть TCP. + +> `opt`: "" + +Номер socket option в десятичной форме. В примере выше `13` — это десятичная форма значения `TCP_CONGESTION`, которое в hex записывается как `0xd`. + +> `value`: "" + +Значение, которое нужно установить. В примере выше это `bbr`. + +Если `type` равно `int`, значение должно быть задано десятичным числом. + +> `happyEyeballs`: [HappyEyeballsObject](#happyeyeballsobject) + +Реализация Happy Eyeballs по RFC 8305, только для TCP. Когда целью является доменное имя, Xray запускает гонку между разрешенными адресами и выбирает первый успешный. Работает только если `Sockopt.domainStrategy` не равен `AsIs`. + +Значения `UseIPv4v6` и `ForceIPv4v6` фактически сводят список к IPv4 и только при неудаче обращаются к IPv6. Это не рекомендуется. Лучше использовать `UseIP` или `ForceIP` вместе с `HappyEyeballs.interleave`. + +::: warning +Не используйте это вместе с `domainStrategy` у `Freedom`, потому что тогда `Sockopt` видит уже конечный IP после подмены. +::: + +### HappyEyeballsObject + +```json +"happyEyeballs": { + "tryDelayMs": 250, + "prioritizeIPv6": false, + "interleave": 1, + "maxConcurrentTry": 4 +} +``` + +> `tryDelayMs`: number + +Задержка между попытками гонки в миллисекундах. Значение по умолчанию — `0`, то есть функция выключена. Рекомендуемое значение — `250`. + +> `prioritizeIPv6`: bool + +Определяет, какой тип адреса будет первым после сортировки. По умолчанию `false`, то есть IPv4 идет первым. + +> `interleave`: number + +Параметр RFC 8305 `First Address Family Count`. Значение по умолчанию — `1`. Он определяет, как IPv4 и IPv6 адреса чередуются в очереди. + +Например, очередь может выглядеть как `46464646`, если значение равно `1`, или как `44664466`, если значение равно `2`, где `6` означает IPv6, а `4` — IPv4. + +> `maxConcurrentTry`: number + +Максимальное количество параллельных попыток. Это не дает ядру открыть слишком много соединений, если домен разрешился в большой список адресов и все они неудачны. Значение по умолчанию — `4`. Значение `0` отключает Happy Eyeballs. diff --git a/docs/ru/config/transports/tls.md b/docs/ru/config/transports/tls.md new file mode 100644 index 00000000..f4c0a8cc --- /dev/null +++ b/docs/ru/config/transports/tls.md @@ -0,0 +1,338 @@ +# TLS + +TLS — это обычный механизм защиты транспорта. + +Он используется для настройки шифрования транспортного уровня, проверки сертификатов, отпечатков клиента и связанных параметров сертификата. + +## TLSObject + +`TLSObject` соответствует полю `tlsSettings` в [`StreamSettingsObject`](../transport.md#streamsettingsobject). + +```json +{ + // пример для outbound, аналогично применимо к inbound + "outbounds": [ + { + // ... + "streamSettings": { + "security": "tls", + "tlsSettings": { + // [!code focus:18] + "serverName": "xray.com", + "verifyPeerCertByName": "", + "rejectUnknownSni": false, + "allowInsecure": false, + "alpn": ["h2", "http/1.1"], + "minVersion": "1.2", + "maxVersion": "1.3", + "cipherSuites": "Укажите нужные наборы шифров, разделяя их двоеточием", + "certificates": [], + "disableSystemRoot": false, + "enableSessionResumption": false, + "fingerprint": "", + "pinnedPeerCertSha256": "", + "curvePreferences": [""], + "masterKeyLog": "", + "echServerKeys": "", + "echConfigList": "", + "echSockopt": {} + } + } + } + ] +} +``` + +> `serverName`: string + +Имя сервера. Значение должно присутствовать в SAN серверного сертификата. Это может быть доменное имя или IP-адрес. Если указано доменное имя, оно отправляется в расширении SNI внутри Client Hello. Для IP-адреса SNI не отправляется, потому что SNI не поддерживает IP. Для IPv6 используйте запись в `[]`. + +Если поле пустое, Xray автоматически использует значение `address`, если это доменное имя. + +Специальное значение `"FromMitM"` заставляет использовать SNI, извлеченный из TLS, расшифрованного входящим `dokodemo-door`. + +> `verifyPeerCertByName`: string + +Только для клиента. SNI, используемый при проверке сертификата. Можно указать несколько доменов через `,`; достаточно, чтобы хотя бы один SAN сертификата совпал с одним из них. Это поле переопределяет `serverName`, используемый для проверки, и нужно для специальных сценариев вроде domain fronting. + +Специальное значение `"FromMitM"` дополнительно добавляет SNI, извлеченный из TLS, расшифрованного входящим `dokodemo-door`. + +> `rejectUnknownSni`: bool + +Если значение равно `true`, сервер отклоняет TLS-рукопожатие, если полученный SNI не соответствует домену сертификата. Значение по умолчанию — `false`. + +> `alpn`: [string] + +Массив строк, задающий значения ALPN при TLS-рукопожатии. Значение по умолчанию — `["h2", "http/1.1"]`. + +Специальное значение `["FromMitM"]`, когда это единственный элемент массива, заставляет исходящий TLS использовать ALPN из TLS-соединения, расшифрованного входящим `dokodemo-door`. + +> `minVersion`: string + +`minVersion` — минимально допустимая версия TLS. + +> `maxVersion`: string + +`maxVersion` — максимально допустимая версия TLS. + +> `cipherSuites`: string + +`cipherSuites` задает список поддерживаемых наборов шифров, разделенных `:`. + +Названия наборов шифров Go и их описание можно посмотреть [здесь](https://golang.org/src/crypto/tls/cipher_suites.go#L500) или [здесь](https://golang.org/src/crypto/tls/cipher_suites.go#L44). + +::: danger +В большинстве случаев эти параметры не нужны и обычно не влияют на безопасность. Если их не задавать, Go выбирает их автоматически в зависимости от платформы. Если вы плохо понимаете, что делаете, лучше не настраивать их вручную. +::: + +> `allowInsecure`: true | false + +Разрешать ли небезопасные соединения. Только для клиента. Значение по умолчанию — `false`. + +Если значение равно `true`, Xray не проверяет корректность TLS-сертификата удаленной стороны. + +::: danger +~~По соображениям безопасности этот параметр не стоит использовать в реальных сценариях, иначе вы можете стать уязвимы для MITM-атак.~~ + +Этот параметр устарел. Вместо него используйте `pinnedPeerCertSha256`. +::: + +> `disableSystemRoot`: true | false + +Отключать ли встроенные корневые сертификаты операционной системы. Значение по умолчанию — `false`. + +Если значение равно `true`, Xray использует при TLS-рукопожатии только сертификаты из `certificates`. Если `false`, используются только системные корневые сертификаты. + +> `enableSessionResumption`: true | false + +Включать ли возобновление сессии. По умолчанию эта функция выключена и используется только если и сервер, и клиент ее включили. + +При успешном согласовании сертификаты не нужно повторно передавать во время рукопожатия. Это дает очень небольшой выигрыш по времени. + +Это не TLS 0-RTT. `gotls` пока не поддерживает такую возможность, поэтому RTT TLS-рукопожатия не уменьшается. + +> `fingerprint`: string + +Этот параметр задает отпечаток `TLS Client Hello`. Значение по умолчанию — `chrome`. Чтобы вернуться к обычному Go TLS, укажите `unsafe`. При включении Xray через библиотеку uTLS **эмулирует** TLS-отпечаток или генерирует его случайно. Поддерживаются три способа настройки: + +1. Отпечатки последних версий популярных браузеров: + +- `"chrome"` +- `"firefox"` +- `"safari"` +- `"ios"` +- `"android"` +- `"edge"` +- `"360"` +- `"qq"` + +2. Автоматическая генерация отпечатка при запуске Xray: + +- `"random"`: случайно выбирается отпечаток одного из новых браузеров +- `"randomized"`: полностью случайный уникальный отпечаток с полной поддержкой TLS 1.3 и X25519 + +3. Нативные имена hello-профилей uTLS, например `"HelloRandomizedNoALPN"` или `"HelloChrome_106_Shuffle"`. Полный список см. в [uTLS](https://github.com/refraction-networking/utls/blob/master/u_common.go#L434). + +::: tip +Эта функция только **эмулирует** отпечаток `TLS Client Hello`. Остальное поведение и остальные отпечатки остаются такими же, как у Go. Если вам нужна более полная браузерная модель TLS, используйте [Browser Dialer](./websocket.md#browser-dialer). +::: + +::: tip +При использовании этой функции некоторые TLS-параметры, влияющие на отпечаток, будут перезаписаны библиотекой uTLS и перестанут действовать, например ALPN. +Параметры, которые все равно передаются: +`"serverName" "disableSystemRoot" "pinnedPeerCertSha256" "masterKeyLog"` +::: + +> `pinnedPeerCertSha256`: string + +Используется для явного задания SHA-256 хеша сертификата удаленной стороны. Используется hex-формат, регистр неважен, например `e8e2d387fdbffeb38e9c9065cf30a97ee23c0e3d32ee6f78ffae40966befccc9`. Можно перечислить несколько значений через `,`; проверка пройдет, если совпадет любое из них. + +Этот формат совпадает с SHA-256 fingerprint в просмотрщике сертификатов Chrome и с форматом сертификатных отпечатков на crt.sh. Вычислить его можно командой `xray tls hash --cert ` или через `openssl x509 -noout -fingerprint -sha256 -in cert.pem`; формат OpenSSL с двоеточиями тоже поддерживается. Команда `xray tls ping` также выводит SHA-256 отпечаток удаленного сертификата. + +Эта проверка заменяет обычную валидацию сертификата. Возможны два случая: + +- Если ядро находит совпавший хеш у leaf-сертификата, проверка сразу считается успешной. +- Если совпавший хеш относится к CA-сертификату, корневому или промежуточному, ядро использует значение `serverName`, чтобы убедиться, что leaf-сертификат подписан именно этим CA. + +> `certificates`: \[ [CertificateObject](#certificateobject) \] + +Список сертификатов. Каждый элемент представляет один сертификат. Рекомендуется использовать полную цепочку. + +::: tip +Если вы хотите получить оценку A или A+ в инструментах вроде ssllibs или myssl, см. [это обсуждение](https://github.com/XTLS/Xray-core/discussions/56#discussioncomment-215600). +::: + +> `curvePreferences`: [string] + +Массив строк, задающий поддерживаемые кривые для ECDHE во время TLS-рукопожатия: + +```text +CurveP256 +CurveP384 +CurveP521 +X25519 +X25519MLKEM768 +SecP256r1MLKEM768* +SecP384r1MLKEM1024* +``` + +\*: uTLS не поддерживает эти кривые + +Начиная с Go 1.26 значение по умолчанию включает все перечисленные кривые. Изменение порядка не заставляет клиента или сервер предпочитать конкретную кривую: фактический выбор происходит обычным механизмом согласования ключей. + +> `masterKeyLog`: string + +Путь к файлу `(Pre)-Master-Secret`, который можно использовать, например, в Wireshark для расшифровки TLS-соединений Xray. + +> `echServerKeys`: string + +Параметр только для сервера. Используется для включения Encrypted Client Hello на сервере. + +Сгенерировать ECH Server Key и соответствующий Config можно командой `xray tls ech --serverName example.com`. `example.com` — это внешний SNI, который будет виден снаружи после шифрования настоящего SNI, и здесь можно использовать любое значение. В Server Key уже содержится ECHConfig. Если клиентский Config потерян, его можно заново получить через `xray tls ech -i "your server key"`. Публиковать его можно в HTTPS-записи DNS; формат см. [здесь](https://dns.google/query?name=encryptedsni.com&rr_type=HTTPS) или в RFC 9460. + +Даже после настройки ECH сервер все равно принимает обычные не-ECH соединения. + +> `echConfigList`: string + +Параметр только для клиента. Задает ECHConfig. Непустое значение означает, что клиент включает Encrypted Client Hello. Поддерживаются два формата. + +Первый — фиксированная строка ECHConfig, например: + +`"AF7+DQBaAAAgACA51i3Ssu4wUMV4FNCc8iRX5J+YC4Bhigz9sacl2lCfSQAkAAEAAQABAAIAAQADAAIAAQACAAIAAgADAAMAAQADAAIAAwADAAtleGFtcGxlLmNvbQAA"` + +Второй — запрос через DNS-сервер. Например, при использовании CDN можно получать ECHConfig динамически из HTTPS-записей. Если найден корректный ECH Config, Xray будет уважать TTL, который вернул сервер. Целью запроса становится заданный SNI или домен сервера, если SNI пустой и цель — доменное имя. + +Базовый формат — `"udp://1.1.1.1"`, то есть получение ECHConfig через UDP DNS 1.1.1.1. Можно также использовать `"https://1.1.1.1/dns-query"` или `h2c://` для DoH или h2c. Во всех случаях можно явно указать порт, например `udp://1.1.1.1:53`. Если порт не указан, используется стандартный для протокола. + +Также можно отдельно указать домен для поиска ECHConfig в форме `"example.com+https://1.1.1.1/dns-query"`. Тогда Xray принудительно использует ECHConfig из DNS-записей `example.com`. Это удобно, если вы хотите получать ECHConfig через DNS, но не хотите явно светить HTTPS-запросы к целевому домену. + +> `echSockopt`: [SockoptObject](./sockopt.md#sockoptobject) + +Настраивает низкоуровневые параметры сокета для соединения, которое используется при DNS-запросе ECH-записей. + +### CertificateObject + +```json +{ + "ocspStapling": 0, + "oneTimeLoading": false, + "usage": "encipherment", + "buildChain": false, + "certificateFile": "/path/to/certificate.crt", + "keyFile": "/path/to/key.key", + "certificate": [ + "--BEGIN CERTIFICATE--", + "MIICwDCCAaigAwIBAgIRAO16JMdESAuHidFYJAR/7kAwDQYJKoZIhvcNAQELBQAw", + "ADAeFw0xODA0MTAxMzU1MTdaFw0xODA0MTAxNTU1MTdaMAAwggEiMA0GCSqGSIb3", + "DQEBAQUAA4IBDwAwggEKAoIBAQCs2PX0fFSCjOemmdm9UbOvcLctF94Ox4BpSfJ+", + "3lJHwZbvnOFuo56WhQJWrclKoImp/c9veL1J4Bbtam3sW3APkZVEK9UxRQ57HQuw", + "OzhV0FD20/0YELou85TwnkTw5l9GVCXT02NG+pGlYsFrxesUHpojdl8tIcn113M5", + "pypgDPVmPeeORRf7nseMC6GhvXYM4txJPyenohwegl8DZ6OE5FkSVR5wFQtAhbON", + "OAkIVVmw002K2J6pitPuJGOka9PxcCVWhko/W+JCGapcC7O74palwBUuXE1iH+Jp", + "noPjGp4qE2ognW3WH/sgQ+rvo20eXb9Um1steaYY8xlxgBsXAgMBAAGjNTAzMA4G", + "A1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAA", + "MA0GCSqGSIb3DQEBCwUAA4IBAQBUd9sGKYemzwPnxtw/vzkV8Q32NILEMlPVqeJU", + "7UxVgIODBV6A1b3tOUoktuhmgSSaQxjhYbFAVTD+LUglMUCxNbj56luBRlLLQWo+", + "9BUhC/ow393tLmqKcB59qNcwbZER6XT5POYwcaKM75QVqhCJVHJNb1zSEE7Co7iO", + "6wIan3lFyjBfYlBEz5vyRWQNIwKfdh5cK1yAu13xGENwmtlSTHiwbjBLXfk+0A/8", + "r/2s+sCYUkGZHhj8xY7bJ1zg0FRalP5LrqY+r6BckT1QPDIQKYy615j1LpOtwZe/", + "d4q7MD/dkzRDsch7t2cIjM/PYeMuzh87admSyL6hdtK0Nm/Q", + "--END CERTIFICATE--" + ], + "key": [ + "--BEGIN RSA PRIVATE KEY--", + "MIIEowIBAAKCAQEArNj19HxUgoznppnZvVGzr3C3LRfeDseAaUnyft5SR8GW75zh", + "bqOeloUCVq3JSqCJqf3Pb3i9SeAW7Wpt7FtwD5GVRCvVMUUOex0LsDs4VdBQ9tP9", + "GBC6LvOU8J5E8OZfRlQl09NjRvqRpWLBa8XrFB6aI3ZfLSHJ9ddzOacqYAz1Zj3n", + "jkUX+57HjAuhob12DOLcST8np6IcHoJfA2ejhORZElUecBULQIWzjTgJCFVZsNNN", + "itieqYrT7iRjpGvT8XAlVoZKP1viQhmqXAuzu+KWpcAVLlxNYh/iaZ6D4xqeKhNq", + "IJ1t1h/7IEPq76NtHl2/VJtbLXmmGPMZcYAbFwIDAQABAoIBAFCgG4phfGIxK9Uw", + "qrp+o9xQLYGhQnmOYb27OpwnRCYojSlT+mvLcqwvevnHsr9WxyA+PkZ3AYS2PLue", + "C4xW0pzQgdn8wENtPOX8lHkuBocw1rNsCwDwvIguIuliSjI8o3CAy+xVDFgNhWap", + "/CMzfQYziB7GlnrM6hH838iiy0dlv4I/HKk+3/YlSYQEvnFokTf7HxbDDmznkJTM", + "aPKZ5qbnV+4AcQfcLYJ8QE0ViJ8dVZ7RLwIf7+SG0b0bqloti4+oQXqGtiESUwEW", + "/Wzi7oyCbFJoPsFWp1P5+wD7jAGpAd9lPIwPahdr1wl6VwIx9W0XYjoZn71AEaw4", + "bK4xUXECgYEA3g2o9WqyrhYSax3pGEdvV2qN0VQhw7Xe+jyy98CELOO2DNbB9QNJ", + "8cSSU/PjkxQlgbOJc8DEprdMldN5xI/srlsbQWCj72wXxXnVnh991bI2clwt7oYi", + "pcGZwzCrJyFL+QaZmYzLxkxYl1tCiiuqLm+EkjxCWKTX/kKEFb6rtnMCgYEAx0WR", + "L8Uue3lXxhXRdBS5QRTBNklkSxtU+2yyXRpvFa7Qam+GghJs5RKfJ9lTvjfM/PxG", + "3vhuBliWQOKQbm1ZGLbgGBM505EOP7DikUmH/kzKxIeRo4l64mioKdDwK/4CZtS7", + "az0Lq3eS6bq11qL4mEdE6Gn/Y+sqB83GHZYju80CgYABFm4KbbBcW+1RKv9WSBtK", + "gVIagV/89moWLa/uuLmtApyEqZSfn5mAHqdc0+f8c2/Pl9KHh50u99zfKv8AsHfH", + "TtjuVAvZg10GcZdTQ/I41ruficYL0gpfZ3haVWWxNl+J47di4iapXPxeGWtVA+u8", + "eH1cvgDRMFWCgE7nUFzE8wKBgGndUomfZtdgGrp4ouLZk6W4ogD2MpsYNSixkXyW", + "64cIbV7uSvZVVZbJMtaXxb6bpIKOgBQ6xTEH5SMpenPAEgJoPVts816rhHdfwK5Q", + "8zetklegckYAZtFbqmM0xjOI6bu5rqwFLWr1xo33jF0wDYPQ8RHMJkruB1FIB8V2", + "GxvNAoGBAM4g2z8NTPMqX+8IBGkGgqmcYuRQxd3cs7LOSEjF9hPy1it2ZFe/yUKq", + "ePa2E8osffK5LBkFzhyQb0WrGC9ijM9E6rv10gyuNjlwXdFJcdqVamxwPUBtxRJR", + "cYTY2HRkJXDdtT0Bkc3josE6UUDvwMpO0CfAETQPto1tjNEDhQhT", + "--END RSA PRIVATE KEY--" + ] +} +``` + +По умолчанию серверные сертификаты перезагружаются каждые 3600 секунд, то есть раз в час. + +> `ocspStapling`: number + +Интервал обновления OCSP stapling в секундах. Значение по умолчанию — `0`. Любое ненулевое значение включает OCSP stapling и одновременно заменяет стандартный 3600-секундный интервал горячей перезагрузки сертификата. + +> `oneTimeLoading`: true | false + +Загрузка только один раз. Значение по умолчанию — `false`. Если установить `true`, отключаются и горячая перезагрузка сертификата, и OCSP stapling. + +> `usage`: "encipherment" | "verify" | "issue" + +Назначение сертификата. Значение по умолчанию — `"encipherment"`. + +- `"encipherment"`: сертификат используется для TLS-аутентификации и шифрования +- `"verify"`: сертификат используется для проверки удаленных TLS-сертификатов; в этом случае он должен быть CA-сертификатом +- `"issue"`: сертификат используется для выпуска других сертификатов; в этом случае он тоже должен быть CA-сертификатом + +::: tip TIP 1 +В Windows самоподписанный CA-сертификат можно установить в системное хранилище и использовать для проверки удаленных TLS-сертификатов. +::: + +::: tip TIP 2 +Когда приходит новый запрос клиента и, например, указан `serverName` равный `"xray.com"`, Xray сначала ищет в списке сертификат, подходящий для `"xray.com"`. Если такого нет, используется любой сертификат с `usage: "issue"` для выпуска нового сертификата на `"xray.com"` сроком на один час, после чего этот сертификат добавляется в список для дальнейшего использования. +::: + +::: tip TIP 3 +Если одновременно заданы `certificateFile` и `certificate`, Xray предпочитает `certificateFile`. То же самое относится к `keyFile` и `key`. +::: + +::: tip TIP 4 +Если `usage` равно `"verify"`, поля `keyFile` и `key` могут быть пустыми. +::: + +::: tip TIP 5 +Самоподписанный CA-сертификат можно сгенерировать командой `xray tls cert`. +::: + +::: tip TIP 6 +Если у вас уже есть домен, бесплатный сторонний сертификат удобно получать через инструменты вроде [acme.sh](https://github.com/acmesh-official/acme.sh). +::: + +> `buildChain`: true | false + +Действует только если назначение сертификата — `issue`. Если установить `true`, CA-сертификат будет встроен в выпускаемую цепочку сертификатов. + +::: tip TIP 1 +Корневой сертификат не стоит встраивать в цепочку. Этот параметр уместен только если подписывающий CA является промежуточным сертификатом. +::: + +> `certificateFile`: string + +Путь к файлу сертификата, например к `.crt`, сгенерированному через OpenSSL. + +> `certificate`: [string] + +Массив строк с содержимым сертификата в формате, показанном выше. Используйте либо `certificate`, либо `certificateFile`. + +> `keyFile`: string + +Путь к файлу приватного ключа, например к `.key`, сгенерированному через OpenSSL. Ключи, защищенные паролем, сейчас не поддерживаются. + +> `key`: [string] + +Массив строк с содержимым приватного ключа в том же формате, что и в примере выше. Используйте либо `key`, либо `keyFile`.