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,139 @@
# xray.dns
Предоставляет интерфейсы DNS-запросов и доступа к вышестоящим серверам.
```lua
local dns = require("xray.dns")
```
## Указатель API
| Категория | Член API | Описание |
| --------- | ----------------------------------------------------- | ---------------------------------- |
| Функция | [`dns.Query(domain, ipv4, ipv6, fake)`](#dns-query) | Запрос через DNS-клиент Xray |
| Поле | [`dns.Servers`](#dns-servers) | Массив вышестоящих серверов |
| Объект | [`serverObj`](#server) | Отдельный вышестоящий DNS-сервер |
| Поле | [`serverObj.ID`](#id) | Идентификатор сервера |
| Метод | [`serverObj:Query(domain, ipv4, ipv6, fake)`](#query) | Прямой запрос к указанному серверу |
## Функции
### dns.Query
```lua
local ips, ttl, err = dns.Query(domain, ipv4, ipv6, fake)
```
Запрашивает домен через DNS-клиент Xray. В Hook DNS недоступен, поскольку скрипт заменяет именно этот процесс обработки запросов.
**Параметры**
| Параметр | Тип | Описание |
| -------- | --------- | ------------------------- |
| `domain` | `string` | Запрашиваемый домен |
| `ipv4` | `boolean` | Разрешены ли запросы IPv4 |
| `ipv6` | `boolean` | Разрешены ли запросы IPv6 |
| `fake` | `boolean` | Разрешён ли FakeDNS |
**Возвращаемые значения**
| Значение | Тип | Описание |
| -------- | ------------------------------------------------ | ------------------------------------------------------------ |
| `ips` | [`[]net.IP`](./data-types.md#net-ip-1) или `nil` | Результаты запроса |
| `ttl` | `number` | TTL в секундах, диапазон `0 .. 4294967295`; никогда не `nil` |
| `err` | [`error`](./data-types.md#error) или `nil` | Ошибка запроса; `nil` означает отсутствие ошибки |
**Поведение**
Все четыре параметра нужно передать явно с правильными типами, иначе возникает исключение Lua.
Запрос учитывает глобальные ограничения типов запросов клиента, Hosts и настройки вышестоящих серверов. Если настроен [скрипт DNS](../guide/dns.md), запрос также передаётся ему. Если встроенный DNS не настроен, используется системный DNS.
При успехе возвращается непустой срез IP; при ошибке запроса или отсутствии доступных адресов — `nil, 0, err`.
**Пример**
```lua
local ips, ttl, err = dns.Query("example.com", true, true, false)
if err == nil and ips ~= nil and #ips > 0 then
local firstIP = ips[1]:String()
end
```
## Поля
### dns.Servers
```lua
local servers = dns.Servers
```
| Имя | Тип | Описание |
| ------------- | ------- | ------------------------------------------------------------------------------ |
| `dns.Servers` | `table` | Массив [`serverObj`](#server), индексы с 1, порядок соответствует конфигурации |
При использовании встроенного DNS список содержит настроенные вышестоящие серверы. Если DNS или его серверы не настроены, список содержит только `localhost` (системный DNS).
Для перебора списка используйте `ipairs`; при выходе индекса за границы `servers[i]` равен `nil`.
**Пример**
```lua
for _, serverObj in ipairs(dns.Servers) do
local id = serverObj.ID
end
```
## Объекты
### server
`serverObj` представляет вышестоящий DNS-сервер с его идентификатором и методом запроса.
| Свойство | Описание |
| ------------------- | --------------------------------------------- |
| Реализация в Go | `luaDNSServer` из `app/dns` |
| Представление в Lua | `table` |
| Получение | Элемент массива [`dns.Servers`](#dns-servers) |
#### ID
```lua
local id = serverObj.ID
```
| Имя | Тип | Описание |
| -------------- | -------- | ------------------------------------------------------------------------------------------------ |
| `serverObj.ID` | `string` | Поле `id` в [конфигурации DNS-сервера](../../../config/dns.md#dnsserverobject); никогда не `nil` |
Если `id` не задан, значение равно `""`, в том числе у серверов, настроенных строками. Автоматически добавленный системный DNS имеет ID `"localhost"`.
Если нужно различать серверы по ID, самостоятельно задайте уникальные значения: ядро не проверяет дубликаты.
#### Query
```lua
local ips, ttl, err = serverObj:Query(domain, ipv4, ipv6, fake)
```
Запрашивает вышестоящий сервер, представленный `serverObj`.
**Параметры и возвращаемые значения**
Требования к параметрам и типы возвращаемых значений такие же, как у [`dns.Query`](#dns-query).
**Поведение**
Обычно настроенный сервер при успехе возвращает непустой срез IP, TTL и `nil`. При ошибке запроса, отсутствии адресов, удовлетворяющих условиям, или запросе FakeDNS с `fake == false` возвращается `nil, 0, err`.
Запрашивает этот сервер напрямую, обходя глобальные Hosts и скрипт DNS. Собственные настройки сервера `queryStrategy`, кеш, `timeoutMs`, `clientIP`, `tag`, а также `expectedIPs` / `unexpectedIPs` и соответствующие `actPrior` / `actUnprior` продолжают действовать.
**Пример**
Вернуть результат запроса к первому серверу напрямую из Hook DNS:
```lua
function HandleDNSQuery(domain, ipv4, ipv6, fake)
return dns.Servers[1]:Query(domain, ipv4, ipv6, fake)
end
```