# Маршрутизация

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

Например, распространенным сценарием использования является разделение внутреннего и внешнего трафика. Xray может использовать внутренние механизмы для определения трафика из разных регионов, а затем отправлять его на разные исходящие прокси.

Более подробный анализ функции маршрутизации: [Краткий анализ функции маршрутизации (routing)](../document/level-1/routing-lv1-part1.md).

## RoutingObject

`RoutingObject` соответствует элементу `routing` в файле конфигурации.

```json
{
  "routing": {
    "domainStrategy": "AsIs",
    "domainMatcher": "hybrid",
    "rules": [],
    "balancers": []
  }
}
```

> `domainStrategy`: "AsIs" | "IPIfNonMatch" | "IPOnDemand"

Стратегия разрешения доменных имен. Используются разные стратегии в зависимости от настройки.

- `"AsIs"`: для выбора маршрута используются только доменные имена. Значение по умолчанию.
- `"IPIfNonMatch"`: если доменное имя не соответствует ни одному правилу, доменное имя разрешается в IP-адрес (запись A или запись AAAA) для повторного сопоставления;
  - Если у доменного имени несколько записей A, предпринимается попытка сопоставить все записи A, пока одна из них не будет соответствовать какому-либо правилу;
  - Разрешенный IP-адрес используется только при выборе маршрута, в пересылаемых пакетах данных по-прежнему используется исходное доменное имя;
- `"IPOnDemand"`: если при сопоставлении встречается любое правило на основе IP-адреса, доменное имя немедленно разрешается в IP-адрес для сопоставления;

> `domainMatcher`: "hybrid" | "linear"

Алгоритм сопоставления доменных имен. Используются разные алгоритмы в зависимости от настройки. Этот параметр влияет на все `RuleObject`, для которых не указан отдельный алгоритм сопоставления.

- `"hybrid"`: используется новый алгоритм сопоставления доменных имен, который работает быстрее и занимает меньше места. Значение по умолчанию.
- `"linear"`: используется старый алгоритм сопоставления доменных имен.

