lua-resty-dns-server

OpenResty 的 Lua DNS 服务器驱动

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

名称

[!构建状态](https://travis-ci.org/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 subnet = request.subnet[1]
                if subnet then
                    ngx.log(ngx.DEBUG, "subnet addr: ",  subnet.address, " mask: ", subnet.mask, " family: ", subnet.family)
                end
    
                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)
    
                local subnet = request.subnet[1]
                if subnet then
                    ngx.log(ngx.DEBUG, "subnet addr: ",  subnet.address, " mask: ", subnet.mask, " family: ", subnet.family)
                end
    
                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 表格,它通常包含以下字段

名称 ====

[![构建状态](https://travis-ci.org/vislee/lua-resty-dns-server.svg?branch=master)](https://travis-ci.org/vislee/lua-resty-dns-server)

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 subnet = request.subnet[1]
            if subnet then
                ngx.log(ngx.DEBUG, "subnet addr: ",  subnet.address, " mask: ", subnet.mask, " family: ", subnet.family)
            end

            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)

            local subnet = request.subnet[1]
            if subnet then
                ngx.log(ngx.DEBUG, "subnet addr: ",  subnet.address, " mask: ", subnet.mask, " family: ", subnet.family)
            end

            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)

作者 ======

wenqiang li(vislee)

guocan xu(selboo)

[返回目录](#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 表格,它包含以下内容

名称 ====

[![构建状态](https://travis-ci.org/vislee/lua-resty-dns-server.svg?branch=master)](https://travis-ci.org/vislee/lua-resty-dns-server)

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 subnet = request.subnet[1]
            if subnet then
                ngx.log(ngx.DEBUG, "subnet addr: ",  subnet.address, " mask: ", subnet.mask, " family: ", subnet.family)
            end

            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)

            local subnet = request.subnet[1]
            if subnet then
                ngx.log(ngx.DEBUG, "subnet addr: ",  subnet.address, " mask: ", subnet.mask, " family: ", subnet.family)
            end

            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)

作者 ======

wenqiang li(vislee)

guocan xu(selboo)

[返回目录](#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 : 指定查询的类别。通常,该字段是互联网的 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

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

  • target

    目标主机的域名。

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

待办事项

作者

wenqiang li(vislee)

guocan xu(selboo)

版权和许可

该模块在 BSD 许可下授权。

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

保留所有权利。

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

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

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

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

另请参见

作者

selboo

许可证

2bsd

版本