Маршрутизация — Xray-core
Блок routing — это движок, решающий, какое исходящее подключение использует соединение. Он содержит список правил (сопоставляются по порядку, побеждает первое), глобальную domainStrategy и именованные балансировщики balancers, которые можно указывать как цель правила.
Параметры верхнего уровня
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
rules | []json.RawMessage | [] | <rule object array> | Правила маршрутизации, вычисляемые в порядке объявления. Побеждает первое совпавшее правило. |
domainStrategy | *string | AsIs | AsIs | IpIfNonMatch | IpOnDemand | Как домены назначения разрешаются для сопоставления правил. AsIs оставляет домены строками (совпадают только доменные правила); IpIfNonMatch разрешает в IP, когда не совпало ни одно доменное правило; IpOnDemand разрешает заранее, как только есть IP-правила. |
balancers | []*BalancingRule | [] | [BalancingRule] | Именованные балансировщики нагрузки, используемые как balancerTag в целях правил. |
Исходный код: infra/conf/router.go:71-75 · зафиксировано на v26.9.9 (52a412d)
rules[] — объект правила
Каждое правило — JSON-объект, у которого ключи сопоставления выбирают множество соединений, а ключи цели решают, куда они пойдут. Форма полиморфна: парсер смотрит, какие ключи сопоставления присутствуют.
Ключи сопоставления (все необязательны, объединяются по И):
| Поле | Тип | Описание |
|---|---|---|
type | string | Должно быть "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. |
port | string | Сопоставление по порту назначения. 80, 80-90, 80,443,8080-8090. |
sourcePort | string | Сопоставление по порту источника (тот же синтаксис). |
localIP | []string | Сопоставление по локальному адресу, на который пришло соединение (IP самого входящего). Тот же синтаксис, что и ip. |
localPort | string | Сопоставление по локальному порту, на который пришло соединение (порт входящего). Тот же синтаксис, что и port. |
network | string | Сопоставление по транспорту. tcp, udp, tcp,udp. |
user | []string | Сопоставление по email-метке пользователя входящего подключения. |
vlessRoute | string | Только для входящих VLESS: сопоставление по 7–8-му байтам UUID, присланного клиентом, — третьей группе UUID, прочитанной как шестнадцатеричное число (например, …-01bb-… = 443). Синтаксис списка портов ("443", "1-100,443"). Позволяет одному серверу маршрутизировать по значению, заложенному в UUID клиентов. |
inboundTag | []string | Сопоставление по тегу входящего подключения. |
protocol | []string | Сопоставление по определённому сниффингом прикладному протоколу. http, tls, bittorrent, quic. Сниффинг должен быть включён на входящем подключении. |
attrs | map[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 и т. д.; без учёта регистра). Вычисляется один раз при построении правила — удобно для одной конфигурации на нескольких устройствах. |
domainMatcher | string | Реализация сопоставителя доменов. hybrid (по умолчанию, быстрый) или linear. |
Ключи цели (нужен ровно один):
| Поле | Описание |
|---|---|
outboundTag | Отправить совпавший трафик в это исходящее подключение. |
balancerTag | Отправить совпавший трафик в балансировщик (который выберет исходящее подключение из своего пула). |
Плюс поля метаданных:
| Поле | Описание |
|---|---|
ruleTag | Человекочитаемое имя правила. Отображается в API и журналах. |
webhook | { url, deduplication, headers }. При срабатывании правила на url отправляется POST с JSON-событием (теги входящего / исходящего, источник, назначение, email пользователя, протокол, отметка времени и т. д.; тайм-аут 5 с; принимается и URL Unix-сокета). deduplication подавляет повторные события для того же email пользователя в течение указанного числа секунд (0 — выключено); headers добавляются к запросу. На маршрутизацию не влияет. |
balancers[]
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
tag | string | (required) | <string> | Имя балансировщика. Используется полем balancerTag правил маршрутизации. |
selector | StringList | (required) | [<outbound-tag prefix>] | Префиксы тегов исходящих подключений. Любое исходящее подключение, чей тег начинается с одного из них, включается в пул балансировщика. |
strategy | StrategyConfig | {type: "random"} | {type: "random|leastLoad|leastPing|roundRobin", settings?: {...}} | Стратегия выбора. random берёт любого участника пула; roundRobin перебирает по кругу; leastPing выбирает участника с наименьшей наблюдаемой задержкой (требует observatory); leastLoad выбирает наименее нагруженного. |
fallbackTag | string | (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) с полями настройки проверок доступности.
Примеры
Прямое направление внутрикитайского трафика (канонический паттерн для Китая):
{
"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" }
]
}
}Маршрутизация через балансировщик с выбором по задержке:
{
"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"
}
}Сопоставление по прикладному протоколу (требует сниффинга на входящем подключении):
{
"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)