> `rules`: \[[RuleObject](#ruleobject)\]

Соответствует массиву, каждый элемент которого является правилом.

Для каждого соединения маршрутизация будет выполняться в соответствии с этими правилами сверху вниз. Когда встречается первое действующее правило, это соединение перенаправляется на указанный им `outboundTag` или `balancerTag`.

::: tip
Если ни одно правило не совпадает, трафик по умолчанию отправляется через первый исходящий канал.
:::

> `balancers`: \[ [BalancerObject](#balancerobject) \]

Массив, каждый элемент которого является конфигурацией балансировщика нагрузки.

Когда правило указывает на балансировщик нагрузки, Xray выбирает исходящий канал через этот балансировщик нагрузки, а затем перенаправляет трафик через него.

### RuleObject

```json
{
  "domainMatcher": "hybrid",
  "type": "field",
  "domain": ["baidu.com", "qq.com", "geosite:cn"],
  "ip": ["0.0.0.0/8", "10.0.0.0/8", "fc00::/7", "fe80::/10", "geoip:cn"],
  "port": "53,443,1000-2000",
  "sourcePort": "53,443,1000-2000",
  "network": "tcp",
  "source": ["10.0.0.1"],
  "user": ["love@xray.com"],
  "inboundTag": ["tag-vmess"],
  "protocol": ["http", "tls", "quic", "bittorrent"],
  "attrs": { ":method": "GET" },
  "outboundTag": "direct",
  "balancerTag": "balancer",
  "ruleTag": "rule name"
}
```

::: danger
Если указано несколько атрибутов, они должны выполняться **одновременно**, чтобы текущее правило вступило в силу.
:::

> `domainMatcher`: "hybrid" | "linear"

Алгоритм сопоставления доменных имен. Используются разные алгоритмы в зависимости от настройки. Этот параметр имеет приоритет над `domainMatcher`, настроенным в `RoutingObject`.

- `"hybrid"`: используется новый алгоритм сопоставления доменных имен, который работает быстрее и занимает меньше места. Значение по умолчанию.
- `"linear"`: используется старый алгоритм сопоставления доменных имен.

> `type`: "field"

В настоящее время поддерживается только опция `"field"`.

::: tip
Можно опустить эту строку в Xray-core v1.8.7 или более поздней версии.
:::

> `domain`: \[string\]

Массив, каждый элемент которого представляет собой сопоставление доменного имени. Возможны следующие форматы:

- Простая строка: правило вступает в силу, если эта строка соответствует любой части целевого доменного имени. Например, "sina.com" может соответствовать "sina.com", "sina.com.cn" и "www.sina.com", но не соответствует "sina.cn".
- Регулярное выражение: начинается с `"regexp:"`, остальная часть является регулярным выражением. Правило вступает в силу, если это регулярное выражение соответствует целевому доменному имени. Например, `"regexp:\\\\.goo.\*\\\\.com\$"` соответствует "www.google.com" или "fonts.googleapis.com", но не соответствует "google.com". (Обратите внимание, что в json обратная косая черта, часто используемая в регулярных выражениях, используется как escape-символ, поэтому обратная косая черта `\` в регулярном выражении должна быть заменена на `\\`)
- Поддомен (рекомендуется): начинается с `"domain:"`, остальная часть является доменным именем. Правило вступает в силу, если это доменное имя является целевым доменным именем или его поддоменом. Например, "domain:xray.com" соответствует "www.xray.com", "xray.com", но не соответствует "wxray.com".
- Полное совпадение: начинается с `"full:"`, остальная часть является доменным именем. Правило вступает в силу, если это доменное имя полностью соответствует целевому доменному имени. Например, "full:xray.com" соответствует "xray.com", но не соответствует "www.xray.com".
- Предопределенный список доменов: начинается с `"geosite:"`, остальная часть является именем, например, `geosite:google` или `geosite:cn`. Имена и списки доменов см. в разделе [Предопределенные списки доменов](#предопределенные-списки-доменов).
- Загрузка доменных имен из файла: имеет вид `"ext:файл:тег"`, должно начинаться с `ext:` (в нижнем регистре), за которым следует имя файла и тег, файл хранится в [каталоге ресурсов](./features/env.md#путь-к-файлу-ресурсов), формат файла такой же, как у `geosite.dat`, тег должен существовать в файле.

::: tip
`"ext:geoip.dat:cn"` эквивалентно `"geoip:cn"`
:::

> `ip`: \[string\]

Массив, каждый элемент которого представляет собой диапазон IP-адресов. Правило вступает в силу, если какой-либо элемент соответствует целевому IP-адресу. Возможны следующие форматы:

- IP-адрес: например, `"127.0.0.1"`.
- [CIDR](https://ru.wikipedia.org/wiki/Бесклассовая_междоменная_маршрутизация): например, `"10.0.0.0/8"`, также можно использовать `"0.0.0.0/0"` `"::/0"` для указания всех IPv4- или IPv6-адресов.
- Предопределенный список IP-адресов: этот список встроен в каждый установочный пакет Xray, имя файла - `geoip.dat`. Формат использования: `"geoip:код_страны"`, должно начинаться с `geoip:` (в нижнем регистре), за которым следует двухбуквенный код страны, поддерживаются почти все страны с доступом в Интернет.
  - Специальное значение: `"geoip:private"`, включает в себя все частные адреса, например, `127.0.0.1`.
  - Функция инверсии (!), `"geoip:!cn"` означает результаты, не входящие в `geoip:cn`.
- Загрузка IP-адресов из файла: имеет вид `"ext:файл:тег"`, должно начинаться с `ext:` (в нижнем регистре), за которым следует имя файла и тег, файл хранится в [каталоге ресурсов](./features/env.md#путь-к-файлу-ресурсов), формат файла такой же, как у `geoip.dat`, тег должен существовать в файле.

> `port`: number | string

Диапазон портов назначения, возможны три формата:

- `"a-b"`: a и b являются положительными целыми числами, меньшими 65536. Этот диапазон является замкнутым интервалом, правило вступает в силу, если порт назначения попадает в этот диапазон.
- `a`: a является положительным целым числом, меньшим 65536. Правило вступает в силу, если порт назначения равен a.
- Смесь двух вышеуказанных форматов, разделенных запятой ",". Например: `"53,443,1000-2000"`.

> `sourcePort`: number | string

Порт источника, возможны три формата:

- `"a-b"`: a и b являются положительными целыми числами, меньшими 65536. Этот диапазон является замкнутым интервалом, правило вступает в силу, если порт источника попадает в этот диапазон.
- `a`: a является положительным целым числом, меньшим 65536. Правило вступает в силу, если порт источника равен a.
- Смесь двух вышеуказанных форматов, разделенных запятой ",". Например: `"53,443,1000-2000"`.

> `network`: "tcp" | "udp" | "tcp,udp"

Допустимые значения: "tcp", "udp" или "tcp,udp". Правило вступает в силу, если тип соединения соответствует указанному.

Поскольку ядро явно поддерживает только два протокола четвёртого уровня — TCP и UDP, то маршрут с условием, включающим только `"network": "tcp,udp"`, может использоваться для **catch-all** маршрутизации всего трафика. Пример использования — поместить такой маршрут в самый конец всех правил маршрутизации для назначения выходного соединения по умолчанию, если не подходит ни одно из других правил (иначе ядро по умолчанию использует первое правило).

Конечно, другие варианты, явно подходящие для маршрутизации любого трафика, такие как указание диапазона портов **1-65535** или IP-адресов **0.0.0.0/0 + ::/0**, также имеют аналогичное действие.

> `source`: \[string\]

Массив, каждый элемент которого представляет собой диапазон IP-адресов. Возможные форматы: IP-адрес, CIDR, GeoIP и загрузка IP-адресов из файла. Правило вступает в силу, если какой-либо элемент соответствует IP-адресу источника.

> `user`: \[string\]

Массив, каждый элемент которого является адресом электронной почты. Правило вступает в силу, если какой-либо элемент соответствует пользователю-источнику.

Аналогично доменному имени, также поддерживается сопоставление с помощью регулярных выражений, начинающихся с `regexp:`. (Также необходимо заменить `\` на `\\`, см. объяснение в разделе `domain`)

> `inboundTag`: \[string\]

Массив, каждый элемент которого является тегом. Правило вступает в силу, если какой-либо элемент соответствует тегу входящего протокола.

> `protocol`: \[ "http" | "tls" | "quic" | "bittorrent" \]

Массив, каждый элемент которого представляет собой протокол. Правило вступает в силу, если какой-либо протокол соответствует типу протокола текущего соединения.
`http` поддерживает только 1.0 и 1.1, h2 пока не поддерживается. (Трафик h2 в открытом виде также встречается очень редко)
`tls` TLS 1.0 ~ 1.3
`quic` из-за сложности этого протокола, перехват может иногда не срабатывать.
`bittorrent` только самый базовый перехват, может не сработать для многих шифрований и обфускаций.

::: tip
Необходимо включить опцию `sniffing` во входящем прокси, чтобы определить тип протокола, используемого соединением.
:::

> `attrs`: object

JSON-объект, где ключи и значения являются строками. Используется для проверки значений атрибутов HTTP-трафика (по очевидным причинам, поддерживаются только 1.0 и 1.1). Правило срабатывает, если HTTP-заголовки содержат все указанные ключи, и значения содержат указанную подстроку. Ключи не чувствительны к регистру. Значения поддерживают использование регулярных выражений.

Также поддерживаются псевдозаголовки h2, такие как `:method` и `:path`, для сопоставления метода и пути (хотя в HTTP/1.1 эти заголовки отсутствуют)

Для метода, отличного от CONNECT, входящего HTTP-запроса, `attrs` можно получить напрямую, для других входящих запросов необходимо включить `sniffing`, чтобы получить эти значения для сопоставления.

Примеры:

- Проверка HTTP GET: `{":method": "GET"}`
- Проверка HTTP Path: `{":path": "/test"}`
- Проверка Content Type: `{"accept": "text/html"}`

> `outboundTag`: string

Соответствует тегу исходящего канала.

> `balancerTag`: string

Соответствует тегу балансировщика нагрузки.

::: tip
Необходимо указать либо `balancerTag`, либо `outboundTag`. Если указаны оба, используется `outboundTag`.
:::

> `ruleTag`: string

Необязательно, не имеет фактического эффекта, используется только для идентификации имени этого правила.

Если установлено, при совпадении с этим правилом в журнал с уровнем Info будет выводиться соответствующая информация, используемая для отладки того, какое правило маршрутизации сработало.

### BalancerObject

Конфигурация балансировщика нагрузки. Когда балансировщик нагрузки активен, он выбирает наиболее подходящий исходящий канал из указанных исходящих каналов в соответствии с конфигурацией и перенаправляет трафик через него.

```json
{
  "tag": "balancer",
  "selector": [],
  "fallbackTag": "outbound",
  "strategy": {}
}
```

> `tag`: string

Тег этого балансировщика нагрузки, используется для сопоставления с `balancerTag` в `RuleObject`.

> `selector`: \[ string \]

Массив строк, каждая из которых будет использоваться для сопоставления с префиксом тега исходящего канала. Например, для следующих тегов исходящих каналов: `[ "a", "ab", "c", "ba" ]`, `"selector": ["a"]` будет соответствовать `[ "a", "ab" ]`.

Обычно, когда находится несколько исходящих подключений (outbound), они используются для равномерного распределения нагрузки.

> `fallbackTag`: string

Если на основе результатов наблюдения за подключениями все исходящие (outbound) оказываются недоступными, то используется исходящее подключение, указанное в этой настройке.
Примечание: необходимо добавить конфигурацию [observatory](./observatory.md#observatoryobject) или [burstObservatory](./observatory.md#burstobservatoryobject).

> `strategy`: [StrategyObject](#strategyobject)

#### StrategyObject

```json
{
  "type": "roundRobin",
  "settings": {}
}
```

> `type` : "random" | "roundRobin" | "leastPing" | "leastLoad"

- `random`: значение по умолчанию. Случайным образом выбирает соответствующий исходящий прокси.
- `roundRobin`: выбирает соответствующие исходящие прокси по очереди.
- `leastPing` Выбирает исходящий прокси с наименьшей задержкой на основе результатов наблюдения за подключениями. Необходимо добавить конфигурацию [observatory](./observatory.md#observatoryobject) или [burstObservatory](./observatory.md#burstobservatoryobject).
- `leastLoad` Выбирает наиболее стабильный исходящий прокси на основе результатов наблюдения за подключениями. Необходимо добавить конфигурацию [observatory](./observatory.md#observatoryobject) или [burstObservatory](./observatory.md#burstobservatoryobject).

> `settings`: [StrategySettingsObject](#strategysettingsobject)

##### StrategySettingsObject

Это необязательный параметр конфигурации, формат которого различается для разных стратегий балансировки нагрузки. В настоящее время этот параметр конфигурации можно добавить только для стратегии балансировки нагрузки `leastLoad`.

```json
{
  "expected": 2,
  "maxRTT": "1s",
  "tolerance": 0.01,
  "baselines": ["1s"],
  "costs": [
    {
      "regexp": false,
      "match": "tag",
      "value": 0.5
    }
  ]
}
```

> `expected`: number

Количество оптимальных узлов, выбираемых балансировщиком нагрузки. Трафик будет случайным образом распределен между этими узлами.

> `maxRTT`: string

Максимально допустимое время RTT (задержки) при измерении скорости.

> `tolerance`: float number

Максимально допустимая доля неудачных измерений скорости, например, 0.01 означает, что допустим 1% неудачных измерений (похоже, не реализовано).

> `baselines`: \[ string \]

Максимально допустимое стандартное отклонение времени RTT при измерении скорости.

> `costs`: \[ CostObject \]

Необязательный параметр конфигурации, массив, позволяющий задать веса для всех исходящих соединений.

> `regexp`: true | false

Использовать ли регулярные выражения для выбора `Tag` исходящего соединения.

> `match`: string

Сопоставление `Tag` исходящего соединения.

> `value`: float number

Значение веса. Чем больше значение, тем менее вероятно, что соответствующий узел будет выбран.

### Примеры конфигурации балансировки нагрузки

```json
    "routing": {
        "rules": [
            {
                "inboundTag": [
                    "in"
                ],
                "balancerTag": "round"
            }
        ],
        "balancers" : [
            {
                "selector": [
                    "out"
                ],
                "strategy": {
                    "type":"roundRobin"
                },
                "tag": "round"
            }
        ]
    }

    "inbounds": [
        {
            "tag": "in"
        }
    ]

    "outbounds": [
        {
            "tag": "out1"
        },
        {
            "tag": "out2"
        }
    ]
```

### Предопределенные списки доменов

Этот список встроен в каждый установочный пакет Xray, имя файла - `geosite.dat`. Этот файл содержит некоторые распространенные доменные имена. Формат использования: `geosite:имя_файла`, например, `geosite:google` означает фильтрацию маршрутизации или DNS для доменных имен, соответствующих `google` в файле.

Распространенные доменные имена:

- `category-ads`: содержит распространенные доменные имена рекламы.
- `category-ads-all`: содержит распространенные доменные имена рекламы, а также доменные имена поставщиков рекламы.
- `cn`: эквивалентно объединению `geolocation-cn` и `tld-cn`.
- `apple`: содержит большинство доменных имен Apple.
- `google`: содержит большинство доменных имен Google.
- `microsoft`: содержит большинство доменных имен Microsoft.
- `facebook`: содержит большинство доменных имен Facebook.
- `twitter`: содержит большинство доменных имен Twitter.
- `telegram`: содержит большинство доменных имен Telegram.
- `geolocation-cn`: содержит распространенные доменные имена сайтов материкового Китая.
- `geolocation-!cn`: содержит распространенные доменные имена сайтов, не относящихся к материковому Китаю.
- `tld-cn`: содержит домены верхнего уровня, управляемые CNNIC для использования в материковом Китае, например, доменные имена, оканчивающиеся на `.cn`, `.中国`.
- `tld-!cn`: содержит домены верхнего уровня, не используемые в материковом Китае, например, доменные имена, оканчивающиеся на `.tw` (Тайвань), `.jp` (Япония), `.sg` (Сингапур), `.us` (США), `.ca` (Канада) и т.д.

Вы также можете просмотреть полный список доменов здесь: [Domain list community](https://github.com/v2fly/domain-list-community).
