Skip to content

Маршрутизация — Xray-core ​

Блок routing — это движок, решающий, какое исходящее подключение использует соединение. Он содержит список правил (сопоставляются по порядку, побеждает первое), глобальную domainStrategy и именованные балансировщики balancers, которые можно указывать как цель правила.

Параметры верхнего уровня ​

ПолеТипПо умолчаниюДопустимые значенияОписание
rules[]json.RawMessage[]<rule object array>Правила маршрутизации, вычисляемые в порядке объявления. Побеждает первое совпавшее правило.
domainStrategy*stringAsIsAsIs | IpIfNonMatch | IpOnDemandКак домены назначения разрешаются для сопоставления правил. AsIs оставляет домены строками (совпадают только доменные правила); IpIfNonMatch разрешает в IP, когда не совпало ни одно доменное правило; IpOnDemand разрешает заранее, как только есть IP-правила.
balancers[]*BalancingRule[][BalancingRule]Именованные балансировщики нагрузки, используемые как balancerTag в целях правил.

Исходный код: infra/conf/router.go:71-75 · зафиксировано на v26.9.9 (52a412d)

rules[] — объект правила ​

Каждое правило — JSON-объект, у которого ключи сопоставления выбирают множество соединений, а ключи цели решают, куда они пойдут. Форма полиморфна: парсер смотрит, какие ключи сопоставления присутствуют.

Ключи сопоставления (все необязательны, объединяются по И):

ПолеТипОписание
typestringДолжно быть "field" — единственный тип правил, который поддерживает Xray.
domain / domains[]stringСопоставление по домену назначения. Принимает шаблоны: full:example.com, domain:example.com, regexp:.+\\.com$, keyword:google, geosite:cn.
ip[]stringСопоставление по IP назначения. Принимает обычный IP, CIDR, geoip:cn.
source[]stringСопоставление по IP источника (тот же синтаксис, что и ip).
sourceIP[]stringТо же, что source (тот же синтаксис, что и ip); если заданы оба, используется sourceIP.
portstringСопоставление по порту назначения. 80, 80-90, 80,443,8080-8090.
sourcePortstringСопоставление по порту источника (тот же синтаксис).
localIP[]stringСопоставление по локальному адресу, на который пришло соединение (IP самого входящего). Тот же синтаксис, что и ip.
localPortstringСопоставление по локальному порту, на который пришло соединение (порт входящего). Тот же синтаксис, что и port.
networkstringСопоставление по транспорту. tcp, udp, tcp,udp.
user[]stringСопоставление по email-метке пользователя входящего подключения.
vlessRoutestringТолько для входящих VLESS: сопоставление по 7–8-му байтам UUID, присланного клиентом, — третьей группе UUID, прочитанной как шестнадцатеричное число (например, …-01bb-… = 443). Синтаксис списка портов ("443", "1-100,443"). Позволяет одному серверу маршрутизировать по значению, заложенному в UUID клиентов.
inboundTag[]stringСопоставление по тегу входящего подключения.
protocol[]stringСопоставление по определённому сниффингом прикладному протоколу. http, tls, bittorrent, quic. Сниффинг должен быть включён на входящем подключении.
attrsmap[string]stringСопоставление по атрибутам сниффинга (например, Host).
process[]stringСопоставление по локальному процессу, открывшему соединение: имя процесса (curl; окончание .exe игнорируется), абсолютный путь (/usr/bin/curl), каталог с / на конце (совпадение по префиксу), self/ (собственный процесс Xray) или xray/ (путь к исполняемому файлу Xray). Совпадают только TCP / UDP-соединения с той же машины; поддерживается в Linux, Android, Windows и macOS.
localOS[]stringСовпадение по операционной системе, на которой запущен сам Xray (Go runtime.GOOS: linux, windows, darwin, android, ios, freebsd и т. д.; без учёта регистра). Вычисляется один раз при построении правила — удобно для одной конфигурации на нескольких устройствах.
domainMatcherstringРеализация сопоставителя доменов. hybrid (по умолчанию, быстрый) или linear.

Ключи цели (нужен ровно один):

ПолеОписание
outboundTagОтправить совпавший трафик в это исходящее подключение.
balancerTagОтправить совпавший трафик в балансировщик (который выберет исходящее подключение из своего пула).

Плюс поля метаданных:

ПолеОписание
ruleTagЧеловекочитаемое имя правила. Отображается в API и журналах.
webhook{ url, deduplication, headers }. При срабатывании правила на url отправляется POST с JSON-событием (теги входящего / исходящего, источник, назначение, email пользователя, протокол, отметка времени и т. д.; тайм-аут 5 с; принимается и URL Unix-сокета). deduplication подавляет повторные события для того же email пользователя в течение указанного числа секунд (0 — выключено); headers добавляются к запросу. На маршрутизацию не влияет.

balancers[] ​

