lua-resty-dns
基于 cosocket API 的 ngx_lua Lua DNS 解析器
$ opm get openresty/lua-resty-dns
名称
lua-resty-dns - 基于 cosocket API 的 ngx_lua Lua DNS 解析器
状态
该库被认为已准备好用于生产环境。
描述
此 Lua 库为 ngx_lua nginx 模块提供了一个 DNS 解析器
https://github.com/openresty/lua-nginx-module/#readme
此 Lua 库利用了 ngx_lua 的 cosocket API,确保了 100% 的非阻塞行为。
请注意,至少需要 ngx_lua 0.5.12 或 OpenResty 1.2.1.11。
此外,还需要 bit 库。如果您使用的是带有 ngx_lua 的 LuaJIT 2.0,则默认情况下 bit
库已可用。
请注意,此库在 OpenResty 包 中默认捆绑并启用。
重要提示:为了能够生成唯一的 ID,在使用此模块之前,必须使用 math.randomseed
正确地播种随机数生成器。
摘要
lua_package_path "/path/to/lua-resty-dns/lib/?.lua;;";
server {
location = /dns {
content_by_lua_block {
local resolver = require "resty.dns.resolver"
local r, err = resolver:new{
nameservers = {"8.8.8.8", {"8.8.4.4", 53} },
retrans = 5, -- 5 retransmissions on receive timeout
timeout = 2000, -- 2 sec
}
if not r then
ngx.say("failed to instantiate the resolver: ", err)
return
end
local answers, err, tries = r:query("www.google.com", nil, {})
if not answers then
ngx.say("failed to query the DNS server: ", err)
ngx.say("retry historie:\n ", table.concat(tries, "\n "))
return
end
if answers.errcode then
ngx.say("server returned error code: ", answers.errcode,
": ", answers.errstr)
end
for i, ans in ipairs(answers) do
ngx.say(ans.name, " ", ans.address or ans.cname,
" type:", ans.type, " class:", ans.class,
" ttl:", ans.ttl)
end
}
}
}
方法
new
语法:r, err = class:new(opts)
创建一个 dns.resolver 对象。出错时返回 nil
和错误消息字符串。
它接受一个 opts
表格参数。支持以下选项
nameservers
要使用的名称服务器列表。每个名称服务器条目可以是单个主机名字符串,也可以是包含主机名字符串和端口号的表格。每个 query
方法调用都会通过简单的循环轮询算法来选择名称服务器。此选项是必需的。
retrans
根据 timeout
设置,在接收 DNS 响应超时时重新传输 DNS 请求的总次数。默认为 5
次。尝试重新传输查询时,将选择下一个根据循环轮询算法选择的名称服务器。
timeout
等待单个请求传输尝试响应的时间(毫秒)。请注意,这**不是**放弃之前的最大总等待时间,最大总等待时间可以通过表达式 timeout x retrans
计算得出。还可以通过调用 set_timeout
方法更改 timeout
设置。默认 timeout
设置为 2000 毫秒,即 2 秒。
no_recurse
布尔标志,控制是否禁用 UDP 请求中的“递归所需”(RD)标志。默认为 false
。
query
语法:answers, err, tries? = r:query(name, options?, tries?)
对 new
方法指定的名称服务器执行 DNS 标准查询,并将所有答案记录返回到类似数组的 Lua 表格中。如果出错,则会返回 nil
和描述错误的字符串。
如果服务器返回非零错误代码,则会在返回的 Lua 表格中相应地设置字段 errcode
和 errstr
。
返回的 answers
表格值中的每个条目也是一个类似哈希的 Lua 表格,通常包含以下一些字段
name
资源记录名称。
type
当前资源记录类型,可能的值为 1
(TYPE_A
)、5
(TYPE_CNAME
)、28
(TYPE_AAAA
)以及 RFC 1035 允许的任何其他值。
address
当资源记录类型为 1
(TYPE_A
)或 28
(TYPE_AAAA
)时,其文本表示形式中的 IPv4 或 IPv6 地址。默认情况下,IPv6 地址中连续的 16 位零组不会被压缩,如果需要,则需要调用 compress_ipv6_addr
静态方法。
section
当前答案记录所属部分的标识符。可能的值为 1
(SECTION_AN
)、2
(SECTION_NS
)和 3
(SECTION_AR
)。
cname
CNAME
资源记录的(已解码)记录数据值。仅在 CNAME
记录中存在。
ttl
当前资源记录的生存时间 (TTL) 值(秒)。
class
当前资源记录类,可能的值为 1
(CLASS_IN
)或 RFC 1035 允许的任何其他值。
preference
MX
资源记录的首选项整数。仅在 MX
类型记录中存在。
exchange
MX
资源记录的交换域名。仅在 MX
类型记录中存在。
nsdname
指定应为指定类和域提供权威的宿主的域名。通常存在于 NS
类型记录中。
rdata
未识别的资源记录的原始资源数据 (RDATA)。
txt
TXT
记录的记录值。当此记录中只有一个字符字符串时,此字段将采用单个 Lua 字符串。否则,此字段将采用一个包含所有字符串的 Lua 表格。
ptrdname
PTR
记录的记录值。
此方法还接受一个可选的 options
参数表,它包含以下字段
qtype
问题的类型。可能的值为 1
(TYPE_A
)、5
(TYPE_CNAME
)、28
(TYPE_AAAA
)或 RFC 1035 和 RFC 3596 指定的任何其他 QTYPE 值。默认为 1
(TYPE_A
)。
authority_section
设置为真值时,answers
返回值将包含 DNS 响应的 Authority
部分。默认为 false
。
additional_section
设置为真值时,answers
返回值将包含 DNS 响应的 Additional
部分。默认为 false
。
可以将可选参数 tries
作为空表提供,并作为第三个结果返回。该表将是一个数组,其中包含每次(如果有)失败尝试的错误消息。
发生数据截断时,解析器将自动使用 TCP 传输模式重试以查询当前名称服务器。所有 TCP 连接都是短暂的。
tcp_query
语法:answers, err = r:tcp_query(name, options?)
就像 query
方法一样,但强制使用 TCP 传输模式而不是 UDP。
所有 TCP 连接都是短暂的。
这是一个示例
local resolver = require "resty.dns.resolver"
local r, err = resolver:new{
nameservers = { "8.8.8.8" }
}
if not r then
ngx.say("failed to instantiate resolver: ", err)
return
end
local ans, err = r:tcp_query("www.google.com", { qtype = r.TYPE_A })
if not ans then
ngx.say("failed to query: ", err)
return
end
local cjson = require "cjson"
ngx.say("records: ", cjson.encode(ans))
set_timeout
语法:r:set_timeout(time)
通过 time
参数(毫秒)覆盖所有名称服务器对等体的当前 timeout
设置。
compress_ipv6_addr
语法:compressed = resty.dns.resolver.compress_ipv6_addr(address)
压缩 IPv6 地址文本格式中连续的 16 位零组。
例如,
local resolver = require "resty.dns.resolver"
local compress = resolver.compress_ipv6_addr
local new_addr = compress("FF01:0:0:0:0:0:0:101")
将在 new_addr
返回值中产生 FF01::101
。
expand_ipv6_addr
语法:expanded = resty.dns.resolver.expand_ipv6_addr(address)
扩展 IPv6 地址文本格式中连续的 16 位零组。
例如,
local resolver = require "resty.dns.resolver"
local expand = resolver.expand_ipv6_addr
local new_addr = expand("FF01::101")
将在 new_addr
返回值中产生 FF01:0:0:0:0:0:0:101
。
arpa_str
语法:arpa_record = resty.dns.resolver.arpa_str(address)
为 IPv4 和 IPv6 地址的 PTR 查询生成反向域名。压缩的 IPv6 地址将自动扩展。
例如,
local resolver = require "resty.dns.resolver"
local ptr4 = resolver.arpa_str("1.2.3.4")
local ptr6 = resolver.arpa_str("FF01::101")
将为 ptr4
生成 4.3.2.1.in-addr.arpa
,为 ptr6
生成 1.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.F.F.ip6.arpa
。
reverse_query
语法:answers, err = r:reverse_query(address)
对 IPv4 和 IPv6 地址执行 PTR 查询。此函数基本上是 query
命令的包装器,它使用 arpa_str
命令动态转换 IP 地址。
常量
TYPE_A
A
资源记录类型,等于十进制数 1
。
TYPE_NS
NS
资源记录类型,等于十进制数 2
。
TYPE_CNAME
CNAME
资源记录类型,等于十进制数 5
。
TYPE_SOA
SOA
资源记录类型,等于十进制数 6
。
TYPE_PTR
PTR
资源记录类型,等于十进制数 12
。
TYPE_MX
MX
资源记录类型,等于十进制数 15
。
TYPE_TXT
TXT
资源记录类型,等于十进制数 16
。
TYPE_AAAA
语法:typ = r.TYPE_AAAA
AAAA
资源记录类型,等于十进制数 28
。
TYPE_SRV
语法:typ = r.TYPE_SRV
SRV
资源记录类型,等于十进制数 33
。
有关详细信息,请参阅 RFC 2782。
TYPE_SPF
语法:typ = r.TYPE_SPF
SPF
资源记录类型,等于十进制数 99
。
有关详细信息,请参阅 RFC 4408。
CLASS_IN
语法:class = r.CLASS_IN
Internet
资源记录类型,等于十进制数 1
。
SECTION_AN
语法:stype = r.SECTION_AN
DNS 响应中 Answer
部分的标识符。等于十进制数 1
。
SECTION_NS
语法:stype = r.SECTION_NS
DNS 响应中 Authority
部分的标识符。等于十进制数 2
。
SECTION_AR
语法:stype = r.SECTION_AR
DNS 响应中 Additional
部分的标识符。等于十进制数 3
。
自动错误日志记录
默认情况下,底层 ngx_lua 模块在发生套接字错误时会记录错误。如果您已经在自己的 Lua 代码中进行了正确的错误处理,则建议通过关闭 ngx_lua 的 lua_socket_log_errors 指令来禁用此自动错误日志记录,即
lua_socket_log_errors off;
限制
此库不能在诸如
set_by_lua*
、log_by_lua*
和header_filter_by_lua*
之类的代码上下文中使用,因为在这些上下文中 ngx_lua cosocket API 不可用。resty.dns.resolver
对象实例不能存储在 Lua 模块级别的 Lua 变量中,因为这样它将被同一 nginx 工作进程处理的所有并发请求共享(请参阅 https://github.com/openresty/lua-nginx-module/#data-sharing-within-an-nginx-worker),并且当并发请求尝试使用相同的resty.dns.resolver
实例时会导致不良的竞争条件。应始终在函数局部变量或ngx.ctx
表格中初始化resty.dns.resolver
对象。这些位置都为每个请求提供了自己的数据副本。
待办事项
并发(或并行)查询模式
更好地支持其他资源记录类型,如
TLSA
。
作者
章亦春 (Yichun "agentzh" Zhang) <[email protected]>,OpenResty Inc.
版权和许可
此模块根据 BSD 许可证授权。
版权所有 (C) 2012-2018,由章亦春 (Yichun "agentzh" Zhang) <[email protected]>,OpenResty Inc. 所有。
保留所有权利。
如果满足以下条件,则允许以源代码和二进制形式重新分发和使用,无论是否修改
源代码的重新分发必须保留上述版权声明、此条件列表和以下免责声明。
二进制形式的重新分发必须在随分发提供的文档和/或其他材料中复制上述版权声明、此条件列表和以下免责声明。
本软件由版权持有人和贡献者“按现状”提供,并且不提供任何明示或暗示的担保,包括但不限于适销性和特定用途适用性的暗示担保。在任何情况下,版权持有人或贡献者均不对任何直接的、间接的、偶然的、特殊的、惩罚性的或后果性的损害(包括但不限于替代商品或服务的采购;使用、数据或利润的损失;或业务中断)负责,无论这些损害是如何引起的以及基于何种责任理论,无论是合同、严格责任或侵权行为(包括疏忽或其他原因)在任何情况下使用本软件引起的,即使已被告知可能发生此类损害。
另请参阅
ngx_lua 模块:https://github.com/openresty/lua-nginx-module/#readme
the lua-resty-memcached 库。
the lua-resty-redis 库。
the lua-resty-mysql 库。
作者
张亦春 "agentzh" (agentzh)
许可证
2bsd
版本
-
基于 cosocket API 的 ngx_lua 的 Lua DNS 解析器 2018-04-19 20:21:00
-
基于 cosocket API 的 ngx_lua 的 Lua DNS 解析器 2017-11-03 23:19:36
-
基于 cosocket API 的 ngx_lua 的 Lua DNS 解析器 2017-08-08 22:41:03
-
基于 cosocket API 的 ngx_lua 的 Lua DNS 解析器 2016-09-30 06:34:36