2025-01-22 16:25:39 +04:00
|
|
|
local _M = {}
|
|
|
|
|
|
|
|
|
|
local function resolve_url_with_custom_dns(url, custom_dns)
|
|
|
|
|
-- Validate inputs
|
|
|
|
|
if not url or url == "" then
|
|
|
|
|
ngx.log(ngx.ERR, "URL is required")
|
|
|
|
|
return nil, "URL is required"
|
|
|
|
|
end
|
2025-07-29 16:42:18 +04:00
|
|
|
|
2025-01-22 16:25:39 +04:00
|
|
|
if not custom_dns or custom_dns == "" then
|
2025-08-20 18:51:12 +04:00
|
|
|
ngx.log(ngx.ERR, "Custom DNS resolver is required")
|
2025-01-22 16:25:39 +04:00
|
|
|
return nil, "Custom DNS resolver is required"
|
|
|
|
|
end
|
|
|
|
|
|
2025-08-20 18:51:12 +04:00
|
|
|
-- Parse URL using resty.http
|
|
|
|
|
local http = require("resty.http")
|
|
|
|
|
local scheme, host, port, path, query = unpack(http:parse_uri(url))
|
|
|
|
|
if not scheme then
|
|
|
|
|
ngx.log(ngx.ERR, "Failed to parse URL: ", url)
|
|
|
|
|
return nil, "Invalid URL format"
|
2025-01-22 16:25:39 +04:00
|
|
|
end
|
|
|
|
|
|
2025-08-20 18:51:12 +04:00
|
|
|
ngx.log(ngx.INFO, "Resolving host: ", host, " using DNS: ", custom_dns)
|
|
|
|
|
|
2025-01-22 16:25:39 +04:00
|
|
|
-- Initialize DNS resolver
|
|
|
|
|
local dns = require("resty.dns.resolver")
|
|
|
|
|
local r, err = dns:new({
|
|
|
|
|
nameservers = {custom_dns},
|
2025-08-20 18:51:12 +04:00
|
|
|
retrans = 5, -- 5 retransmissions on receive timeout
|
|
|
|
|
timeout = 2000, -- 2 sec
|
2025-01-22 16:25:39 +04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if not r then
|
2025-08-20 18:51:12 +04:00
|
|
|
ngx.log(ngx.ERR, "Failed to initialize DNS resolver: ", err)
|
2025-01-22 16:25:39 +04:00
|
|
|
return nil, "DNS resolver initialization failed"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Perform DNS resolution
|
2025-08-20 18:51:12 +04:00
|
|
|
local answers, err = r:query(host)
|
2025-01-22 16:25:39 +04:00
|
|
|
if not answers then
|
2025-08-20 18:51:12 +04:00
|
|
|
ngx.log(ngx.ERR, "DNS resolution failed: ", err)
|
2025-01-22 16:25:39 +04:00
|
|
|
return nil, "DNS resolution failed"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Process DNS answers
|
|
|
|
|
if answers.errcode then
|
2025-08-20 18:51:12 +04:00
|
|
|
ngx.log(ngx.ERR, "DNS server returned error code: ", answers.errcode,
|
|
|
|
|
" ", answers.errstr)
|
2025-01-22 16:25:39 +04:00
|
|
|
return nil, "DNS server error"
|
|
|
|
|
end
|
|
|
|
|
|
2025-08-20 18:51:12 +04:00
|
|
|
-- Return complete URL with resolved IP using parsed components
|
2025-01-22 16:25:39 +04:00
|
|
|
for i, ans in ipairs(answers) do
|
|
|
|
|
if ans.address then
|
2025-01-28 16:03:21 +01:00
|
|
|
ngx.log(ngx.INFO, "Resolved IP: ", ans.address)
|
2025-01-22 16:25:39 +04:00
|
|
|
-- Reconstruct URL using parsed components
|
2025-08-20 18:51:12 +04:00
|
|
|
local resolved_url = scheme .. "://" .. ans.address
|
|
|
|
|
if port then
|
|
|
|
|
resolved_url = resolved_url .. ":" .. port
|
2025-01-22 16:25:39 +04:00
|
|
|
end
|
2025-08-20 18:51:12 +04:00
|
|
|
if path then
|
|
|
|
|
resolved_url = resolved_url .. path
|
2025-01-22 16:25:39 +04:00
|
|
|
end
|
2025-08-20 18:51:12 +04:00
|
|
|
if query and query ~= "" then
|
|
|
|
|
resolved_url = resolved_url .. "?" .. query
|
2025-01-22 16:25:39 +04:00
|
|
|
end
|
|
|
|
|
return resolved_url
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2025-08-20 18:51:12 +04:00
|
|
|
ngx.log(ngx.ERR, "No IP addresses found for host: ", host)
|
2025-01-22 16:25:39 +04:00
|
|
|
return nil, "No IP addresses found"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
_M.resolve_url_with_custom_dns = resolve_url_with_custom_dns
|
|
|
|
|
|
|
|
|
|
return _M
|