mirror of
https://github.com/XTLS/Xray-docs-next.git
synced 2026-09-28 18:08:01 +03:00
317 lines
22 KiB
Markdown
317 lines
22 KiB
Markdown
# Sockopt
|
||
|
||
Sockopt используется для настройки низкоуровневого сетевого поведения.
|
||
|
||
С его помощью можно управлять прозрачным проксированием, стратегией DNS-разрешения и различными параметрами socket.
|
||
|
||
## SockoptObject
|
||
|
||
`SockoptObject` соответствует полю `sockopt` в [`StreamSettingsObject`](../transport.md#streamsettingsobject).
|
||
|
||
```json
|
||
{
|
||
// пример для outbound, аналогично применимо к inbound
|
||
"outbounds": [
|
||
{
|
||
// ...
|
||
"streamSettings": {
|
||
// [!code focus:21]
|
||
"sockopt": {
|
||
"mark": 0,
|
||
"tcpMaxSeg": 1440,
|
||
"tcpFastOpen": false,
|
||
"tproxy": "off",
|
||
"domainStrategy": "AsIs",
|
||
"happyEyeballs": {},
|
||
"dialerProxy": "",
|
||
"acceptProxyProtocol": false,
|
||
"trustedXForwardedFor": [],
|
||
"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
|
||
Если в [tunnel](../inbounds/tunnel.md) параметр `followRedirect` равен `true`, а `tproxy` в Sockopt пустой, то значение `tproxy` будет автоматически установлено в `"redirect"`.
|
||
:::
|
||
|
||
> `domainStrategy`: "AsIs"<br>
|
||
> "UseIP" | "UseIPv6v4" | "UseIPv6" | "UseIPv4v6" | "UseIPv4"<br>
|
||
> "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, иначе соединение будет закрыто.
|
||
|
||
> `trustedXForwardedFor`: [ string ]
|
||
|
||
Применяется только к трем HTTP-ориентированным inbound: `XHTTP`, `WebSocket` и `HTTPUpgrade`.
|
||
|
||
Позволяет ограничить, в каких случаях Xray будет доверять заголовку `X-Forwarded-For` и использовать его для подмены `SourceIP`.
|
||
|
||
Если поле не задано, сохраняется старое поведение: если в запросе есть `X-Forwarded-For`, Xray его читает.
|
||
|
||
После настройки этого поля каждый элемент массива рассматривается как имя дополнительного заголовка, которое должно присутствовать в запросе. Xray будет доверять `X-Forwarded-For` только если в запросе есть хотя бы один из этих заголовков. Их значения не важны, проверяется только наличие самого ключа.
|
||
|
||
> `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",
|
||
"network": "tcp",
|
||
"type": "str",
|
||
"level": "6",
|
||
"opt": "13",
|
||
"value": "bbr"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
> `system`: ""
|
||
|
||
Необязательный параметр. Ограничивает применение конкретной ОС (в нижнем регистре). Если текущая система не совпадает, эта настройка пропускается. Если поле пустое, настройка применяется напрямую. Поддерживаются `linux`, `windows`, `darwin` и `android` (`android` используется только в специализированных сборках для Android; запуск сборки Linux на Android по-прежнему считается как `linux`).
|
||
|
||
> `network`: ""
|
||
|
||
Необязательный параметр. Ограничивает применение конкретным типом сети. Поддерживаются `tcp`, `tcp4`, `tcp6`, `udp`, `udp4`, `udp6`. Значение без числового суффикса означает, что sockopt применяется к обоим стекам. Обратите внимание: цель IPv4 **не означает**, что стандартная библиотека передаст network `tcp4`/`udp4` — например, система может использовать IPv6-сокет для подключения к IPv4-адресу. Перед использованием проверьте поведение стандартной библиотеки.
|
||
|
||
> `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.
|