# 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"
> "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, иначе соединение будет закрыто. > `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.