diff --git a/docs/ru/config/transports/splithttp.md b/docs/ru/config/transports/splithttp.md index 817a786..9355a5a 100644 --- a/docs/ru/config/transports/splithttp.md +++ b/docs/ru/config/transports/splithttp.md @@ -1,4 +1,4 @@ -# SplitHTTP +# SplitHTTP (H2, QUIC H3) @@ -6,10 +6,12 @@ Может использоваться через CDN, не поддерживающие WebSocket, но есть несколько требований: -- CDN должен поддерживать HTTP-фрагментированную передачу и потоковые ответы без буферизации. Ядро будет отправлять `X-Accel-Buffering: no` и `Content-Type: text/event-stream`, чтобы сообщить CDN об этом, но CDN должен соблюдать этот заголовок. Если промежуточный сервер не поддерживает потоковые ответы и зависает, передача, скорее всего, не будет работать. + +- CDN должен поддерживать HTTP-фрагментированную передачу и потоковые ответы без буферизации. Ядро будет отправлять различную информацию, чтобы сообщить CDN об этом, но CDN должна ее соблюдать. Если промежуточный узел не поддерживает потоковые ответы и зависает, этот транспорт, скорее всего, не будет работать. Цель та же, что и у V2fly Meek, но благодаря использованию фрагментированной загрузки скорость загрузки выше, а скорость отдачи оптимизирована, но все еще очень ограничена, поэтому к HTTP-прокси предъявляются более высокие требования (см. выше). + `SplitHTTP` также принимает заголовок `X-Forwarded-For`. ## SplitHttpObject @@ -23,65 +25,156 @@ "headers": { "key": "value" }, - "maxUploadSize": 1000000, - "maxConcurrentUploads": 10 + "scMaxEachPostBytes": 1000000, + "scMaxConcurrentPosts": 100, + "scMinPostsIntervalMs": 30, + "noSSEHeader": false, + "xPaddingBytes": "100-1000", + "xmux": { + "maxConcurrency": 0, + "maxConnections": 0, + "cMaxReuseTimes": 0, + "cMaxLifetimeMs": 0 + } } ``` > `path`: string -Путь HTTP-протокола, используемый SplitHTTP, значение по умолчанию — `"/"`. +Путь HTTP-протокола, используемый SplitHTTP. Значение по умолчанию — `"/"`. > `host`: string -Хост, отправляемый в HTTP-запросе SplitHTTP, по умолчанию пуст. Если значение на стороне сервера пустое, значение хоста, отправленное клиентом, не проверяется. +Хост, отправляемый в HTTP-запросе SplitHTTP. Значение по умолчанию пустое. Если значение на сервере пустое, значение хоста, отправляемое клиентом, не проверяется. -Если это значение указано на стороне сервера или `host` указан в `headers`, то проверяется соответствие хоста запроса клиента. +Если значение указано на сервере или в `headers`, оно будет сравниваться со значением хоста в запросе клиента. Приоритет выбора хоста для отправки клиентом: `host` > `headers` > `address`. > `headers`: map \{string: string\} -Пользовательские HTTP-заголовки, пары ключ-значение, где каждый ключ представляет имя HTTP-заголовка, а соответствующее значение является строкой. +Только для клиента. Пользовательские HTTP-заголовки. Пара «ключ-значение», где каждый ключ представляет собой имя HTTP-заголовка, а соответствующее значение — строка. -> `maxUploadSize`: int +> `scMaxEachPostBytes`: int | string -Максимальный размер фрагмента загрузки в байтах, по умолчанию 1 МБ. +Максимальный размер блока выгрузки в байтах. Значение по умолчанию — 1000000 (1 МБ). -Это значение должно быть меньше максимального размера тела запроса, разрешенного CDN или другим обратным HTTP-прокси, иначе будет выдаваться ошибка HTTP 413. +Размер, установленный на клиенте, должен быть меньше этого значения, иначе запрос POST, размер которого превышает значение, установленное на сервере, будет отклонен. -Увеличение этого значения может увеличить скорость загрузки. +Это значение должно быть меньше максимального размера тела запроса, разрешенного CDN или другим обратным прокси-сервером HTTP, иначе будет выдаваться ошибка HTTP 413. -> `maxConcurrentUploads`: int +Также может быть строкой в формате "500000-1000000", и ядро будет случайным образом выбирать значение из этого диапазона для уменьшения цифрового следа. -Максимальное количество одновременных загрузок, по умолчанию 10, соединения будут использоваться повторно, насколько это возможно. +> `scMaxConcurrentPosts`: int | string -Если соединение нестабильно или потребление памяти на сервере слишком велико, попробуйте уменьшить это значение. +Максимальное количество одновременных запросов POST на одно соединение. Значение по умолчанию — 100. -Значение, установленное клиентом, должно быть меньше, чем на сервере, иначе это может привести к проблемам с подключением. +Параллельная выгрузка также (и в основном) контролируется параметром `scMinPostsIntervalMs`, поэтому это значение является лишь страховкой. -## Детали протокола +Фактическое количество запросов, отправляемых клиентом, должно быть меньше, чем на сервере. (На практике, поскольку указанного выше ограничения трудно достичь, клиент может фактически установить значение, превышающее значение на сервере, но это не рекомендуется). -Подробное обсуждение см. [#3412](https://github.com/XTLS/Xray-core/pull/3412) и [#3462](https://github.com/XTLS/Xray-core/pull/3462). Ниже приведено краткое описание и требования к совместимой реализации: +Также может быть строкой в формате "50-100", и ядро будет случайным образом выбирать значение из этого диапазона для уменьшения цифрового следа. -1. Загрузка начинается с `GET /`. Сервер немедленно отвечает `200 OK` и `Transfer Encoding:chunked` и немедленно отправляет двухбайтовую полезную нагрузку, чтобы принудительно обновить заголовки HTTP-прокси. +> `scMinPostsIntervalMs`: int | string -2. Отправка данных начинается с `POST //`. `seq` действует как порядковый номер TCP, начиная с 0, пакеты данных могут отправляться одновременно, сервер должен пересобрать данные по порядковому номеру. Порядковый номер не следует сбрасывать. +Только для клиента. Минимальный интервал между запросами POST на выгрузку. Значение по умолчанию — 30. - Клиент может свободно выбирать порядок открытия исходящих и нисходящих запросов, любой из них может инициировать сеанс, но соединение `GET` должно быть открыто в течение 30 секунд, иначе сеанс будет разорван. +Также может быть строкой в формате "10-50", и ядро будет случайным образом выбирать значение из этого диапазона для уменьшения цифрового следа. -4. Запрос `GET` будет оставаться открытым до тех пор, пока соединение не будет разорвано, и сервер, и клиент могут закрыть соединение. Конкретное поведение зависит от версии HTTP. +> `noSSEHeader`: bool + +Только для сервера. Не отправлять заголовок ответа `Content-Type: text/event-stream`. Значение по умолчанию — `false` (то есть заголовок будет отправлен). + +> `xPaddingBytes`: int | string + +Задает размер заполнения для запросов (исходящих) и ответов (входящих), чтобы уменьшить цифровой след запроса. Единица измерения — байты. Значение по умолчанию — `"100-1000"`, каждый раз будет выбираться случайное число из этого диапазона. Также может быть одним числом, например `"200"` или `200`. + +Значение `-1` полностью отключает заполнение. + +> `xmux`: [XmuxObject](#xmuxobject) + +## XmuxObject + + + +Позволяет пользователям контролировать поведение мультиплексирования SplitHTTP в h2 и h3. Если не настроено, по умолчанию все запросы мультиплексируются в одно TCP/QUIC-соединение. + +```json +{ + "maxConcurrency": 0, + "maxConnections": 0, + "cMaxReuseTimes": 0, + "cMaxLifetimeMs": 0 +} +``` + +Поскольку по умолчанию используется неограниченное мультиплексирование, `xmux` фактически ограничивает его. Кроме того, не включайте mux.cool. + +Объяснение терминов: +- Потоки будут мультиплексироваться в физические соединения, например: Соединение 1 (Поток 1, Поток 2, Поток 3) Соединение 2 (Поток 4, Поток 5, Поток 6) ... и так далее. В других источниках вы можете встретить описание "соединение-подключение", это то же самое. +- Все поля, описанные ниже, имеют тип int/string и поддерживают как фиксированные значения (например, `16`), так и диапазоны значений (например, `"8-32"`). + +> `maxConcurrency`: int/string + +Значение по умолчанию — 0 (неограниченно). Максимальное количество потоков, мультиплексируемых в одном соединении. Когда количество потоков в соединении достигает этого значения, ядро создает дополнительные соединения для размещения новых потоков, аналогично параметру `concurrency` в mux.cool. + +> `maxConnections`: int/string + +Значение по умолчанию — 0 (неограниченно). Максимальное количество открытых соединений. Ядро будет активно открывать новые соединения для каждого потока до тех пор, пока не будет достигнуто это значение. Затем ядро начнет мультиплексировать потоки в уже установленные соединения. Конфликтует с `maxConcurrency`. + +> `cMaxReuseTimes`: int/string + +Значение по умолчанию — 0 (неограниченно). Максимальное количество раз, которое соединение может быть использовано повторно. По достижении этого значения ядро больше не будет назначать потоки этому соединению, и оно будет разорвано после закрытия последнего внутреннего потока. + +> `cMaxLifetimeMs`: int/string + +Значение по умолчанию — 0 (неограниченно). Максимальное время "жизни" соединения. По истечении этого времени ядро больше не будет назначать потоки этому соединению, и оно будет разорвано после закрытия последнего внутреннего потока. + +## Версия HTTP + +### Поведение клиента + +По умолчанию клиент будет использовать http/1.1, если TLS не включен, и h2, если TLS включен. + +Если TLS включен, можно указать конкретную версию HTTP (http/1.1, h2, h3) в массиве `alpn` в настройках TLS (работает только в том случае, если массив содержит только один элемент, если указано несколько элементов, будет использоваться поведение по умолчанию). + +### Поведение сервера + +По умолчанию сервер будет прослушивать TCP-порт и обрабатывать трафик http/1.1 и h2. + +Если TLS включен, можно указать `h3` в массиве `alpn` в настройках TLS. В этом случае сервер будет прослушивать UDP-порт и обрабатывать трафик h3. + +### Советы + +Поскольку этот протокол основан на стандартных HTTP-запросах, он нечувствителен к преобразованию версий HTTP, и различные промежуточные узлы могут преобразовывать версии HTTP. + +Например, если вы хотите использовать h3 для подключения к Cloudflare, но Cloudflare не будет использовать h3 для обратного подключения, а будет использовать http/1.1 или h2, то на клиенте `alpn` должен быть установлен в `h3`, а на сервере — нет, поскольку запросы, отправляемые на сервер, не будут использовать h3. + +## Browser Dialer + +При использовании HTTPS этот транспорт также поддерживает [Browser Dialer](../features/browser_dialer.md). + +## Подробности протокола + +Подробное обсуждение см. в [#3412](https://github.com/XTLS/Xray-core/pull/3412) и [#3462](https://github.com/XTLS/Xray-core/pull/3462). Ниже приведено краткое описание и требования к совместимости реализации: + +1. Загрузка начинается с запроса `GET /`. Сервер немедленно отвечает `200 OK` и `Transfer Encoding:chunked` и сразу же отправляет двухбайтовую полезную нагрузку, чтобы заставить HTTP-промежуточные узлы сбросить заголовки. + +На данный момент сервер отправляет следующие заголовки: + +* `X-Accel-Buffering: no` — отключает буферизацию. +* `Content-Type: text/event-stream` — отключает буферизацию на некоторых промежуточных узлах, можно отключить с помощью опции `"noSSEHeader"`. +* `Transfer-Encoding: chunked` — кодировка передачи данных, используется только в HTTP/1.1. +* `Cache-Control: no-store` — отключает любое возможное кэширование ответов. + +2. Выгрузка начинается с запроса `POST //`. `seq` работает аналогично порядковому номеру TCP, начиная с 0. Пакеты данных могут отправляться одновременно, сервер должен пересобрать данные в соответствии с порядковым номером. Порядковый номер не должен сбрасываться. + + Клиент может открывать запросы на выгрузку и загрузку в любом порядке, любой из них может инициировать сеанс, но соединение `GET` должно быть открыто в течение 30 секунд, иначе сеанс будет разорван. + +3. Запрос `GET` будет оставаться открытым до тех пор, пока соединение не будет разорвано. Как сервер, так и клиент могут закрыть соединение. Конкретное поведение зависит от версии HTTP. Рекомендации: -* Не ожидайте, что CDN будет правильно передавать все заголовки, цель этого протокола — обойти CDN, не поддерживающие WS, а поведение этих CDN обычно не очень дружелюбное. +* Не ожидайте, что CDN будет правильно передавать все заголовки. Цель этого протокола — обойти CDN, которые не поддерживают WS, а такие CDN обычно ведут себя не очень хорошо. -* Следует предполагать, что все HTTP-соединения не поддерживают потоковые запросы, поэтому размер каждого пакета, отправляемого исходящим соединением, должен определяться с учетом задержки, пропускной способности и ограничений самого промежуточного сервера (аналогично MTU TCP и алгоритму Нейгла). - -* Что касается версий HTTP, ядро временно не поддерживает h2c, поэтому при отсутствии HTTPS Xray отправляет только запросы http/1.1. - -Во избежание дополнительных сложностей, связанных с согласованием ALPN, клиент Xray использует h2 при использовании HTTPS. Вы также можете вручную указать alpn как http/1.1 или h3 в настройках TLS клиента, чтобы использовать соответствующую версию HTTP для отправки запросов. Сервер Xray, с другой стороны, совместим со всеми типами входящих соединений, включая h2c (h3 пока не поддерживается), поскольку входящие соединения могут использовать различные типы запросов из-за перенаправления через промежуточные узлы. - -## BrowserDialer - -При использовании HTTPS этот транспорт также поддерживает [BrowserDialer](../features/browser_dialer.md). +* Следует предполагать, что все HTTP-соединения не поддерживают потоковые запросы, поэтому размер каждого пакета, отправляемого по исходящему соединению, должен основываться на задержке, пропускной способности и ограничениях самого промежуточного узла (аналогично MTU и алгоритму Нейгла в TCP). \ No newline at end of file