---
url: /development/lua/reference/hook-dns.md
---
# DNS Hook

核心在内置 DNS 查询中调用 `dns.script` 中的全局函数 `HandleDNSQuery`。配置接入和完整示例见[DNS 脚本指南](../guide/dns.md)。

## API 索引

| 分类 | 成员                                     | 说明          |
| ---- | ---------------------------------------- | ------------- |
| Hook | [`HandleDNSQuery(...)`](#handlednsquery) | 处理 DNS 查询 |

## Hook 接口

### HandleDNSQuery(...)

```lua
function HandleDNSQuery(domain, ipv4, ipv6, fake)
    return ips, ttl, err
end
```

处理一次 DNS 查询，返回 IP slice、TTL 或错误。

#### 参数

核心始终传入全部四个参数，均非 `nil`。

| 参数     | 类型      | 说明                         |
| -------- | --------- | ---------------------------- |
| `domain` | `string`  | 待查询域名，非空且已转为小写 |
| `ipv4`   | `boolean` | 是否允许查询 IPv4 地址       |
| `ipv6`   | `boolean` | 是否允许查询 IPv6 地址       |
| `fake`   | `boolean` | 本次查询是否允许 FakeDNS     |

`ipv4`、`ipv6` 已受全局 [`queryStrategy`](../../../config/dns.md#dnsobject) 限制，至少一个为 `true`。向上游查询时通常原样传递这三个 boolean 参数。

#### 返回值

| 返回值 | 类型                                                | 说明                                                            |
| ------ | --------------------------------------------------- | --------------------------------------------------------------- |
| `ips`  | [`[]net.IP`](./data-types.md#net-ip-1) 或 `nil`     | 查询结果，必须是 slice，不接受 Lua 数组                         |
| `ttl`  | `number` 或 `nil`                                   | TTL（秒）；`err == nil` 时必须为 `0 .. 4294967295` 范围内的整数 |
| `err`  | [`error`](./data-types.md#error)、`string` 或 `nil` | 仅 `nil` 表示无错误                                             |

#### 行为约定

核心依次校验 `err`、`ttl`、`ips`，遇到错误即停止；`err` 非 `nil` 时忽略其余两项。无错误时，即使 IP 结果为空，也必须提供合法 TTL。

返回空响应可写 `return nil, 0, nil`；错误应放在第三个位置，例如 `return nil, nil, "查询失败"`。

| 脚本结果                                             | 核心处理               |
| ---------------------------------------------------- | ---------------------- |
| 校验通过且 `ips` 非空                                | 本次查询成功           |
| `err == nil`、TTL 合法，但 `ips` 为 `nil` 或空 slice | 本次查询失败（空响应） |
| 返回错误、返回值类型错误或执行异常                   | 本次查询失败           |

#### 示例

可以直接转发 [`serverObj:Query`](./module-dns.md#query) 的三个返回值：

```lua
local dns = require("xray.dns")
local serverObj = dns.Servers[1]

function HandleDNSQuery(domain, ipv4, ipv6, fake)
    return serverObj:Query(domain, ipv4, ipv6, fake)
end
```
