zoukankan      html  css  js  c++  java
  • nginx + lua + redis 动态封ip

    PHP 设置正则

    <?php
    
    namespace MainController;
    
    
    use KIFCacheDisRedis;
    use KIFCoreRequest;
    
    /**
     *  涉及文件
     * /export/manager/ybyl/main/config/route.inc.php
     * /export/manager/ybyl/main/lib/Controller/QiniuAuth.class.php
     *
     */
    
    <<<EOF
    禁止ip设置
    
    查看禁止ip列表
    /usr/local/php7.4/bin/php /export/manager/ybyl/main/www/index.php -c=QiniuAuth -a=list
    
    增加
    /usr/local/php7.4/bin/php /export/manager/ybyl/main/www/index.php -c=QiniuAuth -a=add -i=2408:84e1:60:*:*:*:*:*
    
    删除
    /usr/local/php7.4/bin/php /export/manager/ybyl/main/www/index.php -c=QiniuAuth -a=del -i=IP1,IP2
    
    清除所有配置
    /usr/local/php7.4/bin/php /export/manager/ybyl/main/www/index.php -c=QiniuAuth -a=clearAll
    
    EOF;
    
    class QiniuAuth extends Controller
    {
        protected $objDisRedis;
        protected $bannedIpKey = 'bannedips';
        protected $bannedIpPreg = 'ip_blacklist_preg';
    
        public function __construct()
        {
            $this->objDisRedis = new DisRedis();
        }
    
        /**
         *
         * /?c=qiniuAuth
         * 七牛cdn鉴权
         * 'HTTP_CIP' => '106.3.135.101',
         * 'HTTP_CIP' => '2408:84e1:60:4979:2d11:d97e:a7c0:b0d7',
         * //  'HTTP_AUTHFROM' => 'qiniu',
         *
         */
        public function doDefault()
        {
            $userip = $_SERVER['HTTP_CIP'];
            $preg = $this->objDisRedis->get($this->bannedIpPreg);
            if (!$userip || $preg && preg_match($preg, $userip)) {
                header("HTTP/1.0 401 Unauthorized");
                header("Status: 401 Unauthorized");
                exit();
            } else {
                header("HTTP/1.0 200 OK");
                header("Status: 200 OK");
                exit();
            }
        }
    
        /**
         * /usr/local/php7.4/bin/php /export/manager/xx/main/www/index.php -c=QiniuAuth -a=Add -i=
         * 添加限制访问ip, 支持多个
         * 界面: 以换行符分割, 命令行: 以逗号分割
         * // hash 表
         */
        public function doAdd()
        {
            if (Request::isCLI()) {
                $opts = getopt('a:c:i:');
                $ips = $opts['i'];
                $ips = explode(',', $ips);
            } else {
                $ips = Request::p('ips');
                $ips = explode("
    ", $ips);
            }
            $ips = array_filter($ips);
            if (empty($ips)) {
                $this->ajax_fail_exit('no ips');
            }
    
            foreach ($ips as $ip) {
                $this->objDisRedis->hSet($this->bannedIpKey, $ip, time());
            }
            $setRes = $this->setBannedIpPreg();
            if(!$setRes) {
                $this->ajax_fail_exit('cache ip preg error');
            }
            $this->ajax_success_exit('success');
        }
    
        /**
         *
         * 删除限制访问ip, 支持多个
         * 界面: 以换行符分割, 命令行: 以逗号分割
         * // hash 表
         */
        public function doDel()
        {
            if (Request::isCLI()) {
                $opts = getopt('a:c:i:');
                $ips = $opts['i'];
                $ips = explode(',', $ips);
            } else {
                $ips = Request::p('ips');
                $ips = explode("
    ", $ips);
            }
            $ips = array_filter($ips);
            if (empty($ips)) {
                $this->ajax_fail_exit('no ips');
            }
            $res = $this->objDisRedis->hDel($this->bannedIpKey, $ips);
            $setRes = $this->setBannedIpPreg();
            if(!$setRes) {
                $this->ajax_fail_exit('cache ip preg error');
            }
            if ($res) {
                $this->ajax_success_exit('success');
            } else {
                $this->ajax_fail_exit('fail');
            }
        }
    
        /**
         * 清除所有配置
         */
        public function doClearAll() {
            $res = $this->objDisRedis->del([$this->bannedIpPreg, $this->bannedIpKey]);
            if ($res) {
                $this->ajax_success_exit('clear success');
            } else {
                $this->ajax_fail_exit('clear fail');
            }
        }
    
        /**
         * 列出所有设置的
         */
        public function doList()
        {
            $ips = $this->objDisRedis->hGetAll($this->bannedIpKey);
            $str = "Ip	添加时间" . PHP_EOL;
            foreach($ips as $ip => $addTime) {
                $str .= $ip . "	" . date('Y-m-d H:i:s', $addTime) . PHP_EOL;
            }
            echo $str;
            echo PHP_EOL;
    
            echo 'preg: ' . PHP_EOL;
            echo $this->objDisRedis->get($this->bannedIpPreg);
            echo PHP_EOL;
            echo PHP_EOL;
        }
    
        protected function setBannedIpPreg() {
            $ips = $this->objDisRedis->hGetAll($this->bannedIpKey);
            $bannedIps = array_keys($ips);
            $str = '';
            if(!empty($bannedIps)) {
                $str = implode('|', $bannedIps);
                $str = '(' . $str . ')';
                // for php
    //            $str = str_replace('.', '.', $str);
    //            $str = str_replace('*', '.*', $str);
    
                // for lua
                $str = str_replace('.', '.', $str);
                $str = str_replace('*', '[wW]+', $str);
            }
            return $this->objDisRedis->set($this->bannedIpPreg, $str);
        }
    
    
        public function display()
        {
            return $this->render();
        }
    }

    nginx 配置

    worker_processes  1;
    error_log logs/error.log;
    events {
        worker_connections 1024;
    }
    http {
        lua_package_path /usr/local/openresty/nginx/lua/lua-resty-redis/lib/resty/redis.lua;
        lua_shared_dict ip_blacklist 1m;
        server {
            listen 8080;
    
            location / {
                default_type text/html;
                access_by_lua_file lua/ip_blacklist.lua;
                content_by_lua_block {
                    ngx.say("<p>hello, world</p>")
                }
    
            }
        }
    }

    lua脚本

    ip_blacklist.lua 只返回状态码, 七牛cdn鉴权用

    local redis_host = "127.0.0.1"
    local redis_port = 6379
    local redis_db = 0;
    local redis_auth = "17kb.com"
    
    -- connection timeout for redis in ms. don't set this too high!
    local redis_connection_timeout = 100
    
    -- check a set with this key for blacklist entries
    local redis_key = "ip_blacklist_preg"
    
    -- cache lookups for this many seconds
    local cache_ttl = 60
    
    -- end configuration
    
    local ip = ngx.var.remote_addr
    local ip_blacklist = ngx.shared.ip_blacklist
    local last_update_time = ip_blacklist:get("last_update_time");
    
    if last_update_time == nil or last_update_time < ( ngx.now() - cache_ttl ) then
        local redis = require "resty.redis";
        local red = redis:new();
        red:set_timeout(redis_connect_timeout);
        local ok, err = red:connect(redis_host, redis_port);
    
        if not ok then
            -- ngx.log(ngx.DEBUG, "Redis connection error while retrieving ip_blacklist:");
        else
            local res, err = red:auth(redis_auth)
            if not res then
                -- ngx.log(ngx.DEBUG, "failed to authenticate: " .. err);
            else
                red:select(redis_db)
                local new_ip_blacklist_preg, err = red:get(redis_key);
                if err then
                    -- ngx.log(ngx.DEBUG, "Redis read error while retrieving ip_blacklist:" .. err);
                else
                    -- replace the locally stored ip_blacklist with the updated values:
                    ip_blacklist:flush_all();
    
                    ip_blacklist:set(redis_key, new_ip_blacklist_preg);
    
                    -- update time
                    ip_blacklist:set("last_update_time", ngx.now());
                end
            end
        end
    end
    
    local regex = ip_blacklist:get(redis_key)
    if regex then
        local m  = ngx.re.match( ip, regex, "oj") 
        if m then
             return ngx.exit(401);
        else
            return ngx.exit(200);
        end
    else
        return ngx.exit(200);
    end

     

  • 相关阅读:
    ES6:Iterator遍历器
    前端:对BFC的理解
    前端:性能优化之防抖与节流
    ES6新增数据类型Symbol
    ajax和fetch、aixos的区别
    我对js数据类型的理解和深浅(copy)的应用场景
    egg的基本使用
    前端:css3的过渡与动画的基础知识
    Java基础篇之类
    JAVA基础篇之Scanner
  • 原文地址:https://www.cnblogs.com/bandbandme/p/13307385.html
Copyright © 2011-2022 走看看