@ -1,15 +1,14 @@
# OpenResty configuration — replaces the previous nginx + libnginx-mod-http-geoip2 stack.
# ASN-based blocking moved to blocklist.lua using lua-resty-maxminddb (pure Lua, no C module).
load_module modules/ngx _http_geoip2_module.so ;
# Make POD_NAMESPACE and Redis URL available to Lua.
env POD_NAMESPACE ;
env REDIS_URL ;
user www-data ;
user www-data nginx ;
worker_processes 1 ;
error_log /var/log/openresty /error.log warn ;
pid /var/run/openresty .pid ;
error_log /var/log/nginx /error.log warn ;
pid /var/run/nginx .pid ;
events {
@ -18,7 +17,7 @@ events {
http {
include /usr/local/openresty/nginx/conf /mime.types ;
include /etc/nginx /mime.types ;
default_type application/octet-stream ;
# ----------------------------------------------------------------
@ -36,7 +35,7 @@ http {
'"$http_user_agent" " $http_x_forwarded_for" '
'rt=$request_time' ;
access_log /var/log/openresty /access.log main ;
access_log /var/log/nginx /access.log main ;
# ----------------------------------------------------------------
# FIX: kernel bypass — was off (disables zero-copy file serving)
@ -70,7 +69,29 @@ http {
limit_req_zone $binary_remote_addr zone=sapl_heavy:10m rate=10r/m ;
# ----------------------------------------------------------------
# Bot blocking by User-Agent (nginx map — no module required).
# ASN-Based Blocking (datacenter / scraper ASNs).
# Requires libnginx-mod-http-geoip2 and GeoLite2-ASN.mmdb.
# ----------------------------------------------------------------
geoip2 /etc/nginx/geoip/GeoLite2-ASN.mmdb {
$geoip2_asn_number autonomous_system_number ;
$geoip2_asn_org autonomous_system_organization ;
}
map $geoip2_asn_number $bot_asn {
default 0 ;
16509 1 ; # Amazon AWS
14618 1 ; # Amazon AWS us-east
8075 1 ; # Microsoft Azure
396982 1 ; # Google Cloud
20473 1 ; # Vultr
24940 1 ; # Hetzner
16276 1 ; # OVH
36352 1 ; # ColoCrossing
63949 1 ; # Linode / Akamai
}
# ----------------------------------------------------------------
# Bot blocking by User-Agent.
# Chrome/98.0.4758 is a confirmed scraper (no real user runs a
# 2022 browser version in 2026 ). Googlebot excluded for SEO.
# ----------------------------------------------------------------
@ -91,29 +112,22 @@ http {
}
# ----------------------------------------------------------------
# OpenResty: open MaxMind ASN DB on ce in master (workers inherit fd) .
# ASN-based blocking runs in blocklist.lua via lua-resty-maxminddb .
# Lua: search path for Debian-packaged resty.* libraries .
# lua-resty-redis installs to /usr/share/lua/5.1/resty/redis.lua .
# ----------------------------------------------------------------
init_by_lua_block {
local ok, mmdb = pcall(require, "resty.maxminddb")
if ok then
local db_path = "/usr/local/openresty/nginx/conf/geoip/GeoLite2-ASN.mmdb"
pcall(function() mmdb.init(db_path) end)
end
}
lua_package_path '/usr/share/lua/5.1/?.lua ; ;' ;
# ----------------------------------------------------------------
# OpenResty: s hared dict for IP-prefix deny list (refreshed every 60s).
# Shared dict for IP-prefix deny list (refreshed every 60s).
# 1 MB holds ~ 10,000 prefix entries with overhead to spare.
# ----------------------------------------------------------------
lua_shared_dict ip_prefix_blocked 1m ;
# ----------------------------------------------------------------
# OpenResty: background timer populates ip_prefix_blocked from Redis.
# Runs on ce per worker process at startup, then every 60s.
# Background timer: populates ip_prefix_blocked from Redis DB 1 .
# Runs on ce per worker at startup, then every 60s.
# ----------------------------------------------------------------
init_worker_by_lua_block {
-- Parse REDIS_URL (redis://host:port or redis://host:port/db).
local url = os.getenv("REDIS_URL") or "redis://127.0.0.1:6379"
local REDIS_HOST, port_str = url:match("redis://([^:/]+):(%d+)")
if not REDIS_HOST then REDIS_HOST = url:match("redis://([^:/]+)") or "127.0.0.1" end
@ -136,7 +150,6 @@ http {
local dict = ngx.shared.ip_prefix_blocked
dict:flush_all()
for _, m in ipairs(members) do
-- Normalise: strip trailing dot, re-add unless it's a full dotted-quad.
local stripped = m:gsub("%. $", "")
local key = (select(2, stripped:gsub("%.", "")) < 3 )
and (stripped .. ".") or stripped
@ -156,5 +169,5 @@ http {
gzip_types text/plain text/css text/javascript application/javascript application/x-javascript text/xml application/xml application/rss+xml image/gif image/png image/x-icon image/jpeg image/svg+xml ;
gzip_vary on ;
include /usr/local/openresty/nginx/conf /conf.d/*.conf ;
include /etc/nginx /conf.d/*.conf ;
}