mirror of
https://github.com/XTLS/Xray-docs-next.git
synced 2026-10-11 16:58:22 +03:00
182 lines
10 KiB
Markdown
182 lines
10 KiB
Markdown
# Routing Hook
|
|
|
|
The core calls the global `HandleRoute` function in `routing.script` when selecting an outbound. See the [Routing Scripts guide](../guide/routing.md) for configuration and complete examples.
|
|
|
|
## API Index
|
|
|
|
| Category | Member | Description |
|
|
| -------- | --------------------------------------- | ------------------------------------- |
|
|
| Hook | [`HandleRoute(...)`](#handleroute) | Select an outbound for a request |
|
|
| Object | [`routing.Context`](#routing-context) | The current request's routing context |
|
|
| Method | [`ctx:GetSourceIPs()`](#getsourceips) | Get source IPs |
|
|
| Method | [`ctx:GetTargetIPs()`](#gettargetips) | Get target IPs |
|
|
| Method | [`ctx:GetLocalIPs()`](#getlocalips) | Get local IPs |
|
|
| Method | [`ctx:GetAttributes()`](#getattributes) | Get request attributes |
|
|
|
|
## Hook Interface
|
|
|
|
### HandleRoute(...)
|
|
|
|
```lua
|
|
function HandleRoute(ctx, inboundTag, sourcePort, targetPort,
|
|
localPort, targetDomain, network, protocol, user,
|
|
vlessRoute, skipDNSResolve)
|
|
return outboundTag, ruleTag, err
|
|
end
|
|
```
|
|
|
|
Selects an outbound for the current request, optionally returning a rule name or an error.
|
|
|
|
#### Parameters
|
|
|
|
The core always passes all 11 parameters in the order shown above, and none is `nil`. You can omit unused trailing parameters from the function definition; this does not change the values passed by the core.
|
|
|
|
| Parameter | Type | Description | Empty and Default Values |
|
|
| ---------------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
| `ctx` | [`routing.Context`](#routing-context) | Current request context | Always valid `userdata` |
|
|
| `inboundTag` | `string` | Inbound tag | `""` if the inbound has no tag or inbound information is unavailable |
|
|
| `sourcePort` | `number` | Source port, `0 .. 65535` | `0` if no valid source address is available |
|
|
| `targetPort` | `number` | Target port, `0 .. 65535` | `0` if no valid target address is available |
|
|
| `localPort` | `number` | Local port of the inbound connection, `0 .. 65535` | `0` if no valid local address is available |
|
|
| `targetDomain` | `string` | The effective sniffed domain takes precedence over the connection's target domain; converted to lowercase | `""` if the target is an IP without an effective sniffed domain, or target information is unavailable |
|
|
| `network` | `number` | Network type; compare with constants such as [`router.NetworkTCP`](./module-router.md#constants) | `NetworkUnknown` (`0`) if outbound information is unavailable or the network type is unknown |
|
|
| `protocol` | `string` | Sniffed protocol | `""` if sniffed protocol information is unavailable |
|
|
| `user` | `string` | User email | `""` if inbound or user information is unavailable, or no email is set |
|
|
| `vlessRoute` | `number` | Routing value formed from bytes 7 and 8 of the VLESS UUID, `0 .. 65535` | `0` if unavailable; the value itself may also be 0 |
|
|
| `skipDNSResolve` | `boolean` | When `true`, DNS queries must be skipped to avoid loops | `false` if the flag or additional request information is unavailable |
|
|
|
|
#### Return Values
|
|
|
|
| Return value | Type | Description |
|
|
| ------------- | ---------------------------------------------------- | ---------------------------------------------------------- |
|
|
| `outboundTag` | `string` or `nil` | Outbound tag; `nil` or `""` means no outbound was selected |
|
|
| `ruleTag` | `string` or `nil` | Optional rule name; `nil`, omission, or `""` means no name |
|
|
| `err` | [`error`](./data-types.md#error), `string`, or `nil` | Only `nil` means no error |
|
|
|
|
#### Behavior
|
|
|
|
The core validates `err`, `outboundTag`, and `ruleTag` in that order, stopping at the first error. When `err` is non-`nil`, the first two values are ignored. When no outbound is selected, `ruleTag` is ignored.
|
|
|
|
On success, trailing `ruleTag` and `err` values may be omitted, for example `return "direct"`. An error must be in the third position, for example `return nil, nil, "routing failed"`; `return nil, "routing failed"` does not report an error.
|
|
|
|
| Script result | Core behavior |
|
|
| ----------------------------------------------------------------- | -------------------------------------------------------------------------------- |
|
|
| Validation succeeds and `outboundTag` is non-empty | Uses the corresponding outbound; closes the connection if the tag does not exist |
|
|
| No outbound selected | Uses the default outbound |
|
|
| Returned error, invalid return-value type, or execution exception | Logs the error and tries the default outbound |
|
|
|
|
The default outbound is the first outbound in the configuration; the connection is closed if no default outbound is available. To block traffic, explicitly return a configured [`blackhole`](../../../config/outbounds/blackhole.md) outbound tag instead of relying on this behavior with a nonexistent tag.
|
|
|
|
## Related Objects
|
|
|
|
### routing.Context
|
|
|
|
`routing.Context` represents the current request's routing context, accessed through the `ctx` parameter in `HandleRoute`.
|
|
|
|
| Property | Description |
|
|
| ------------------ | ------------------------------------------------------ |
|
|
| Underlying Go type | The `routing.Context` interface in `features/routing` |
|
|
| Lua representation | `userdata` |
|
|
| Obtained from | The first argument passed by the core to `HandleRoute` |
|
|
|
|
All methods below take no additional parameters. See [Data Types](./data-types.md) for IP and slice operations.
|
|
|
|
#### GetSourceIPs
|
|
|
|
```lua
|
|
local ips = ctx:GetSourceIPs()
|
|
```
|
|
|
|
Gets the request's source IPs.
|
|
|
|
**Parameters**
|
|
|
|
No additional parameters.
|
|
|
|
**Return Values**
|
|
|
|
| Return value | Type | Description |
|
|
| ------------ | ----------------------------------------------- | ------------------------------------- |
|
|
| `ips` | [`[]net.IP`](./data-types.md#net-ip-1) or `nil` | IP list for the corresponding address |
|
|
|
|
**Behavior**
|
|
|
|
Returns `nil` if there is no inbound, the source address is invalid, or it is not an IP address.
|
|
|
|
#### GetTargetIPs
|
|
|
|
```lua
|
|
local ips = ctx:GetTargetIPs()
|
|
```
|
|
|
|
Gets the request's target IPs.
|
|
|
|
**Parameters**
|
|
|
|
No additional parameters.
|
|
|
|
**Return Values**
|
|
|
|
| Return value | Type | Description |
|
|
| ------------ | ----------------------------------------------- | ------------------------------------- |
|
|
| `ips` | [`[]net.IP`](./data-types.md#net-ip-1) or `nil` | IP list for the corresponding address |
|
|
|
|
**Behavior**
|
|
|
|
Returns `nil` if there is no outbound, the target address is invalid, or it is a domain name.
|
|
|
|
#### GetLocalIPs
|
|
|
|
```lua
|
|
local ips = ctx:GetLocalIPs()
|
|
```
|
|
|
|
Gets the local IPs of the inbound connection.
|
|
|
|
**Parameters**
|
|
|
|
No additional parameters.
|
|
|
|
**Return Values**
|
|
|
|
| Return value | Type | Description |
|
|
| ------------ | ----------------------------------------------- | ------------------------------------- |
|
|
| `ips` | [`[]net.IP`](./data-types.md#net-ip-1) or `nil` | IP list for the corresponding address |
|
|
|
|
**Behavior**
|
|
|
|
Returns `nil` if there is no inbound, the local address is invalid, or it is not an IP address.
|
|
|
|
#### GetAttributes
|
|
|
|
```lua
|
|
local attributes = ctx:GetAttributes()
|
|
```
|
|
|
|
Gets the current request's attributes.
|
|
|
|
**Parameters**
|
|
|
|
No additional parameters.
|
|
|
|
**Return Values**
|
|
|
|
| Return value | Type | Description |
|
|
| ------------ | ------------------- | ------------------------------ |
|
|
| `attributes` | `map[string]string` | Always `userdata`; never `nil` |
|
|
|
|
**Behavior**
|
|
|
|
Read attributes with `attributes[key]`, where `key` must be a string. An existing key returns a string (possibly `""`); a missing key returns `nil`.
|
|
|
|
See the [`attrs`](../../../config/routing.md#ruleobject) field in the routing configuration for the meaning and use of attributes.
|
|
|
|
**Example**
|
|
|
|
```lua
|
|
local attributes = ctx:GetAttributes()
|
|
if attributes[":method"] == "GET" then
|
|
return "direct", "lua-get"
|
|
end
|
|
```
|