Xray-core: Add Lua script for dns and routing

https://github.com/XTLS/Xray-core/pull/6823
This commit is contained in:
Meow
2026-10-11 09:55:19 +08:00
parent 4c8f3b2b7e
commit f179efd35d
48 changed files with 4950 additions and 0 deletions
@@ -0,0 +1,181 @@
# 路由 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
```