# Hook маршрутизации При выборе исходящего подключения ядро вызывает глобальную функцию `HandleRoute` из `routing.script`. Настройка и полные примеры приведены в [руководстве по скриптам маршрутизации](../guide/routing.md). ## Указатель API | Категория | Член API | Описание | | --------- | --------------------------------------- | ---------------------------------------- | | Hook | [`HandleRoute(...)`](#handleroute) | Выбор исходящего подключения для запроса | | Объект | [`routing.Context`](#routing-context) | Контекст маршрутизации текущего запроса | | Метод | [`ctx:GetSourceIPs()`](#getsourceips) | Получение IP источника | | Метод | [`ctx:GetTargetIPs()`](#gettargetips) | Получение IP назначения | | Метод | [`ctx:GetLocalIPs()`](#getlocalips) | Получение локальных IP | | Метод | [`ctx:GetAttributes()`](#getattributes) | Получение атрибутов запроса | ## Интерфейс Hook ### HandleRoute(...) ```lua function HandleRoute(ctx, inboundTag, sourcePort, targetPort, localPort, targetDomain, network, protocol, user, vlessRoute, skipDNSResolve) return outboundTag, ruleTag, err end ``` Выбирает исходящее подключение для текущего запроса и при необходимости возвращает имя правила или ошибку. #### Параметры Ядро всегда передаёт все 11 параметров в указанном порядке; ни один из них не равен `nil`. В определении функции можно опустить неиспользуемые параметры в конце — это не меняет значения, передаваемые ядром. | Параметр | Тип | Описание | Пустые значения и значения по умолчанию | | ---------------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | `ctx` | [`routing.Context`](#routing-context) | Контекст текущего запроса | Всегда допустимый `userdata` | | `inboundTag` | `string` | Тег входящего подключения | `""`, если тег не задан или нет входящей информации | | `sourcePort` | `number` | Порт источника, `0 .. 65535` | `0`, если нет допустимого адреса источника | | `targetPort` | `number` | Порт назначения, `0 .. 65535` | `0`, если нет допустимого адреса назначения | | `localPort` | `number` | Локальный порт входящего соединения, `0 .. 65535` | `0`, если нет допустимого локального адреса | | `targetDomain` | `string` | Действующий домен, обнаруженный анализом трафика, имеет приоритет; иначе используется домен цели соединения. Значение приводится к нижнему регистру | `""`, если цель — IP без действующего обнаруженного домена или нет информации о цели | | `network` | `number` | Тип сети; сравнивается с константами вроде [`router.NetworkTCP`](./module-router.md#константы) | `NetworkUnknown` (`0`), если нет исходящей информации или тип сети неизвестен | | `protocol` | `string` | Протокол, обнаруженный анализом трафика | `""`, если нет информации об обнаруженном протоколе | | `user` | `string` | Email пользователя | `""`, если нет входящей информации, данных пользователя или email не задан | | `vlessRoute` | `number` | Значение маршрута из 7-го и 8-го байтов UUID VLESS, `0 .. 65535` | `0` при отсутствии информации; само значение также может быть 0 | | `skipDNSResolve` | `boolean` | При `true` нужно пропустить DNS-запросы, чтобы избежать петель | `false`, если нет этого флага или дополнительных данных запроса | #### Возвращаемые значения | Значение | Тип | Описание | | ------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------- | | `outboundTag` | `string` или `nil` | Тег исходящего подключения; `nil` или `""` означает, что оно не выбрано | | `ruleTag` | `string` или `nil` | Необязательное имя правила; `nil`, отсутствие значения или `""` означает отсутствие имени | | `err` | [`error`](./data-types.md#error), `string` или `nil` | Только `nil` означает отсутствие ошибки | #### Поведение Ядро последовательно проверяет `err`, `outboundTag` и `ruleTag`, останавливаясь при первой ошибке. Если `err` не равен `nil`, первые два значения игнорируются. Если исходящее подключение не выбрано, `ruleTag` игнорируется. При успехе значения `ruleTag` и `err` в конце можно опустить, например `return "direct"`. Ошибка должна быть в третьей позиции, например `return nil, nil, "ошибка маршрутизации"`; `return nil, "ошибка маршрутизации"` не сообщает об ошибке. | Результат скрипта | Действие ядра | | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------- | | Проверка успешна, `outboundTag` непустой | Использует соответствующее исходящее подключение; если тег не существует, закрывает соединение | | Исходящее подключение не выбрано | Использует исходящее подключение по умолчанию | | Возвращена ошибка, неверный тип значения или исключение выполнения | Записывает ошибку в журнал и пробует исходящее подключение по умолчанию | Исходящее подключение по умолчанию — первое в конфигурации; если оно недоступно, соединение закрывается. Для блокировки трафика явно возвращайте тег настроенного исходящего подключения [`blackhole`](../../../config/outbounds/blackhole.md), а не используйте это поведение с несуществующим тегом. ## Связанные объекты ### routing.Context `routing.Context` представляет контекст маршрутизации текущего запроса и доступен в `HandleRoute` через параметр `ctx`. | Свойство | Описание | | ------------------- | ------------------------------------------------- | | Базовый тип Go | Интерфейс `routing.Context` из `features/routing` | | Представление в Lua | `userdata` | | Получение | Первый параметр `HandleRoute`, передаваемый ядром | Все методы ниже не принимают дополнительных параметров. Операции с IP и срезами описаны в разделе [Типы данных](./data-types.md). #### GetSourceIPs ```lua local ips = ctx:GetSourceIPs() ``` Получает IP-адреса источника запроса. **Параметры** Дополнительных параметров нет. **Возвращаемые значения** | Значение | Тип | Описание | | -------- | ------------------------------------------------ | --------------------------------- | | `ips` | [`[]net.IP`](./data-types.md#net-ip-1) или `nil` | Список IP соответствующего адреса | **Поведение** Возвращает `nil`, если нет входящего подключения, адрес источника недопустим или не является IP-адресом. #### GetTargetIPs ```lua local ips = ctx:GetTargetIPs() ``` Получает IP-адреса назначения запроса. **Параметры** Дополнительных параметров нет. **Возвращаемые значения** | Значение | Тип | Описание | | -------- | ------------------------------------------------ | --------------------------------- | | `ips` | [`[]net.IP`](./data-types.md#net-ip-1) или `nil` | Список IP соответствующего адреса | **Поведение** Возвращает `nil`, если нет исходящего подключения, адрес назначения недопустим или является доменным именем. #### GetLocalIPs ```lua local ips = ctx:GetLocalIPs() ``` Получает локальные IP-адреса входящего соединения. **Параметры** Дополнительных параметров нет. **Возвращаемые значения** | Значение | Тип | Описание | | -------- | ------------------------------------------------ | --------------------------------- | | `ips` | [`[]net.IP`](./data-types.md#net-ip-1) или `nil` | Список IP соответствующего адреса | **Поведение** Возвращает `nil`, если нет входящего подключения, локальный адрес недопустим или не является IP-адресом. #### GetAttributes ```lua local attributes = ctx:GetAttributes() ``` Получает атрибуты текущего запроса. **Параметры** Дополнительных параметров нет. **Возвращаемые значения** | Значение | Тип | Описание | | ------------ | ------------------- | ----------------------------------- | | `attributes` | `map[string]string` | Всегда `userdata`; никогда не `nil` | **Поведение** Читайте атрибуты через `attributes[key]`, где `key` должен быть строкой. Существующий ключ возвращает строку (возможно `""`), отсутствующий — `nil`. Значение и использование атрибутов описаны в поле [`attrs`](../../../config/routing.md#ruleobject) конфигурации маршрутизации. **Пример** ```lua local attributes = ctx:GetAttributes() if attributes[":method"] == "GET" then return "direct", "lua-get" end ```