---
url: /development/lua/reference/hook-routing.md
---
# 路由 Hook

核心在选择出站时调用 `routing.script` 中的全局函数 `HandleRoute`。配置接入和完整示例见[路由脚本指南](../guide/routing.md)。

## 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`                              | 入站标识                                                               | 入站未设置 tag 或没有入站信息时为 `""`                 |
| `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`                              | VLESS UUID 第 7、8 字节组成的路由值，`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) 出站 tag 而不是利用此特性返回不存在的标识。

## 关联对象

### routing.Context

`routing.Context` 表示当前请求的路由上下文，在 `HandleRoute` 中通过参数 `ctx` 访问。

| 属性        | 说明                                           |
| ----------- | ---------------------------------------------- |
| Go 底层类型 | `features/routing` 中的 `routing.Context` 接口 |
| Lua 表现    | `userdata`                                     |
| 取得方式    | 核心传入的 `HandleRoute` 第一个参数            |

下列方法均无额外参数。IP 及 slice 操作统一见[数据类型](./data-types.md)。

#### GetSourceIPs

```lua
local ips = ctx:GetSourceIPs()
```

取得请求的来源 IP。

**参数**

无额外参数。

**返回值**

| 返回值 | 类型                                            | 说明               |
| ------ | ----------------------------------------------- | ------------------ |
| `ips`  | [`[]net.IP`](./data-types.md#net-ip-1) 或 `nil` | 对应地址的 IP 列表 |

**行为约定**

没有入站、来源地址无效或来源地址不是 IP 时返回 `nil`。

#### 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 列表 |

**行为约定**

没有入站、本地地址无效或本地地址不是 IP 时返回 `nil`。

#### 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
```
