Skip to content

IP-Block-Ltd/ipblock-nginx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

⚠️ Status: untested. This extension is provided as-is and has not been tested in production. Please feel free to fork, modify, improve, and open pull requests.

Licensed under GNU GPLv3 (see LICENSE).

IP Block for NGINX

Two integration approaches are provided — pick one:

  • OpenResty / Lua (openresty-lua/) — richest, uses lua-resty-http + shared-dict cache.
  • Stock nginx auth_request (auth_request/) — no Lua; delegates to a small FastCGI checker.

Variant 1 — OpenResty / Lua

IP Block for NGINX (OpenResty / lua-nginx)

Blocks requests at the edge by consulting the ip-block.com decision API from OpenResty's access phase, with a per-IP decision cache in a lua_shared_dict.

  • Tested with: OpenResty 1.31.1.1 (latest stable, June 2026), which bundles ngx_http_lua_module + LuaJIT.
  • Dependency: lua-resty-http 0.17.x (resty.http).

Files

File Purpose
ip_block.lua The module. Contains init(opts) and access(opts).
nginx.conf Complete, commented example configuration.

Install

  1. Install OpenResty and lua-resty-http:

    # lua-resty-http via the OpenResty package manager
    opm get ledgetech/lua-resty-http
    # or via LuaRocks:  luarocks install lua-resty-http
  2. Copy ip_block.lua somewhere on your Lua package path, e.g. /etc/openresty/ip-block/ip_block.lua.

  3. In your http {} block add (see nginx.conf for the full version):

    lua_package_path "/etc/openresty/ip-block/?.lua;;";
    lua_shared_dict ip_block_cache 10m;
    lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
    resolver 1.1.1.1 8.8.8.8 ipv6=off;
    
    init_by_lua_block {
        require("ip_block").init({
            site_id = "your-site-id",
            api_key = "your-api-key",
        })
    }
  4. In the server {} or location {} you want protected:

    access_by_lua_block { require("ip_block").access() }
  5. Reload: openresty -s reload (or nginx -s reload).

Configuration

Pass options to init() (global) or access({...}) (per-location override).

Option Default Meaning
enabled true Master on/off switch.
site_id "" Your ip-block.com site id.
api_key "" Your API key (sent in the JSON body).
api_url https://api.ip-block.com/v1/check Decision endpoint.
fail_open true On any error/timeout/non-2xx, allow the request. Set false to fail closed.
timeout_ms 1000 Per-request timeout (connect+send+read).
cache_ttl 300 Seconds to cache a per-IP decision (0 disables caching).
cache_name ip_block_cache Name of the lua_shared_dict.
behind_proxy false If true, read the client IP from real_ip_header.
real_ip_header X-Forwarded-For Header to read the client IP from. Left-most entry is used.
block_action 403 403 (plain deny) or redirect.
block_redirect_url https://www.ip-block.com/blocked.php Used when block_action=redirect.
block_message Access denied. Body text for the 403.
whitelist {} Array of IPs that are never checked.

You can source secrets from the environment (os.getenv) as shown in nginx.conf. Make sure the variables are visible to the nginx master process (e.g. via env IPBLOCK_API_KEY; in the main config and your service manager).

Behaviour

  • Only {"action":"block"} blocks. Anything else (including malformed or missing action) is treated per the fail_open policy.
  • Errors are not cached, so a transient API outage does not pin an IP; the next request retries. Successful allow/block decisions are cached for cache_ttl.
  • Whitelisted IPs short-circuit before any cache or API call.

Notes

  • ssl_verify = true requires lua_ssl_trusted_certificate to point at a valid CA bundle, and a working resolver.
  • The cache is shared across all worker processes of a single nginx instance. For a fleet of nginx nodes, each node keeps its own cache (that is fine — decisions are idempotent and short-lived).

Variant 2 — stock nginx (auth_request)

IP Block for NGINX (pure nginx, auth_request)

An alternative to the OpenResty/Lua module that works with stock nginx — no Lua at the proxy layer. It uses the built-in ngx_http_auth_request_module to run an internal subrequest against a small checker for every request.

  • Tested with: nginx 1.28 (stable) / 1.29 (mainline). The auth_request module is included in the official nginx.org packages (build flag --with-http_auth_request_module; verify with nginx -V).
  • Checker runtime: PHP 8 via php-fpm (checker.php). Any HTTP endpoint that returns 2xx = allow / 403 = block can be substituted.

Files

File Purpose
nginx.conf auth_request wiring + internal /_ip_block_check location.
checker.php FastCGI checker: calls the API, caches per-IP, returns 204/403.

How it works

client --> nginx (location /)
              |  auth_request /_ip_block_check   (internal GET subrequest)
              v
           checker.php  --POST /v1/check-->  api.ip-block.com
              |  204 allow  / 403 block
              v
   allow: serve content   |   block: 403 -> optional redirect to blocked.php

auth_request drops the request body and method on the subrequest, so nginx forwards the real client IP, User-Agent and Referer to the checker as FastCGI params. 2xx from the checker allows the request; 401/403 denies it.

Install

  1. Confirm your nginx has the module: nginx -V 2>&1 | grep -o with-http_auth_request_module.
  2. Copy checker.php to e.g. /etc/nginx/ip-block/checker.php and make sure the php-fpm pool can read it.
  3. Merge the upstream, location /, @ip_block_denied and = /_ip_block_check blocks from nginx.conf into your config. Point fastcgi_pass at your php-fpm socket/port and SCRIPT_FILENAME at the checker's real path.
  4. Set your IPB_SITE_ID / IPB_API_KEY (and other params) in the = /_ip_block_check location, or export them to php-fpm as environment vars.
  5. nginx -t && nginx -s reload.

Configuration (FastCGI params / env vars)

Param Default Meaning
IPB_SITE_ID Your site id.
IPB_API_KEY API key (sent in JSON body).
IPB_API_URL https://api.ip-block.com/v1/check Decision endpoint.
IPB_FAIL_OPEN 1 1 = allow on error/timeout; 0 = fail closed.
IPB_TIMEOUT_MS 1000 API timeout.
IPB_CACHE_TTL 300 Per-IP cache seconds (0 disables).
IPB_CACHE_DIR system temp /ip-block-cache Disk cache location.
IPB_WHITELIST Comma-separated IPs never checked.
IPB_CLIENT_IP $remote_addr Real client IP (set from realip in nginx).
IPB_USER_AGENT / IPB_REFERRER Forwarded from the client request.

Getting the real client IP

If nginx is behind a CDN/load-balancer, enable the realip module in http{} so $remote_addr becomes the true client address:

set_real_ip_from 10.0.0.0/8;   # your trusted proxy range(s)
real_ip_header   X-Forwarded-For;
real_ip_recursive on;

Behaviour

  • Only {"action":"block"} blocks; everything else allows (subject to fail_open).
  • Errors are not cached; the next request retries the API.
  • Whitelisted IPs short-circuit before the cache and API call.

Caching notes

checker.php uses a simple on-disk cache (one file per site+IP). For higher volume swap the two file_get_contents/file_put_contents cache calls for APCu, Redis, or memcached. The OpenResty variant in ../openresty-lua/ uses an in-memory lua_shared_dict and is faster if you can run OpenResty.

About

IP Block protection for NGINX / OpenResty — ip-block.com integration. Untested at the moment; please feel free to modify. GPLv3.

Topics

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors