98 lines
2.5 KiB
Lua
98 lines
2.5 KiB
Lua
local resolver = require("resty.dns.resolver")
|
|
local lrucache = require("resty.lrucache")
|
|
local configuration = require("configuration")
|
|
local util = require("util")
|
|
|
|
local _M = {}
|
|
local CACHE_SIZE = 10000
|
|
local MAXIMUM_TTL_VALUE = 2147483647 -- maximum value according to https://tools.ietf.org/html/rfc2181
|
|
|
|
local cache, err = lrucache.new(CACHE_SIZE)
|
|
if not cache then
|
|
return error("failed to create the cache: " .. (err or "unknown"))
|
|
end
|
|
|
|
local function a_records_and_max_ttl(answers)
|
|
local addresses = {}
|
|
local ttl = MAXIMUM_TTL_VALUE -- maximum value according to https://tools.ietf.org/html/rfc2181
|
|
|
|
for _, ans in ipairs(answers) do
|
|
if ans.address then
|
|
table.insert(addresses, ans.address)
|
|
if ttl > ans.ttl then
|
|
ttl = ans.ttl
|
|
end
|
|
end
|
|
end
|
|
|
|
return addresses, ttl
|
|
end
|
|
|
|
local function resolve_host(host, r, qtype)
|
|
local answers
|
|
answers, err = r:query(host, { qtype = qtype }, {})
|
|
if not answers then
|
|
return nil, -1, tostring(err)
|
|
end
|
|
|
|
if answers.errcode then
|
|
return nil, -1, string.format("server returned error code: %s: %s", answers.errcode, answers.errstr)
|
|
end
|
|
|
|
local addresses, ttl = a_records_and_max_ttl(answers)
|
|
if #addresses == 0 then
|
|
return nil, -1, "no record resolved"
|
|
end
|
|
|
|
return addresses, ttl, nil
|
|
end
|
|
|
|
function _M.resolve(host)
|
|
local cached_addresses = cache:get(host)
|
|
if cached_addresses then
|
|
local message = string.format(
|
|
"addresses %s for host %s was resolved from cache",
|
|
table.concat(cached_addresses, ", "), host)
|
|
ngx.log(ngx.INFO, message)
|
|
return cached_addresses
|
|
end
|
|
|
|
local r
|
|
r, err = resolver:new{
|
|
nameservers = util.deepcopy(configuration.nameservers),
|
|
retrans = 5,
|
|
timeout = 2000, -- 2 sec
|
|
}
|
|
|
|
if not r then
|
|
ngx.log(ngx.ERR, "failed to instantiate the resolver: " .. tostring(err))
|
|
return { host }
|
|
end
|
|
|
|
local dns_errors = {}
|
|
|
|
local addresses, ttl
|
|
addresses, ttl, err = resolve_host(host, r, r.TYPE_A)
|
|
if not addresses then
|
|
table.insert(dns_errors, tostring(err))
|
|
elseif #addresses > 0 then
|
|
cache:set(host, addresses, ttl)
|
|
return addresses
|
|
end
|
|
|
|
addresses, ttl, err = resolve_host(host, r, r.TYPE_AAAA)
|
|
if not addresses then
|
|
table.insert(dns_errors, tostring(err))
|
|
elseif #addresses > 0 then
|
|
cache:set(host, addresses, ttl)
|
|
return addresses
|
|
end
|
|
|
|
if #dns_errors > 0 then
|
|
ngx.log(ngx.ERR, "failed to query the DNS server:\n" .. table.concat(dns_errors, "\n"))
|
|
end
|
|
|
|
return { host }
|
|
end
|
|
|
|
return _M
|