ПолеТипПо умолчаниюДопустимые значенияОписание
tagstring(required)<string>Имя балансировщика. Используется полем balancerTag правил маршрутизации.
selectorStringList(required)[<outbound-tag prefix>]Префиксы тегов исходящих подключений. Любое исходящее подключение, чей тег начинается с одного из них, включается в пул балансировщика.
strategyStrategyConfig{type: "random"}{type: "random|leastLoad|leastPing|roundRobin", settings?: {...}}Стратегия выбора. random берёт любого участника пула; roundRobin перебирает по кругу; leastPing выбирает участника с наименьшей наблюдаемой задержкой (требует observatory); leastLoad выбирает наименее нагруженного.
fallbackTagstring(unset)<outbound tag>Исходящее подключение, используемое когда пул балансировщика пуст или все его участники недоступны.

Исходный код: infra/conf/router.go:21-26 · зафиксировано на v26.9.9 (52a412d)

Варианты стратегий ​

  • random — равномерный случайный выбор.
  • roundRobin — перебор пула по кругу.
  • leastPing — выбор участника с наименьшей задержкой. Требует включённого observatory или burstObservatory, чтобы у каждого исходящего подключения была известная задержка.
  • leastLoad — выбор наименее нагруженного участника. Несёт strategyLeastLoadConfig (см. infra/conf/router_strategy.go) с полями настройки проверок доступности.

Примеры ​

Прямое направление внутрикитайского трафика (канонический паттерн для Китая):

json
{
  "routing": {
    "domainStrategy": "IpIfNonMatch",
    "rules": [
      { "type": "field", "ip": ["geoip:private"], "outboundTag": "direct" },
      { "type": "field", "domain": ["geosite:cn"], "outboundTag": "direct" },
      { "type": "field", "ip": ["geoip:cn"], "outboundTag": "direct" },
      { "type": "field", "outboundTag": "proxy" }
    ]
  }
}

Маршрутизация через балансировщик с выбором по задержке:

json
{
  "routing": {
    "rules": [
      { "type": "field", "outboundTag": "direct", "domain": ["geosite:cn"] },
      { "type": "field", "balancerTag": "proxy-balance" }
    ],
    "balancers": [
      {
        "tag": "proxy-balance",
        "selector": ["proxy-"],
        "strategy": { "type": "leastPing" },
        "fallbackTag": "direct"
      }
    ]
  },
  "observatory": {
    "subjectSelector": ["proxy-"],
    "probeURL": "http://cp.cloudflare.com/generate_204",
    "probeInterval": "30s"
  }
}

Сопоставление по прикладному протоколу (требует сниффинга на входящем подключении):

json
{
  "inbounds": [{
    "port": 1080,
    "protocol": "socks",
    "sniffing": { "enabled": true, "destOverride": ["http", "tls"] }
  }],
  "routing": {
    "rules": [
      { "type": "field", "protocol": ["bittorrent"], "outboundTag": "block" }
    ]
  }
}

Примечания ​

  • Правила вычисляются в порядке объявления. Побеждает первое совпавшее; последующие правила видят только несовпавший трафик.
  • domainStrategy решает, что происходит, когда есть только IP-правила:
    • AsIs — доменные адресаты минуют IP-правила. Самый дешёвый вариант.
    • IpIfNonMatch — разрешать домен в IP, только если ни одно правило не совпало по домену. Сбалансированный вариант.
    • IpOnDemand — разрешать каждый домен в IP заранее, как только есть IP-правила. Самый точный и самый дорогой.
  • Доменные префиксы (full:, domain:, regexp:, keyword:, geosite:) разбираются внутри сопоставителя. Без префикса поведение по умолчанию — domain: (совпадение по суффиксу).
  • Правила geoip: и geosite: читают внешние файлы данных (geoip.dat / geosite.dat), обычно лежащие рядом с бинарным файлом Xray. Имена категорий (cn, private, apple, google, …) определены в этих файлах.
  • Эти файлы данных можно автообновлять: блок верхнего уровня geodata скачивает свежие geoip.dat / geosite.dat по cron-расписанию через выбранное исходящее подключение. См. Geo-данные.
  • Входящий сниффинг питает ключи сопоставления protocol и attrs. Блок sniffing входящего подключения принимает destOverride плюс списки исключений domainsExcluded и ipsExcluded, которые пропускают переопределение адресата для совпавших доменов / IP (наряду с metadataOnly и routeOnly).
  • Балансировщики со strategy: leastPing работают только при настроенном observatory или burst-observatory.
  • ruleTag позволяет управлять правилами во время работы через gRPC RoutingService (см. API).

Сравнение с другими ядрами ​

  • sing-box использует структурированные правила в snake_case с явными полями по каждому критерию (domain_suffix, ip_cidr, process_name). Правила могут нести action (route, direct, reject, hijack-dns, sniff, resolve, route-options), а не только тег исходящего подключения. См. Маршрутизация — sing-box.
  • mihomo использует компактные строковые правила (DOMAIN-SUFFIX,example.com,proxy), вычисляемые по порядку, плюс отдельный механизм rule-providers: для удалённых списков правил. См. Маршрутизация — mihomo.

Исходный код: infra/conf/router.go:21-75 · v26.9.9 (52a412d)

Core Tutorial от Argsment