mirror of
https://github.com/bunkerity/bunkerized-nginx
synced 2023-12-13 21:30:18 +01:00
334 lines
13 KiB
Plaintext
334 lines
13 KiB
Plaintext
{% if ANTIBOT_SESSION_SECRET == "random" +%}
|
|
set $session_secret {{ random(32) }};
|
|
{% else +%}
|
|
set $session_secret {{ ANTIBOT_SESSION_SECRET }};
|
|
{% endif %}
|
|
set $session_check_addr on;
|
|
|
|
access_by_lua_block {
|
|
|
|
-- disable checks for internal requests
|
|
if ngx.req.is_internal() then
|
|
return
|
|
end
|
|
|
|
-- let's encrypt
|
|
local use_lets_encrypt = {% if AUTO_LETS_ENCRYPT == "yes" %}true{% else %}false{% endif +%}
|
|
|
|
-- redis
|
|
local use_redis = {% if USE_REDIS == "yes" %}true{% else %}false{% endif +%}
|
|
local redis_host = "{{ REDIS_HOST }}"
|
|
|
|
-- external blacklists
|
|
local use_user_agents = {% if BLOCK_USER_AGENT == "yes" %}true{% else %}false{% endif +%}
|
|
local use_proxies = {% if BLOCK_PROXIES == "yes" %}true{% else %}false{% endif +%}
|
|
local use_abusers = {% if BLOCK_ABUSERS == "yes" %}true{% else %}false{% endif +%}
|
|
local use_tor_exit_nodes = {% if BLOCK_TOR_EXIT_NODE == "yes" %}true{% else %}false{% endif +%}
|
|
local use_referrers = {% if BLOCK_REFERRER == "yes" %}true{% else %}false{% endif +%}
|
|
|
|
-- countries
|
|
local use_country = {% if WHITELIST_COUNTRY != "" or BLACKLIST_COUNTRY != "" %}true{% else %}false{% endif +%}
|
|
|
|
-- antibot
|
|
local use_antibot_cookie = {% if USE_ANTIBOT == "cookie" %}true{% else %}false{% endif +%}
|
|
local use_antibot_javascript = {% if USE_ANTIBOT == "javascript" %}true{% else %}false{% endif +%}
|
|
local use_antibot_captcha = {% if USE_ANTIBOT == "captcha" %}true{% else %}false{% endif +%}
|
|
local use_antibot_recaptcha = {% if USE_ANTIBOT == "recaptcha" %}true{% else %}false{% endif +%}
|
|
|
|
-- resolvers
|
|
local dns_resolvers = {% raw %}{{% endraw %}{% if DNS_RESOLVERS != "" %}{% set elements = DNS_RESOLVERS.split(" ") %}{% for i in range(0, elements|length) %}"{{ elements[i] }}"{% if i < elements|length-1 %},{% endif %}{% endfor %}{% endif %}{% raw %}}{% endraw +%}
|
|
|
|
-- whitelist
|
|
local use_whitelist_ip = {% if USE_WHITELIST_IP == "yes" %}true{% else %}false{% endif +%}
|
|
local use_whitelist_reverse = {% if USE_WHITELIST_REVERSE == "yes" %}true{% else %}false{% endif +%}
|
|
local whitelist_ip_list = {% raw %}{{% endraw %}{% if WHITELIST_IP_LIST != "" %}{% set elements = WHITELIST_IP_LIST.split(" ") %}{% for i in range(0, elements|length) %}"{{ elements[i] }}"{% if i < elements|length-1 %},{% endif %}{% endfor %}{% endif %}{% raw %}}{% endraw +%}
|
|
local whitelist_reverse_list = {% raw %}{{% endraw %}{% if WHITELIST_REVERSE_LIST != "" %}{% set elements = WHITELIST_REVERSE_LIST.split(" ") %}{% for i in range(0, elements|length) %}"{{ elements[i] }}"{% if i < elements|length-1 %},{% endif %}{% endfor %}{% endif %}{% raw %}}{% endraw +%}
|
|
|
|
-- blacklist
|
|
local use_blacklist_ip = {% if USE_BLACKLIST_IP == "yes" %}true{% else %}false{% endif +%}
|
|
local use_blacklist_reverse = {% if USE_BLACKLIST_REVERSE == "yes" %}true{% else %}false{% endif +%}
|
|
local blacklist_ip_list = {% raw %}{{% endraw %}{% if BLACKLIST_IP_LIST != "" %}{% set elements = BLACKLIST_IP_LIST.split(" ") %}{% for i in range(0, elements|length) %}"{{ elements[i] }}"{% if i < elements|length-1 %},{% endif %}{% endfor %}{% endif %}{% raw %}}{% endraw +%}
|
|
local blacklist_reverse_list = {% raw %}{{% endraw %}{% if BLACKLIST_REVERSE_LIST != "" %}{% set elements = BLACKLIST_REVERSE_LIST.split(" ") %}{% for i in range(0, elements|length) %}"{{ elements[i] }}"{% if i < elements|length-1 %},{% endif %}{% endfor %}{% endif %}{% raw %}}{% endraw +%}
|
|
|
|
-- dnsbl
|
|
local use_dnsbl = {% if USE_DNSBL == "yes" %}true{% else %}false{% endif +%}
|
|
local dnsbl_list = {% raw %}{{% endraw %}{% if DNSBL_LIST != "" %}{% set elements = DNSBL_LIST.split(" ") %}{% for i in range(0, elements|length) %}"{{ elements[i] }}"{% if i < elements|length-1 %},{% endif %}{% endfor %}{% endif %}{% raw %}}{% endraw +%}
|
|
|
|
-- bad behavior
|
|
local use_bad_behavior = {% if USE_BAD_BEHAVIOR == "yes" %}true{% else %}false{% endif +%}
|
|
|
|
-- limit req
|
|
local use_limit_req = {% if USE_LIMIT_REQ == "yes" %}true{% else %}false{% endif +%}
|
|
|
|
-- remote API
|
|
local use_remote_api = {% if USE_REMOTE_API == "yes" %}true{% else %}false{% endif +%}
|
|
|
|
-- include LUA code
|
|
local whitelist = require "whitelist"
|
|
local blacklist = require "blacklist"
|
|
local dnsbl = require "dnsbl"
|
|
local cookie = require "cookie"
|
|
local cjson = require "cjson"
|
|
local javascript = require "javascript"
|
|
local captcha = require "captcha"
|
|
local recaptcha = require "recaptcha"
|
|
local iputils = require "resty.iputils"
|
|
local behavior = require "behavior"
|
|
local logger = require "logger"
|
|
local redis = require "resty.redis"
|
|
local checker = require "checker"
|
|
local limitreq = require "limitreq"
|
|
|
|
-- user variables
|
|
local antibot_uri = "{{ ANTIBOT_URI }}"
|
|
local whitelist_user_agent = {% raw %}{{% endraw %}{% if WHITELIST_USER_AGENT != "" %}{% set elements = WHITELIST_USER_AGENT.split(" ") %}{% for i in range(0, elements|length) %}"{{ elements[i] }}"{% if i < elements|length-1 %},{% endif %}{% endfor %}{% endif %}{% raw %}}{% endraw +%}
|
|
local whitelist_uri = {% raw %}{{% endraw %}{% if WHITELIST_URI != "" %}{% set elements = WHITELIST_URI.split(" ") %}{% for i in range(0, elements|length) %}"{{ elements[i] }}"{% if i < elements|length-1 %},{% endif %}{% endfor %}{% endif %}{% raw %}}{% endraw +%}
|
|
|
|
-- check if already in whitelist cache
|
|
if use_whitelist_ip and whitelist.ip_cached_ok() then
|
|
ngx.exit(ngx.OK)
|
|
end
|
|
if use_whitelist_reverse and whitelist.reverse_cached_ok() then
|
|
ngx.exit(ngx.OK)
|
|
end
|
|
|
|
-- check if already in blacklist cache
|
|
if use_blacklist_ip and blacklist.ip_cached_ko() then
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
if use_blacklist_reverse and blacklist.reverse_cached_ko() then
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
|
|
-- check if already in dnsbl cache
|
|
if use_dnsbl and dnsbl.cached_ko() then
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
|
|
-- check if IP is whitelisted (only if not in cache)
|
|
if use_whitelist_ip and not whitelist.ip_cached() then
|
|
if whitelist.check_ip(whitelist_ip_list) then
|
|
ngx.exit(ngx.OK)
|
|
end
|
|
end
|
|
|
|
-- check if reverse is whitelisted (only if not in cache)
|
|
if use_whitelist_reverse and not whitelist.reverse_cached() then
|
|
if whitelist.check_reverse(whitelist_reverse_list) then
|
|
ngx.exit(ngx.OK)
|
|
end
|
|
end
|
|
|
|
-- check if URI is whitelisted
|
|
for k, v in pairs(whitelist_uri) do
|
|
if ngx.var.request_uri == v then
|
|
logger.log(ngx.NOTICE, "WHITELIST", "URI " .. v .. " is whitelisted")
|
|
ngx.exit(ngx.OK)
|
|
end
|
|
end
|
|
|
|
-- check if it's certbot
|
|
if use_lets_encrypt and string.match(ngx.var.request_uri, "^/%.well%-known/acme%-challenge/[A-Za-z0-9%-%_]+$") then
|
|
logger.log(ngx.INFO, "LETSENCRYPT", "got a visit from Let's Encrypt")
|
|
ngx.exit(ngx.OK)
|
|
end
|
|
|
|
-- check if IP is blacklisted (only if not in cache)
|
|
if use_blacklist_ip and not blacklist.ip_cached() then
|
|
if blacklist.check_ip(blacklist_ip_list) then
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
end
|
|
|
|
-- check if reverse is blacklisted (only if not in cache)
|
|
if use_blacklist_reverse and not blacklist.reverse_cached() then
|
|
if blacklist.check_reverse(blacklist_reverse_list, dns_resolvers) then
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
end
|
|
|
|
-- check if IP is banned because of "bad behavior"
|
|
if use_bad_behavior and behavior.is_banned() then
|
|
logger.log(ngx.WARN, "BEHAVIOR", "IP " .. ngx.var.remote_addr .. " is banned because of bad behavior")
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
|
|
-- check if IP is banned because of "request limit"
|
|
if use_limit_req then
|
|
{% if USE_LIMIT_REQ == "yes" %}
|
|
{% for k, v in all.items() %}
|
|
{% if k.startswith("LIMIT_REQ_URL") and v != "" +%}
|
|
{% set url = v %}
|
|
{% set rate = all[k.replace("URL", "RATE")] if k.replace("URL", "RATE") in all else "1r/s" %}
|
|
{% set burst = all[k.replace("URL", "BURST")] if k.replace("URL", "BURST") in all else "5" %}
|
|
{% set delay = all[k.replace("URL", "DELAY")] if k.replace("URL", "DELAY") in all else "1" %}
|
|
{% if url == "/" %}
|
|
if limitreq.check("{{ rate }}", {{ burst }}, {{ delay }}) then
|
|
ngx.exit(ngx.HTTP_TOO_MANY_REQUESTS)
|
|
end
|
|
{% else %}
|
|
if ngx.var.uri == "{{ url }}" and limitreq.check("{{ rate }}", {{ burst }}, {{ delay }}) then
|
|
ngx.exit(ngx.HTTP_TOO_MANY_REQUESTS)
|
|
end
|
|
{% endif %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% endif %}
|
|
|
|
end
|
|
|
|
-- our redis client
|
|
local redis_client = nil
|
|
if use_redis then
|
|
redis_client = redis:new()
|
|
local ok, err = redis_client:connect(redis_host, 6379)
|
|
if not ok then
|
|
redis_client = nil
|
|
logger.log(ngx.ERR, "REDIS", "Can't connect to the Redis service " .. redis_host)
|
|
end
|
|
end
|
|
|
|
-- check if IP is in proxies list
|
|
if use_proxies then
|
|
local checker = checker:new("proxies", ngx.shared.proxies_data, redis_client, "simple")
|
|
if checker:check(iputils.ip2bin(ngx.var.remote_addr)) then
|
|
logger.log(ngx.WARN, "PROXIES", "IP " .. ngx.var.remote_addr .. " is in proxies list")
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
end
|
|
|
|
-- check if IP is in abusers list
|
|
if use_abusers then
|
|
local checker = checker:new("abusers", ngx.shared.abusers_data, redis_client, "simple")
|
|
if checker:check(iputils.ip2bin(ngx.var.remote_addr)) then
|
|
logger.log(ngx.WARN, "ABUSERS", "IP " .. ngx.var.remote_addr .. " is in abusers list")
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
end
|
|
|
|
-- check if IP is in TOR exit nodes list
|
|
if use_tor_exit_nodes then
|
|
local checker = checker:new("exit-nodes", ngx.shared.tor_exit_nodes_data, redis_client, "simple")
|
|
if checker:check(iputils.ip2bin(ngx.var.remote_addr)) then
|
|
logger.log(ngx.WARN, "TOR", "IP " .. ngx.var.remote_addr .. " is in TOR exit nodes list")
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
end
|
|
|
|
-- check if user-agent is allowed
|
|
if use_user_agents and ngx.var.http_user_agent ~= nil then
|
|
local whitelisted = false
|
|
for k, v in pairs(whitelist_user_agent) do
|
|
if string.match(ngx.var.http_user_agent, v) then
|
|
logger.log(ngx.NOTICE, "WHITELIST", "User-Agent " .. ngx.var.http_user_agent .. " is whitelisted")
|
|
whitelisted = true
|
|
break
|
|
end
|
|
end
|
|
if not whitelisted then
|
|
local checker = checker:new("user-agents", ngx.shared.user_agents_data, redis_client, "match")
|
|
if checker:check(ngx.var.http_user_agent) then
|
|
logger.log(ngx.WARN, "USER-AGENTS", "User-Agent " .. ngx.var.http_user_agent .. " is blacklisted")
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- check if referrer is allowed
|
|
if use_referrer and ngx.var.http_referer ~= nil then
|
|
local checker = checker:new("referrers", ngx.shared.referrers_data, redis_client, "match")
|
|
if checker:check(ngx.var.http_referer) then
|
|
logger.log(ngx.WARN, "REFERRERS", "Referrer " .. ngx.var.http_referer .. " is blacklisted")
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
end
|
|
|
|
-- check if country is allowed
|
|
if use_country and ngx.var.allowed_country == "no" and not iputils.ip_in_cidrs(ngx.var.remote_addr, cjson.decode(ngx.shared.reserved_ips:get("data"))) then
|
|
logger.log(ngx.WARN, "COUNTRY", "Country of " .. ngx.var.remote_addr .. " is blacklisted")
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
|
|
-- check if IP is in DNSBLs (only if not in cache)
|
|
if use_dnsbl and not dnsbl.cached() then
|
|
if dnsbl.check(dnsbl_list, dns_resolvers) then
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
end
|
|
|
|
-- check if IP is in distributed DB
|
|
if use_remote_api then
|
|
local checker = checker:new("remote-api-db", ngx.shared.remote_api_db, redis_client, "simple")
|
|
if checker:check(iputils.ip2bin(ngx.var.remote_addr)) then
|
|
logger.log(ngx.WARN, "REMOTE API", "IP " .. ngx.var.remote_addr .. " is in the distributed DB")
|
|
ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
end
|
|
end
|
|
|
|
-- cookie check
|
|
if use_antibot_cookie and ngx.var.uri ~= "/favicon.ico" then
|
|
if not cookie.is_set("uri") then
|
|
if ngx.var.request_uri ~= antibot_uri then
|
|
cookie.set({uri = ngx.var.request_uri})
|
|
return ngx.redirect(antibot_uri)
|
|
end
|
|
logger.log(ngx.WARN, "ANTIBOT", "cookie fail for " .. ngx.var.remote_addr)
|
|
return ngx.exit(ngx.HTTP_FORBIDDEN)
|
|
else
|
|
if ngx.var.request_uri == antibot_uri then
|
|
return ngx.redirect(cookie.get("uri"))
|
|
end
|
|
end
|
|
end
|
|
|
|
-- javascript check
|
|
if use_antibot_javascript and ngx.var.uri ~= "/favicon.ico" then
|
|
if not cookie.is_set("javascript") then
|
|
if ngx.var.request_uri ~= antibot_uri then
|
|
cookie.set({uri = ngx.var.request_uri, challenge = javascript.get_challenge()})
|
|
return ngx.redirect(antibot_uri)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- captcha check
|
|
if use_antibot_captcha and ngx.var.uri ~= "/favicon.ico" then
|
|
if not cookie.is_set("captcha") then
|
|
if ngx.var.request_uri ~= antibot_uri then
|
|
cookie.set({uri = ngx.var.request_uri})
|
|
return ngx.redirect(antibot_uri)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- recaptcha check
|
|
if use_antibot_recaptcha and ngx.var.uri ~= "/favicon.ico" then
|
|
if not cookie.is_set("recaptcha") then
|
|
if ngx.var.request_uri ~= antibot_uri then
|
|
cookie.set({uri = ngx.var.request_uri})
|
|
return ngx.redirect(antibot_uri)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- plugins check
|
|
local plugins, flags = ngx.shared.plugins_data:get("plugins")
|
|
if plugins ~= nil then
|
|
for plugin_id in string.gmatch(plugins, "%w+") do
|
|
local plugin = require(plugin_id .. "/" .. plugin_id)
|
|
plugin.check()
|
|
end
|
|
end
|
|
|
|
ngx.exit(ngx.OK)
|
|
|
|
}
|
|
|
|
{% if USE_ANTIBOT == "javascript" +%}
|
|
include {{ NGINX_PREFIX }}antibot-javascript.conf;
|
|
{% elif USE_ANTIBOT == "captcha" +%}
|
|
include {{ NGINX_PREFIX }}antibot-captcha.conf;
|
|
{% elif USE_ANTIBOT == "recaptcha" +%}
|
|
include {{ NGINX_PREFIX }}antibot-recaptcha.conf;
|
|
{% endif %}
|