0%

基于redis+nginx+Lua实现访问白名单黑名单

黑名单一词来源于世界著名的英国的牛津和剑桥等大学。在中世纪初这些学校规定对于犯有不端行为的学生,将其姓名、行为列案记录在黑皮书上,谁的名字上了黑皮书,即使不是终生臭名昭著,也会使人在相当时间内名誉扫地。学生们对学校的这一规定十分害怕,常常小心谨慎,严防越轨行为的发生。在网络SEO优化当中,搜索引擎或者义务用户收集的搜索引擎垃圾制造者列表,可以用于从搜索引擎封杀这些垃圾制造者,或者抵制他们。黑名单启用后,被列入到黑名单的用户(或IP地址、IP包、邮件、病毒等)不能通过。白名单的概念与“黑名单”相对应,如果设立了白名单,则在白名单中的用户(或IP地址、IP包、邮件等)会优先通过,不会被当成垃圾邮件拒收,安全性和快捷性都大大提高。将其含义扩展一步,那么凡有黑名单功能的应用,就会有白名单功能与其对应。

一、准备工作

  1. 添加echo-nginx-module模块

    • git clone https://github.com/openresty/echo-nginx-module.git /usr/local/echo-nginx-module

    • 切换到nginx源码目录 cd /usr/local/src/nginx

    • 重新执行 ./configure –prefix=/usr/local/nginx –add-module=/usr/local/echo-nginx-module

    • 若提示错误少什么依赖就安装相应的依赖,无提示则执行 make && make install

    • 网上还有另一种方法,同理可以添加别的模块

    1
    2
    3
    4
    git clone https://github.com/nginx/nginx.git
    git submodule add git@github.com:openresty/echo-nginx-module.git
    #重新配置nginx,把echo-nginx-module模块编译进nginx可执行文件
    sudo ./configure --add-module=echo-nginx-module
  2. 安装 ngx_devel_kit (NDK) 模块

  3. 添加lua-nginx-module模块

  4. 重新编译nginx

    1
    2
    3
    4
    5
    6
    7
    ./configure --prefix=/usr/local/nginx 
    --with-ld-opt="-Wl,-rpath,$LUAJIT_LIB"
    --add-module=/usr/local/ngx_devel_kit
    --add-module=/usr/local/echo-nginx-module
    --add-module=/usr/local/lua-nginx-module
    make -j2
    make install
  5. 重启nginx服务器

  6. 测试Lua,在nginx.conf配置文件server代码块中加入以下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    location /echo { 
    default_type 'text/plain';
    echo 'install echo module success!';
    }
    location /lua {
    default_type 'text/plain';
    content_by_lua 'ngx.say("install lua module success!")';
    }
  7. curl http://localhost/echo // 正常的话输出:install echo module success!

  8. curl http://localhost/lua // 正常的话输出:install lua module success!

二、实现

  1. 实现原理:通过在nginx上进行访问限制,通过lua来灵活实现业务需求,redis用于存储黑名单列表

  2. 具体过程

    • step1:lua代码(post请求,ip地址黑名单,请求参数中imsi,tel值和黑名单)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    [root@git-server ~]# cat /usr/local/nginx/conf/lua/ipblacklist.lua
    ngx.req.read_body()

    local redis = require "resty.redis"
    local red = redis.new()
    red.connect(red, '127.0.0.1', '6379')

    local myIP = ngx.req.get_headers()["X-Real-IP"]
    if myIP == nil then
    myIP = ngx.req.get_headers()["x_forwarded_for"]
    end
    if myIP == nil then
    myIP = ngx.var.remote_addr
    end

    if ngx.re.match(ngx.var.uri,"^(/webapi/).*$") then
    local method = ngx.var.request_method
    if method == 'POST' then
    local args = ngx.req.get_post_args()

    local hasIP = red:sismember('black.ip',myIP)
    local hasIMSI = red:sismember('black.imsi',args.imsi)
    local hasTEL = red:sismember('black.tel',args.tel)
    if hasIP==1 or hasIMSI==1 or hasTEL==1 then
    --ngx.say("This is 'Black List' request")
    ngx.exit(ngx.HTTP_FORBIDDEN)
    end
    else
    --ngx.say("This is 'POST' request")
    ngx.exit(ngx.HTTP_FORBIDDEN)
    end
    end
    • step2:修改nginx.conf
    1
    2
    3
    4
    5
    6
    7
    location / {
    root html;
    index index.html index.htm;
    access_by_lua_file /usr/local/nginx/conf/lua/ipblacklist.lua;
    proxy_pass http://127.0.0.1:8080;
    client_max_body_size 1m;
    }
    • step3:添加黑名单规则数据
    1
    2
    3
    redis-cli sadd black.ip '192.160.10.10'
    redis-cli sadd black.imsi '460123456789'
    redis-cli sadd black.tel '15888888888'
    • step4:验证结果
    1
    curl -d "imsi=460123456789&tel=15800000000" "http://yourdomain/index.php"