Маршрутизация — 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.7.28 (5ca6f4b)
rules[] — объект правила
Каждое правило — JSON-объект, у которого ключи сопоставления выбирают множество соединений, а ключи цели решают, куда они пойдут. Форма полиморфна: парсер смотрит, какие ключи сопоставления присутствуют.
Ключи сопоставления (все необязательны, объединяются по И):
| Поле | Тип | Описание |
|---|---|---|
type | string | Должно быть "field" (устаревший "chain" и другие типы существовали в V2Ray; сейчас поддерживается только field). |
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). |
port | string | Сопоставление по порту назначения. 80, 80-90, 80,443,8080-8090. |
sourcePort | string | Сопоставление по порту источника (тот же синтаксис). |
network | string | Сопоставление по транспорту. tcp, udp, tcp,udp. |
user | []string | Сопоставление по email-метке пользователя входящего подключения. |
inboundTag | []string | Сопоставление по тегу входящего подключения. |
protocol | []string | Сопоставление по определённому сниффингом прикладному протоколу. http, tls, bittorrent, quic. Сниффинг должен быть включён на входящем подключении. |
attrs | map[string]string | Сопоставление по атрибутам сниффинга (например, Host). |
domainMatcher | string | Реализация сопоставителя доменов. hybrid (по умолчанию, быстрый) или linear. |
Ключи цели (нужен ровно один):
| Поле | Описание |
|---|---|
outboundTag | Отправить совпавший трафик в это исходящее подключение. |
balancerTag | Отправить совпавший трафик в балансировщик (который выберет исходящее подключение из своего пула). |
Плюс поле метаданных:
| Поле | Описание |
|---|---|
ruleTag | Человекочитаемое имя правила. Отображается в API и журналах. |
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`](/ru/xray/observatory)); `leastLoad` выбирает наименее нагруженного. |
fallbackTag | string | (unset) | <outbound tag> | Исходящее подключение, используемое когда пул балансировщика пуст или все его участники недоступны. |
Исходный код: infra/conf/router.go:21-26 · зафиксировано на v26.7.28 (5ca6f4b)
Варианты стратегий
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и — новинка недавних версий Xray —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.7.28 (5ca6f4b)
