Skip to content

Instantly share code, notes, and snippets.

@heartshare
Forked from chrisboulton/ip_blacklist.lua
Last active August 26, 2015 05:50
Show Gist options
  • Save heartshare/6bbdb40ec32cfe026d5b to your computer and use it in GitHub Desktop.
Save heartshare/6bbdb40ec32cfe026d5b to your computer and use it in GitHub Desktop.

Revisions

  1. @chrisboulton chrisboulton revised this gist Jul 20, 2013. 1 changed file with 0 additions and 3 deletions.
    3 changes: 0 additions & 3 deletions ip_blacklist.lua
    Original file line number Diff line number Diff line change
    @@ -24,9 +24,6 @@
    --
    -- access_by_lua_file /etc/nginx/lua/ip_blacklist.lua;
    --
    -- you need to create and set the size of a shared dictionary in the
    -- http {} stanza of your nginx configuration:
    --
    -- chris boulton, @surfichris

    local redis_host = "your.redis.server.here"
  2. @chrisboulton chrisboulton created this gist Jul 20, 2013.
    96 changes: 96 additions & 0 deletions ip_blacklist.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,96 @@
    -- a quick LUA access script for nginx to check IP addresses against an
    -- `ip_blacklist` set in Redis, and if a match is found send a HTTP 403.
    --
    -- allows for a common blacklist to be shared between a bunch of nginx
    -- web servers using a remote redis instance. lookups are cached for a
    -- configurable period of time.
    --
    -- block an ip:
    -- redis-cli SADD ip_blacklist 10.1.1.1
    -- remove an ip:
    -- redis-cli SREM ip_blacklist 10.1.1.1
    --
    -- also requires lua-resty-redis from:
    -- https://github.com/agentzh/lua-resty-redis
    --
    -- your nginx http context should contain something similar to the
    -- below: (assumes resty/redis.lua exists in /etc/nginx/lua/)
    --
    -- lua_package_path "/etc/nginx/lua/?.lua;;";
    -- lua_shared_dict ip_blacklist_cache 10m;
    --
    -- you can then use the below (adjust path where necessary) to check
    -- against the blacklist in a http, server, location, if context:
    --
    -- access_by_lua_file /etc/nginx/lua/ip_blacklist.lua;
    --
    -- you need to create and set the size of a shared dictionary in the
    -- http {} stanza of your nginx configuration:
    --
    -- chris boulton, @surfichris

    local redis_host = "your.redis.server.here"
    local redis_port = 6379

    -- connection timeout for redis in ms. don't set this too high!
    local redis_timeout = 200

    -- check a set with this key for blacklist entries
    local redis_key = "ip_blacklist"

    -- cache lookups for this many seconds
    local cache_ttl = 60

    -- end configuration

    local ip = ngx.var.remote_addr
    local ip_blacklist_cache = ngx.shared.ip_blacklist_cache

    -- setup a local cache
    if cache_ttl > 0 then
    -- lookup the value in the cache
    local cache_result = ip_blacklist_cache:get(ip)
    if cache_result then
    ngx.log(ngx.DEBUG, "ip_blacklist: found result in cache for "..ip.." -> "..cache_result)

    if cache_result == 0 then
    ngx.log(ngx.DEBUG, "ip_blacklist: (cache) no result found for "..ip)
    return
    end

    ngx.log(ngx.INFO, "ip_blacklist: (cache) "..ip.." is blacklisted")
    return ngx.exit(ngx.HTTP_FORBIDDEN)
    end
    end

    -- lookup against redis
    local resty = require "resty.redis"
    local redis = resty:new()

    redis:set_timeout(redis_timeout)

    local connected, err = redis:connect(redis_host, redis_port)
    if not connected then
    ngx.log(ngx.ERR, "ip_blacklist: could not connect to redis @"..redis_host..": "..err)
    return
    end

    local result, err = redis:sismember("ip_blacklist", ip)
    if not result then
    ngx.log(ngx.ERR, "ip_blacklist: lookup failed for "..ip..":"..err)
    return
    end

    -- cache the result from redis
    if cache_ttl > 0 then
    ip_blacklist_cache:set(ip, result, cache_ttl)
    end

    redis:set_keepalive(10000, 2)
    if result == 0 then
    ngx.log(ngx.INFO, "ip_blacklist: no result found for "..ip)
    return
    end

    ngx.log(ngx.INFO, "ip_blacklist: "..ip.." is blacklisted")
    return ngx.exit(ngx.HTTP_FORBIDDEN)