lua-resty-dns-server

OpenResty 的 Lua DNS 服务器驱动

$ opm get vislee/lua-resty-dns-server

名称

lua-resty-dns-server - OpenResty 的 Lua DNS 服务器驱动

状态

此库仍处于早期开发阶段,且尚处于实验阶段。

描述

此 Lua 库为 ngx_lua nginx 模块提供了一个 DNS 服务器驱动。

https://github.com/openresty/stream-lua-nginx-module/#readme

概要

    lua_package_path "/path/to/lua-resty-dns-server/lib/?.lua;;";
    
    stream {
        server {
            listen 53 udp;
            content_by_lua_block {
                local server = require 'resty.dns.server'
                local sock, err = ngx.req.socket()
                if not sock then
                    ngx.log(ngx.ERR, "failed to get the request socket: ", err)
                    return ngx.exit(ngx.ERROR)
                end
    
                local req, err = sock:receive()
                if not req then
                    ngx.log(ngx.ERR, "failed to receive: ", err)
                    return ngx.exit(ngx.ERROR)
                end
    
                local dns = server:new()
                local request, err = dns:decode_request(req)
                if not request then
                    ngx.log(ngx.ERR, "failed to decode request: ", err)
    
                    local resp = dns:encode_response()
                    local ok, err = sock:send(resp)
                    if not ok then
                        ngx.log(ngx.ERR, "failed to send: ", err)
                        ngx.exit(ngx.ERROR)
                    end
    
                    return
                end
    
                local query = request.questions[1]
                ngx.log(ngx.DEBUG, "qname: ", query.qname, " qtype: ", query.qtype)
    
                local cname = "sinacloud.com"
    
                if query.qtype == server.TYPE_CNAME or
                    query.qtype == server.TYPE_AAAA or query.qtype == server.TYPE_A then
    
                    local err = dns:create_cname_answer(query.qname, 600, cname)
                    if err then
                        ngx.log(ngx.ERR, "failed to create cname answer: ", err)
                        return
                    end
                else
                    dns:create_soa_answer("test.com", 600, "a.root-test.com", "vislee.test.com", 1515161223, 1800, 900, 604800, 86400)
                end
    
                local resp = dns:encode_response()
                local ok, err = sock:send(resp)
                if not ok then
                    ngx.log(ngx.ERR, "failed to send: ", err)
                    return
                end
            }
        }
    
        server {
            listen 53;
            content_by_lua_block {
                local bit    = require 'bit'
                local lshift = bit.lshift
                local rshift = bit.rshift
                local band   = bit.band
                local byte   = string.byte
                local char   = string.char
                local server = require 'resty.dns.server'
    
                local sock, err = ngx.req.socket()
                if not sock then
                    ngx.log(ngx.ERR, "failed to get the request socket: ", err)
                    return ngx.exit(ngx.ERROR)
                end
    
                local buf, err = sock:receive(2)
                if not buf then
                    ngx.log(ngx.ERR, "failed to receive: ", err)
                    return ngx.exit(ngx.ERROR)
                end
    
                local len_hi = byte(buf, 1)
                local len_lo = byte(buf, 2)
                local len = lshift(len_hi, 8) + len_lo
                local data, err = sock:receive(len)
                if not data then
                    ngx.log(ngx.ERR, "failed to receive: ", err)
                    return ngx.exit(ngx.ERROR)
                end
    
                local dns = server:new()
                local request, err = dns:decode_request(data)
                if not request then
                    ngx.log(ngx.ERR, "failed to decode dns request: ", err)
                    return
                end
    
                local query = request.questions[1]
                ngx.log(ngx.DEBUG, "qname: ", query.qname, " qtype: ", query.qtype)
    
                if query.qtype == server.TYPE_CNAME or query.qtype == server.TYPE_A then
                    dns:create_cname_answer(query.qname, 600, "sinacloud.com")
                elseif query.qtype == server.TYPE_AAAA then
                    local resp_header, err = dns:create_response_header(server.RCODE_NOT_IMPLEMENTED)
                    resp_header.ra = 0
                else
                    dns:create_soa_answer("test.com", 600, "a.root-test.com", "vislee.test.com", 1515161223, 1800, 900, 604800, 86400)
                end
    
                local resp = dns:encode_response()
                local len = #resp
                local len_hi = char(rshift(len, 8))
                local len_lo = char(band(len, 0xff))
    
                local ok, err = sock:send({len_hi, len_lo, resp})
                if not ok then
                    ngx.log(ngx.ERR, "failed to send: ", err)
                    return
                end
                return
            }
        }
    }
    

方法

new

语法: s, err = class:new()

创建一个 dns.server 对象。出错时返回 nil 和错误消息字符串。

decode_request

语法: request, err = s:decode_request(buf)

解析 DNS 请求。

返回的请求是一个 Lua 表,包含以下一些字段

  • header: header 也是一个 Lua 表,通常包含以下一些字段

名称 ====

lua-resty-dns-server - OpenResty 的 Lua DNS 服务器驱动

目录 =================

* [名称](#name) * [状态](#status) * [描述](#description) * [概要](#synopsis) * [方法](#methods) * [new](#new) * [decode_request](#decode_request) * [create_a_answer](#create_a_answer) * [create_aaaa_answer](#create_aaaa_answer) * [create_cname_answer](#create_cname_answer) * [create_txt_answer](#create_txt_answer) * [create_ns_answer](#create_ns_answer) * [create_soa_answer](#create_soa_answer) * [create_mx_answer](#create_mx_answer) * [create_srv_answer](#create_srv_answer) * [create_response_header](#create_response_header) * [encode_response](#encode_response) * [常量](#constants) * [TYPE_A](#type_a) * [TYPE_NS](#type_ns) * [TYPE_CNAME](#type_cname) * [TYPE_SOA](#type_soa) * [TYPE_MX](#type_mx) * [TYPE_TXT](#type_txt) * [TYPE_AAAA](#type_aaaa) * [TYPE_SRV](#type_srv) * [TYPE_ANY](#type_any) * [RCODE_NOT_IMPLEMENTED](#rcode_not_implemented) * [待办事项](#todo) * [作者](#author) * [版权和许可](#copyright-and-license) * [参见](#see-also)

状态 ======

此库仍处于早期开发阶段,且尚处于实验阶段。

描述 ===========

此 Lua 库为 ngx_lua nginx 模块提供了一个 DNS 服务器驱动。

https://github.com/openresty/stream-lua-nginx-module/#readme

概要 ========

```nginx lua_package_path "/path/to/lua-resty-dns-server/lib/?.lua;;";

stream { server { listen 53 udp; content_by_lua_block { local server = require 'resty.dns.server' local sock, err = ngx.req.socket() if not sock then ngx.log(ngx.ERR, "failed to get the request socket: ", err) return ngx.exit(ngx.ERROR) end

            local req, err = sock:receive()
            if not req then
                ngx.log(ngx.ERR, "failed to receive: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local dns = server:new()
            local request, err = dns:decode_request(req)
            if not request then
                ngx.log(ngx.ERR, "failed to decode request: ", err)

                local resp = dns:encode_response()
                local ok, err = sock:send(resp)
                if not ok then
                    ngx.log(ngx.ERR, "failed to send: ", err)
                    ngx.exit(ngx.ERROR)
                end

                return
            end

            local query = request.questions[1]
            ngx.log(ngx.DEBUG, "qname: ", query.qname, " qtype: ", query.qtype)

            local cname = "sinacloud.com"

            if query.qtype == server.TYPE_CNAME or
                query.qtype == server.TYPE_AAAA or query.qtype == server.TYPE_A then

                local err = dns:create_cname_answer(query.qname, 600, cname)
                if err then
                    ngx.log(ngx.ERR, "failed to create cname answer: ", err)
                    return
                end
            else
                dns:create_soa_answer("test.com", 600, "a.root-test.com", "vislee.test.com", 1515161223, 1800, 900, 604800, 86400)
            end

            local resp = dns:encode_response()
            local ok, err = sock:send(resp)
            if not ok then
                ngx.log(ngx.ERR, "failed to send: ", err)
                return
            end
        }
    }

    server {
        listen 53;
        content_by_lua_block {
            local bit    = require 'bit'
            local lshift = bit.lshift
            local rshift = bit.rshift
            local band   = bit.band
            local byte   = string.byte
            local char   = string.char
            local server = require 'resty.dns.server'

            local sock, err = ngx.req.socket()
            if not sock then
                ngx.log(ngx.ERR, "failed to get the request socket: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local buf, err = sock:receive(2)
            if not buf then
                ngx.log(ngx.ERR, "failed to receive: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local len_hi = byte(buf, 1)
            local len_lo = byte(buf, 2)
            local len = lshift(len_hi, 8) + len_lo
            local data, err = sock:receive(len)
            if not data then
                ngx.log(ngx.ERR, "failed to receive: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local dns = server:new()
            local request, err = dns:decode_request(data)
            if not request then
                ngx.log(ngx.ERR, "failed to decode dns request: ", err)
                return
            end

            local query = request.questions[1]
            ngx.log(ngx.DEBUG, "qname: ", query.qname, " qtype: ", query.qtype)

            if query.qtype == server.TYPE_CNAME or query.qtype == server.TYPE_A then
                dns:create_cname_answer(query.qname, 600, "sinacloud.com")
            elseif query.qtype == server.TYPE_AAAA then
                local resp_header, err = dns:create_response_header(server.RCODE_NOT_IMPLEMENTED)
                resp_header.ra = 0
            else
                dns:create_soa_answer("test.com", 600, "a.root-test.com", "vislee.test.com", 1515161223, 1800, 900, 604800, 86400)
            end

            local resp = dns:encode_response()
            local len = #resp
            local len_hi = char(rshift(len, 8))
            local len_lo = char(band(len, 0xff))

            local ok, err = sock:send({len_hi, len_lo, resp})
            if not ok then
                ngx.log(ngx.ERR, "failed to send: ", err)
                return
            end
            return
        }
    }
}

```

[返回目录](#table-of-contents)

方法 =======

[返回目录](#table-of-contents)

new --- `语法: s, err = class:new()`

创建一个 dns.server 对象。出错时返回 `nil` 和错误消息字符串。

[返回目录](#table-of-contents)

decode_request -------------- `语法: request, err = s:decode_request(buf)`

解析 DNS 请求。

返回的请求是一个 Lua 表,包含以下一些字段

* `header`: `header` 也是一个 Lua 表,通常包含以下一些字段

    * `id` : The identifier assigned by the program that generates any kind of query.
    * `qr` : The field specifies whether this message is a query (`0`), or a response (`1`).
    * `opcode` : The field specifies kind of query in this message.
    * `tc` : The field specifies that this message was truncated due to length greater than that permitted on the transmission channel.
    * `rd` : Recursion Desired. If `RD` is set, it directs the name server to pursue the query recursively.
    * `rcode` : response code.
    * `qdcount` : The field specifying the number of entries in the question section.

* `questions` : `questions` 中的每个条目也是一个 Lua 表,包含以下一些

    * `qname` : A domain name of query.
    * `qtype` : Specifies the type of the query.
    * `qclass` : Specifies the class of the query. Usually the field is `IN` for the Internet.

[返回目录](#table-of-contents)

create_a_answer -------------- `语法: err = s:create_a_answer(name, ttl, ipv4)`

创建 A 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `ipv4`

    The IPv4 address.

[返回目录](#table-of-contents)

create_aaaa_answer --------------- `语法: err = s:create_aaaa_answer(name, ttl, ipv6)`

创建 AAAA 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `ipv6`

    The IPv6 address.

[返回目录](#table-of-contents)

create_cname_answer ------------------- `语法: err = s:create_cname_answer(name, ttl, cname)`

创建 CNAME 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `cname`

    The name for an alias.

[返回目录](#table-of-contents)

create_txt_answer ------------------ `语法: err = s:create_txt_answer(name, ttl, txt)`

创建 txt 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `txt`

    The text strings.

[返回目录](#table-of-contents)

create_ns_answer ---------------- `语法: err = s:create_ns_answer(name, ttl, nsdname)`

创建 NS 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `nsdname`

    The specifies a host which should be authoritative for the specified class and domain.

[返回目录](#table-of-contents)

create_soa_answer ----------------- `语法: err = s:create_soa_answer(name, ttl, mname, rname, serial, refresh, retry, expire, minimum)`

创建 SOA 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `mname`

    The the name server that was the original or primary source of data for this zone.
* `rname`

    The mailbox of the person responsible for this zone.
* `serial`

    The unsigned 32 bit version number of the original copy of the zone.
* `refresh`

    A 32 bit time interval before the zone should be refreshed.
* `retry`

    A 32 bit time interval that should elapse before a failed refresh should be retried.
* `expire`

    A 32 bit time value that specifies the upper limit on the time interval that can elapse before the zone is no longer authoritative.
* `minimum`

    The unsigned 32 bit minimum TTL field that should be exported with any RR from this zone.

[返回目录](#table-of-contents)

create_mx_answer ---------------- `语法: err = s:create_mx_answer(name, ttl, preference, exchange)`

创建 MX 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `preference`

    The preference of this mail exchange.
* `exchange`

    The mail exchange.

[返回目录](#table-of-contents)

create_srv_answer ----------------- `语法: err = s:create_srv_answer(name, ttl, priority, weight, port, target)`

创建 SRV 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `priority`

    The priority of this target host.
* `weight`

    The weight field specifies a relative weight for entries with the same priority.
* `port`

    The port on this target host of this service.
* `target`

    The domain name of the target host.

[返回目录](#table-of-contents)

create_response_header ----------------- `语法: resp_header, err = s:create_response_header(rcode)`

[返回目录](#table-of-contents)

encode_response --------------- `语法: resp = s:encode_response()`

编码 DNS 答案。在响应或 `nil` 时返回错误消息字符串。

[返回目录](#table-of-contents)

常量 =========

[返回目录](#table-of-contents)

TYPE_A ------

`A` 资源记录类型,等于十进制数 `1`。

[返回目录](#table-of-contents)

TYPE_NS -------

`NS` 资源记录类型,等于十进制数 `2`。

[返回目录](#table-of-contents)

TYPE_CNAME ----------

`CNAME` 资源记录类型,等于十进制数 `5`。

[返回目录](#table-of-contents)

TYPE_SOA ----------

`SOA` 资源记录类型,等于十进制数 `6`。

[返回目录](#table-of-contents)

TYPE_MX -------

`MX` 资源记录类型,等于十进制数 `15`。

[返回目录](#table-of-contents)

TYPE_TXT --------

`TXT` 资源记录类型,等于十进制数 `16`。

[返回目录](#table-of-contents)

TYPE_AAAA --------- `语法: typ = s.TYPE_AAAA`

`AAAA` 资源记录类型,等于十进制数 `28`。

[返回目录](#table-of-contents)

TYPE_SRV --------- `语法: typ = s.TYPE_SRV`

`SRV` 资源记录类型,等于十进制数 `33`。

详情请参见 RFC 2782。

[返回目录](#table-of-contents)

TYPE_ANY --------- `语法: typ = s.TYPE_ANY`

所有资源记录类型,等于十进制数 `255`。

[返回目录](#table-of-contents)

RCODE_FORMAT_ERROR ------------------

[返回目录](#table-of-contents)

RCODE_NOT_IMPLEMENTED ---------------------

[返回目录](#table-of-contents)

待办事项 ====

[返回目录](#table-of-contents)

作者 ======

李文强 (vislee)

[返回目录](#table-of-contents)

版权和许可 =====================

此模块根据 BSD 许可证授权。

版权所有 (C) 2018-2019,由 vislee。

保留所有权利。

在满足以下条件的情况下,允许以源代码和二进制形式重新分发和使用,无论是否修改

* 源代码的重新分发必须保留上述版权声明、此条件列表和以下免责声明。

* 二进制形式的重新分发必须在随分发提供的文档和/或其他材料中复制上述版权声明、此条件列表和以下免责声明。

本软件由版权持有人和贡献者“按原样”提供,并且不提供任何明示或暗示的担保,包括但不限于适销性和特定用途适用性的暗示担保。在任何情况下,版权持有人或贡献者均不对任何直接的、间接的、偶然的、特殊的、惩罚性的或后果性的损害(包括但不限于替代商品或服务的采购;使用、数据或利润损失;或业务中断)负责,无论此类损害是因使用本软件而引起的,还是基于任何责任理论,无论是在合同中、严格责任中,还是在侵权行为(包括疏忽或其他)中,即使已被告知此类损害的可能性。

[返回目录](#table-of-contents)

参见 ======== * stream-lua-nginx-module:https://github.com/openresty/stream-lua-nginx-module/#readme * [lua-resty-dns](https://github.com/openresty/lua-resty-dns) 库。 * 此 [ngx_stream_ipdb_module](https://github.com/vislee/ngx_stream_ipdb_module) 库可以支持区域解析。

[返回目录](#table-of-contents) id : 生成任何类型查询的程序分配的标识符。qr : 该字段指定此消息是查询 (0) 还是响应 (1)。opcode : 该字段指定此消息中的查询类型。tc : 该字段指定此消息由于长度超过传输通道允许的长度而被截断。rd : 递归所需。如果设置了 RD,则指示名称服务器递归地执行查询。rcode : 响应代码。qdcount : 指定问题部分中条目数量的字段。

  • questions : `questions` 中的每个条目也是一个 Lua 表,包含以下一些

名称 ====

lua-resty-dns-server - OpenResty 的 Lua DNS 服务器驱动

目录 =================

* [名称](#name) * [状态](#status) * [描述](#description) * [概要](#synopsis) * [方法](#methods) * [new](#new) * [decode_request](#decode_request) * [create_a_answer](#create_a_answer) * [create_aaaa_answer](#create_aaaa_answer) * [create_cname_answer](#create_cname_answer) * [create_txt_answer](#create_txt_answer) * [create_ns_answer](#create_ns_answer) * [create_soa_answer](#create_soa_answer) * [create_mx_answer](#create_mx_answer) * [create_srv_answer](#create_srv_answer) * [create_response_header](#create_response_header) * [encode_response](#encode_response) * [常量](#constants) * [TYPE_A](#type_a) * [TYPE_NS](#type_ns) * [TYPE_CNAME](#type_cname) * [TYPE_SOA](#type_soa) * [TYPE_MX](#type_mx) * [TYPE_TXT](#type_txt) * [TYPE_AAAA](#type_aaaa) * [TYPE_SRV](#type_srv) * [TYPE_ANY](#type_any) * [RCODE_NOT_IMPLEMENTED](#rcode_not_implemented) * [待办事项](#todo) * [作者](#author) * [版权和许可](#copyright-and-license) * [参见](#see-also)

状态 ======

此库仍处于早期开发阶段,且尚处于实验阶段。

描述 ===========

此 Lua 库为 ngx_lua nginx 模块提供了一个 DNS 服务器驱动。

https://github.com/openresty/stream-lua-nginx-module/#readme

概要 ========

```nginx lua_package_path "/path/to/lua-resty-dns-server/lib/?.lua;;";

stream { server { listen 53 udp; content_by_lua_block { local server = require 'resty.dns.server' local sock, err = ngx.req.socket() if not sock then ngx.log(ngx.ERR, "failed to get the request socket: ", err) return ngx.exit(ngx.ERROR) end

            local req, err = sock:receive()
            if not req then
                ngx.log(ngx.ERR, "failed to receive: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local dns = server:new()
            local request, err = dns:decode_request(req)
            if not request then
                ngx.log(ngx.ERR, "failed to decode request: ", err)

                local resp = dns:encode_response()
                local ok, err = sock:send(resp)
                if not ok then
                    ngx.log(ngx.ERR, "failed to send: ", err)
                    ngx.exit(ngx.ERROR)
                end

                return
            end

            local query = request.questions[1]
            ngx.log(ngx.DEBUG, "qname: ", query.qname, " qtype: ", query.qtype)

            local cname = "sinacloud.com"

            if query.qtype == server.TYPE_CNAME or
                query.qtype == server.TYPE_AAAA or query.qtype == server.TYPE_A then

                local err = dns:create_cname_answer(query.qname, 600, cname)
                if err then
                    ngx.log(ngx.ERR, "failed to create cname answer: ", err)
                    return
                end
            else
                dns:create_soa_answer("test.com", 600, "a.root-test.com", "vislee.test.com", 1515161223, 1800, 900, 604800, 86400)
            end

            local resp = dns:encode_response()
            local ok, err = sock:send(resp)
            if not ok then
                ngx.log(ngx.ERR, "failed to send: ", err)
                return
            end
        }
    }

    server {
        listen 53;
        content_by_lua_block {
            local bit    = require 'bit'
            local lshift = bit.lshift
            local rshift = bit.rshift
            local band   = bit.band
            local byte   = string.byte
            local char   = string.char
            local server = require 'resty.dns.server'

            local sock, err = ngx.req.socket()
            if not sock then
                ngx.log(ngx.ERR, "failed to get the request socket: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local buf, err = sock:receive(2)
            if not buf then
                ngx.log(ngx.ERR, "failed to receive: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local len_hi = byte(buf, 1)
            local len_lo = byte(buf, 2)
            local len = lshift(len_hi, 8) + len_lo
            local data, err = sock:receive(len)
            if not data then
                ngx.log(ngx.ERR, "failed to receive: ", err)
                return ngx.exit(ngx.ERROR)
            end

            local dns = server:new()
            local request, err = dns:decode_request(data)
            if not request then
                ngx.log(ngx.ERR, "failed to decode dns request: ", err)
                return
            end

            local query = request.questions[1]
            ngx.log(ngx.DEBUG, "qname: ", query.qname, " qtype: ", query.qtype)

            if query.qtype == server.TYPE_CNAME or query.qtype == server.TYPE_A then
                dns:create_cname_answer(query.qname, 600, "sinacloud.com")
            elseif query.qtype == server.TYPE_AAAA then
                local resp_header, err = dns:create_response_header(server.RCODE_NOT_IMPLEMENTED)
                resp_header.ra = 0
            else
                dns:create_soa_answer("test.com", 600, "a.root-test.com", "vislee.test.com", 1515161223, 1800, 900, 604800, 86400)
            end

            local resp = dns:encode_response()
            local len = #resp
            local len_hi = char(rshift(len, 8))
            local len_lo = char(band(len, 0xff))

            local ok, err = sock:send({len_hi, len_lo, resp})
            if not ok then
                ngx.log(ngx.ERR, "failed to send: ", err)
                return
            end
            return
        }
    }
}

```

[返回目录](#table-of-contents)

方法 =======

[返回目录](#table-of-contents)

new --- `语法: s, err = class:new()`

创建一个 dns.server 对象。出错时返回 `nil` 和错误消息字符串。

[返回目录](#table-of-contents)

decode_request -------------- `语法: request, err = s:decode_request(buf)`

解析 DNS 请求。

返回的请求是一个 Lua 表,包含以下一些字段

* `header`: `header` 也是一个 Lua 表,通常包含以下一些字段

    * `id` : The identifier assigned by the program that generates any kind of query.
    * `qr` : The field specifies whether this message is a query (`0`), or a response (`1`).
    * `opcode` : The field specifies kind of query in this message.
    * `tc` : The field specifies that this message was truncated due to length greater than that permitted on the transmission channel.
    * `rd` : Recursion Desired. If `RD` is set, it directs the name server to pursue the query recursively.
    * `rcode` : response code.
    * `qdcount` : The field specifying the number of entries in the question section.

* `questions` : `questions` 中的每个条目也是一个 Lua 表,包含以下一些

    * `qname` : A domain name of query.
    * `qtype` : Specifies the type of the query.
    * `qclass` : Specifies the class of the query. Usually the field is `IN` for the Internet.

[返回目录](#table-of-contents)

create_a_answer -------------- `语法: err = s:create_a_answer(name, ttl, ipv4)`

创建 A 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `ipv4`

    The IPv4 address.

[返回目录](#table-of-contents)

create_aaaa_answer --------------- `语法: err = s:create_aaaa_answer(name, ttl, ipv6)`

创建 AAAA 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `ipv6`

    The IPv6 address.

[返回目录](#table-of-contents)

create_cname_answer ------------------- `语法: err = s:create_cname_answer(name, ttl, cname)`

创建 CNAME 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `cname`

    The name for an alias.

[返回目录](#table-of-contents)

create_txt_answer ------------------ `语法: err = s:create_txt_answer(name, ttl, txt)`

创建 txt 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `txt`

    The text strings.

[返回目录](#table-of-contents)

create_ns_answer ---------------- `语法: err = s:create_ns_answer(name, ttl, nsdname)`

创建 NS 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `nsdname`

    The specifies a host which should be authoritative for the specified class and domain.

[返回目录](#table-of-contents)

create_soa_answer ----------------- `语法: err = s:create_soa_answer(name, ttl, mname, rname, serial, refresh, retry, expire, minimum)`

创建 SOA 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `mname`

    The the name server that was the original or primary source of data for this zone.
* `rname`

    The mailbox of the person responsible for this zone.
* `serial`

    The unsigned 32 bit version number of the original copy of the zone.
* `refresh`

    A 32 bit time interval before the zone should be refreshed.
* `retry`

    A 32 bit time interval that should elapse before a failed refresh should be retried.
* `expire`

    A 32 bit time value that specifies the upper limit on the time interval that can elapse before the zone is no longer authoritative.
* `minimum`

    The unsigned 32 bit minimum TTL field that should be exported with any RR from this zone.

[返回目录](#table-of-contents)

create_mx_answer ---------------- `语法: err = s:create_mx_answer(name, ttl, preference, exchange)`

创建 MX 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `preference`

    The preference of this mail exchange.
* `exchange`

    The mail exchange.

[返回目录](#table-of-contents)

create_srv_answer ----------------- `语法: err = s:create_srv_answer(name, ttl, priority, weight, port, target)`

创建 SRV 记录。出错时返回 `nil` 或错误消息字符串。通常包含以下一些字段

* `name`

    The resource record name.
* `ttl`

    The time-to-live (TTL) value in seconds for the current resource record.
* `priority`

    The priority of this target host.
* `weight`

    The weight field specifies a relative weight for entries with the same priority.
* `port`

    The port on this target host of this service.
* `target`

    The domain name of the target host.

[返回目录](#table-of-contents)

create_response_header ----------------- `语法: resp_header, err = s:create_response_header(rcode)`

[返回目录](#table-of-contents)

encode_response --------------- `语法: resp = s:encode_response()`

编码 DNS 答案。在响应或 `nil` 时返回错误消息字符串。

[返回目录](#table-of-contents)

常量 =========

[返回目录](#table-of-contents)

TYPE_A ------

`A` 资源记录类型,等于十进制数 `1`。

[返回目录](#table-of-contents)

TYPE_NS -------

`NS` 资源记录类型,等于十进制数 `2`。

[返回目录](#table-of-contents)

TYPE_CNAME ----------

`CNAME` 资源记录类型,等于十进制数 `5`。

[返回目录](#table-of-contents)

TYPE_SOA ----------

`SOA` 资源记录类型,等于十进制数 `6`。

[返回目录](#table-of-contents)

TYPE_MX -------

`MX` 资源记录类型,等于十进制数 `15`。

[返回目录](#table-of-contents)

TYPE_TXT --------

`TXT` 资源记录类型,等于十进制数 `16`。

[返回目录](#table-of-contents)

TYPE_AAAA --------- `语法: typ = s.TYPE_AAAA`

`AAAA` 资源记录类型,等于十进制数 `28`。

[返回目录](#table-of-contents)

TYPE_SRV --------- `语法: typ = s.TYPE_SRV`

`SRV` 资源记录类型,等于十进制数 `33`。

详情请参见 RFC 2782。

[返回目录](#table-of-contents)

TYPE_ANY --------- `语法: typ = s.TYPE_ANY`

所有资源记录类型,等于十进制数 `255`。

[返回目录](#table-of-contents)

RCODE_FORMAT_ERROR ------------------

[返回目录](#table-of-contents)

RCODE_NOT_IMPLEMENTED ---------------------

[返回目录](#table-of-contents)

待办事项 ====

[返回目录](#table-of-contents)

作者 ======

李文强 (vislee)

[返回目录](#table-of-contents)

版权和许可 =====================

此模块根据 BSD 许可证授权。

版权所有 (C) 2018-2019,由 vislee。

保留所有权利。

在满足以下条件的情况下,允许以源代码和二进制形式重新分发和使用,无论是否修改

* 源代码的重新分发必须保留上述版权声明、此条件列表和以下免责声明。

* 二进制形式的重新分发必须在随分发提供的文档和/或其他材料中复制上述版权声明、此条件列表和以下免责声明。

本软件由版权持有人和贡献者“按原样”提供,并且不提供任何明示或暗示的担保,包括但不限于适销性和特定用途适用性的暗示担保。在任何情况下,版权持有人或贡献者均不对任何直接的、间接的、偶然的、特殊的、惩罚性的或后果性的损害(包括但不限于替代商品或服务的采购;使用、数据或利润损失;或业务中断)负责,无论此类损害是因使用本软件而引起的,还是基于任何责任理论,无论是在合同中、严格责任中,还是在侵权行为(包括疏忽或其他)中,即使已被告知此类损害的可能性。

[返回目录](#table-of-contents)

参见 ======== * stream-lua-nginx-module:https://github.com/openresty/stream-lua-nginx-module/#readme * [lua-resty-dns](https://github.com/openresty/lua-resty-dns) 库。 * 此 [ngx_stream_ipdb_module](https://github.com/vislee/ngx_stream_ipdb_module) 库可以支持区域解析。

[返回目录](#table-of-contents) qname : 查询的域名。qtype : 指定查询的类型。qclass : 指定查询的类别。通常,该字段对于 Internet 为 IN

create_a_answer

语法: err = s:create_a_answer(name, ttl, ipv4)

创建 A 记录。出错时返回 nil 或错误消息字符串。通常包含以下一些字段

  • name

    资源记录名称。

  • ttl

    当前资源记录的生存时间 (TTL) 值(以秒为单位)。

  • ipv4

    IPv4 地址。

create_aaaa_answer

语法: err = s:create_aaaa_answer(name, ttl, ipv6)

创建 AAAA 记录。出错时返回 nil 或错误消息字符串。通常包含以下一些字段

  • name

    资源记录名称。

  • ttl

    当前资源记录的生存时间 (TTL) 值(以秒为单位)。

  • ipv6

    IPv6 地址。

create_cname_answer

语法: err = s:create_cname_answer(name, ttl, cname)

创建 CNAME 记录。出错时返回 nil 或错误消息字符串。通常包含以下一些字段

  • name

    资源记录名称。

  • ttl

    当前资源记录的生存时间 (TTL) 值(以秒为单位)。

  • cname

    别名的名称。

create_txt_answer

语法: err = s:create_txt_answer(name, ttl, txt)

创建 txt 记录。出错时返回 nil 或错误消息字符串。通常包含以下一些字段

  • name

    资源记录名称。

  • ttl

    当前资源记录的生存时间 (TTL) 值(以秒为单位)。

  • txt

    文本字符串。

create_ns_answer

语法: err = s:create_ns_answer(name, ttl, nsdname)

创建 NS 记录。出错时返回 nil 或错误消息字符串。通常包含以下一些字段

  • name

    资源记录名称。

  • ttl

    当前资源记录的生存时间 (TTL) 值(以秒为单位)。

  • nsdname

    指定应为此特定类别和域提供权威的服务器。

create_soa_answer

语法: err = s:create_soa_answer(name, ttl, mname, rname, serial, refresh, retry, expire, minimum)

创建 SOA 记录。出错时返回 nil 或错误消息字符串。通常包含以下一些字段

  • name

    资源记录名称。

  • ttl

    当前资源记录的生存时间 (TTL) 值(以秒为单位)。

  • mname

    此区域数据的原始或主要来源的名称服务器。

  • rname

    负责此区域的邮箱。

  • serial

    区域原始副本的 32 位无符号版本号。

  • refresh

    应刷新区域之前的时间间隔(以 32 位时间间隔表示)。

  • retry

    刷新失败后应经过的时间间隔(以 32 位时间间隔表示),之后应重试。

  • expire

    指定区域不再具有权威性之前可能经过的时间间隔的上限(以 32 位时间值为单位)。

  • minimum

    应从此区域导出任何 RR 的 32 位无符号最小 TTL 字段。

create_mx_answer

语法: err = s:create_mx_answer(name, ttl, preference, exchange)

创建 MX 记录。出错时返回 nil 或错误消息字符串。通常包含以下一些字段

  • name

    资源记录名称。

  • ttl

    当前资源记录的生存时间 (TTL) 值(以秒为单位)。

  • preference

    此邮件交换的优先级。

  • exchange

    邮件交换。

create_srv_answer

语法: err = s:create_srv_answer(name, ttl, priority, weight, port, target)

创建 SRV 记录。出错时返回 nil 或错误消息字符串。通常包含以下一些字段

  • name

    资源记录名称。

  • ttl

    当前资源记录的生存时间 (TTL) 值(以秒为单位)。

  • priority

    此目标主机的优先级。

  • weight

    权重字段指定具有相同优先级的条目的相对权重。

  • port

    此服务的目标主机上的端口。

  • 目标

    目标主机的域名。

create_response_header

语法:resp_header, err = s:create_response_header(rcode)

encode_response

语法:resp = s:encode_response()

编码DNS答案。返回响应中的消息字符串或nil

常量

TYPE_A

A资源记录类型,等于十进制数1

TYPE_NS

NS资源记录类型,等于十进制数2

TYPE_CNAME

CNAME资源记录类型,等于十进制数5

TYPE_SOA

SOA资源记录类型,等于十进制数6

TYPE_MX

MX资源记录类型,等于十进制数15

TYPE_TXT

TXT资源记录类型,等于十进制数16

TYPE_AAAA

语法:typ = s.TYPE_AAAA

AAAA资源记录类型,等于十进制数28

TYPE_SRV

语法:typ = s.TYPE_SRV

SRV资源记录类型,等于十进制数33

详情请参见 RFC 2782。

TYPE_ANY

语法:typ = s.TYPE_ANY

所有资源记录类型,等于十进制数255

RCODE_FORMAT_ERROR

RCODE_NOT_IMPLEMENTED

待办事项

作者

李文强 (vislee)

版权和许可

此模块根据 BSD 许可证授权。

版权所有 (C) 2018-2019,由 vislee。

保留所有权利。

在满足以下条件的情况下,允许以源代码和二进制形式重新分发和使用,无论是否修改

  • 源代码的再分发必须保留上述版权声明、此条件列表和以下免责声明。

  • 二进制形式的再分发必须在随分发提供的文档和/或其他材料中复制上述版权声明、此条件列表和以下免责声明。

本软件由版权持有人和贡献者“按原样”提供,并且不提供任何明示或暗示的担保,包括但不限于适销性和特定用途适用性的暗示担保。在任何情况下,版权持有人或贡献者均不对任何直接的、间接的、偶然的、特殊的、惩罚性的或后果性的损害(包括但不限于替代商品或服务的采购;使用、数据或利润损失;或业务中断)负责,无论此类损害是因使用本软件而引起的,还是基于任何责任理论,无论是在合同中、严格责任中,还是在侵权行为(包括疏忽或其他)中,即使已被告知此类损害的可能性。

另请参阅

作者

vislee

许可证

2bsd

版本