85 lines
2.2 KiB
Plaintext
85 lines
2.2 KiB
Plaintext
access_by_lua_block {
|
|
|
|
-- get client IP
|
|
local ip = ngx.var.remote_addr
|
|
|
|
-- check if IP is in cache
|
|
local cached = ngx.shared.dnsblcache:get(ip)
|
|
if cached ~= nil then
|
|
if cached == "ok" then
|
|
ngx.exit(ngx.OK)
|
|
else
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
end
|
|
|
|
-- get the reverse DNS
|
|
local rdns = ""
|
|
local both = false
|
|
local resolver = require "resty.dns.resolver"
|
|
local resolvers = {%DNSBL_RESOLVERS%}
|
|
local r, err = resolver:new{nameservers=resolvers, retrans=2, timeout=2000}
|
|
if not r then
|
|
ngx.exit(ngx.OK)
|
|
end
|
|
local answers, err = r:reverse_query(ip)
|
|
if not answers.errcode then
|
|
for ak, av in ipairs(answers) do
|
|
if av.ptrdname then
|
|
rdns = av.ptrdname
|
|
break
|
|
end
|
|
end
|
|
end
|
|
if rdns ~= "" then
|
|
local answers, err, tries = r:query(rdns, nil, {})
|
|
for ak, av in ipairs(answers) do
|
|
if av.address and av.address == ip then
|
|
both = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
-- check if it's a legitimate SE crawler
|
|
local ips = {"23.21.227.69", "40.88.21.235", "50.16.241.113", "50.16.241.114", "50.16.241.117", "50.16.247.234", "52.204.97.54", "52.5.190.19", "54.197.234.188", "54.208.100.253", "54.208.102.37", "107.21.1.8"}
|
|
local domains = {".googlebot.com", ".google.com", ".search.msn.com", ".crawl.yahoot.net", ".crawl.baidu.jp", ".crawl.baidu.com", ".yandex.com", ".yandex.ru", ".yandex.net"}
|
|
for k, v in pairs(ips) do
|
|
if v == ip then
|
|
ngx.shared.dnsblcache:set(ip, "ok", 86400)
|
|
ngx.exit(ngx.OK)
|
|
end
|
|
end
|
|
if both and rdns ~= "" then
|
|
for k, v in pairs(domains) do
|
|
if rdns:sub(-#v) == v then
|
|
ngx.shared.dnsblcache:set(ip, "ok", 86400)
|
|
ngx.exit(ngx.OK)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- dnsbl check
|
|
local dnsbls = {%DNSBL_LIST%}
|
|
for k, v in pairs(dnsbls) do
|
|
local name = resolver.arpa_str(ip)
|
|
name = name:gsub("%.in%-addr%.arpa", ""):gsub("%.ip6%.arpa", "") .. "." .. v
|
|
local answers, err, tries = r:query(name, nil, {})
|
|
if not answers.errcode then
|
|
for ak, av in ipairs(answers) do
|
|
if av.address then
|
|
a,b,c,d = av.address:match("([%d]+).([%d]+).([%d]+).([%d]+)")
|
|
if a == "127" then
|
|
ngx.shared.dnsblcache:set(ip, "dnsbl", 86400)
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- legitimate user
|
|
ngx.shared.dnsblcache:set(ip, "ok", 86400)
|
|
ngx.exit(ngx.OK)
|
|
}
|