• Openresty+Redis自动封禁访问频率过高IP


    ​在IP地址为w.w.w.w的服务器上安装nginx+luq+redis服务

    实现思路:通过在Nginx上进行访问限制,通过Lua来灵活实现业务需求,而Redis用于存储黑名单列表。

    Nginx+Lua+Redis安装

    研究目标:nginx中使用lua脚本及nginx直接访问redis。

    需要下载安装的内容:openresty和redis

    第一步,安装编译工具及库文件,如果服务器上已经有了,可以不用再安装。

    命令:yum install -y gcc gcc-c++ readline-devel pcre-devel openssl openssl-devel tcl perl make zlib zlib-devel libtool

    第二步,采用OpenResty方式安装 Nginx+Lua模块。

    OpenResty/ngx_openresty是一个全功能的 Web 应用服务器。它打包了标准的 Nginx 核心,很多的常用的第三方模块,以及它们的大多数依赖项。在网址:下载OpenResty。

    命令:cd /usr/local/src

    wget

    tar xzvf openresty-1.19.3.2.tar.gz

    mv openresty-1.19.3.2 openresty

    cd openresty/

    ./configure --prefix=/usr/local/src/openresty/nginx

    --with-luajit

    make

    make install

    查看nginx版本命令:

    /usr/local/src/openresty/nginx/sbin/nginx -v

    或 /usr/local/src/openresty/nginx/sbin/nginx -V

    结果显示“nginx version: openresty/1.19.3.2”,nginx就安装完成。

    第三步,安装redis。

    下载redis安装包命令:mkdir /usr/local/redisfile

    cd /usr/local/redisfile

    wget http://download.redis.io/releases/redis-4.0.10.tar.gz

    解压安装包命令:tar zxvf redis-4.0.10.tar.gz

    编译安装命令:cd redis-4.0.10

    make

    cd /usr/local/redisfile/redis-4.0.10/src

    make install

    Nginx+Lua+Redis配置

    第一步,创建 Nginx 运行使用的用户nginx。

    命令:useradd -s /sbin/nologin -M nginx

    ( Nginx 服务的默认用户是 nobody ,为了安全更改为 nginx,在配置文件中启用user nginx nginx;)

    第二步,修改nginx配置文件。

    配置nginx.conf文件,nginx.conf路径为/usr/local/src/openresty/nginx/conf/nginx.conf。文件内容如下:

    user nginx nginx;  #用户名设置为刚刚创建的用户名
    worker_processes  4; #允许生成的进程数,默认为1
    worker_cpu_affinity 0001 0010 0100 1000;
    error_log  /var/log/nginx/error.log info; #日志位置和级别
    pid      /var/run/nginx.pid; #指定nginx进程运行文件存放地址
    worker_rlimit_nofile 102400; #最大连接数,默认为512
    events {
        use epoll; #事件驱动模型
        worker_connections 102400; #最大连接数,默认为512
        accept_mutex off; #设置网路连接序列化,防止惊群现象发生,默认为on
        multi_accept on; #设置一个进程是否同时接受多个网络连接,默认为off
    }
    http
    {
        include mime.types;
        default_type application/octet-stream;
        ...
        server
        {
            listen 8080;  #监听端口
            server_name localhost;  #域名,当前IP地址
            charset utf-8;  #编码改为utf-8
            ...
    }

    第三步,修改redis配置文件。

    1)为了方便管理,在/usr/local中新建/redis/etc文件夹,并在将/usr/local/redisfile/redis-4.0.10文件夹中的conf配置文件复制粘贴到/usr/local/redis/etc。原生的配置文件不用变,改完之后还能回到原来的样子,以保证安全。

    命令:cp /usr/local/redisfile/redis-4.0.10/redis.conf /usr/local/redis/etc

    2)在/usr/local中新建/redis/bin文件夹,/usr/local/redisfile/redis-4.0.10/src文件夹中的常用命令复制粘贴到/usr/local/redis/bin。

    命令:cd /usr/local/redisfile/redis-4.0.10/src
    cp mkreleasdhdr.sh redis-benchmark redis-check-aof redis-check-dump redis-cli redis-server /usr/local/redis/bin

    3)redis开启访问权限的方法。

    编辑配置/usr/local/redis/etc/redis.conf文件,修改“bind 127.0.0.1”为“bind 0.0.0.0”,再把“daemonize no”改为“daemonize yes”,“requirepass foobared”改为“requirepass 123456”,“dir ./”改为“dir /usr/local/redis/db”,“logfile ”改为“logfile /usr/local/redis/logs/redis.log”,保存并重启redis。

    Nginx+Lua+Redis启动和访问站点

    第一步,启动nginx。

    命令:/usr/local/src/openresty/nginx/sbin/nginx

    第二步,检查nginx是否已经启动。(查看是否有进程)

    命令:ps -ef | grep nginx

    结果的第一行显示“nginx:master process”,nginx已经启动。

    注意:nginx:master process后面有一个路径,这就是nginx的安装路径。

    第三步,访问nginx站点。

    从浏览器访问已经配置好的站点IP,如果页面显示“Welcome to OpenResty!”,则说明OpenResty已经安装及配置好了。

    第四步,关闭nginx。

    命令:cd /usr/local/src/openresty/nginx/sbin

    ./nginx -s stop

    第五步,配置文件修改后,需要指定配置文件进行nginx重启。

    如果nginx服务已经停止,那就需要把nginx服务启动。

    命令:/usr/local/src/openresty/nginx/sbin/nginx -c /usr/local/src/openresty/nginx/conf/nginx.conf

    重启nginx服务必须是在nginx服务已经启动的情况下进行,因为这时,/usr/local/nginx/logs中存在nginx.pid文件。

    命令:/usr/local/src/openresty/nginx/sbin/nginx -s reload

    第六步,前台启动redis服务。

    命令:cd /usr/local/redis/bin

    ./redis-server

    注意:执行完该命令后,如果Lunix关闭当前会话,则redis服务也随即关闭。正常情况下,启动redis服务需要从后台启动,并且指定启动配置文件。

    第七步,后台启动redis服务。

    再次启动redis服务,并指定启动服务配置文件。

    命令:cd /usr/local/redis/bin

    ./redis-server & #不会带上redis.conf配置文件启动

    redis-server /usr/local/redis/etc/redis.conf

    #结果第一行最后面显示redis端口

    ps -ef | grep redis

    #结果第一行最后面显示redis进程号

    netstat -nap | grep 6379

    服务端启动成功后,启动redis 客户端,查看端口号。

    命令:redis-cli

    auth 123456

    set [key] [value]

    get [key]

    exit

    netstat -nap | grep 6379

    第八步,前台和后台关闭redis服务。

    命令:cd /usr/local/redis/bin

    pkill redis-server

    redis-cli shutdown

    netstat -nap | grep 6379

    在Nginx中使用Lua脚本访问Redis

    第一步,连接redis,然后添加一些测试参数。

    命令:redis-cli

    auth 123456

    set "123" "456"

    第二步,编写链接redis的Lua脚本。

    在/usr/local/src/openresty/nginx/conf/lua中新建脚本文件redis.lua,在文件中写入下面的脚本:

    local redis = require "resty.redis"
    
    local conn = redis.new()
    
    conn.connect(conn,'127.0.0.1','6379')
    
    conn.auth('123456')
    
    local res = conn:get("123")
    
    if res==ngx.null then
    
        ngx.say("redis集群中不存在KEY——'123'")
    
        return
    
    end
    
    ngx.say(res)

    第三步,编写访问控制的Lua脚本。

    在/usr/local/src/openresty/nginx/conf/lua中新建脚本文件access.lua,在文件中写入下面的脚本:

    local ip_block_time=300 --封禁IP时间(秒)
    
    local ip_time_out=30    --指定ip访问频率时间段(秒)
    
    local ip_max_count=20 --指定ip访问频率计数最大值(秒)
    
    local BUSINESS = ngx.var.business --nginx的location中定义的业务标识符
    
    --连接redis
    
    local redis = require "resty.redis"
    
    local conn = redis:new()
    
    ok, err = conn:connect("127.0.0.1", 6379)
    
    conn:set_timeout(2000) --超时时间2秒
    
    ok, err = conn:auth("123456")
    
    --如果连接失败,跳转到脚本结尾
    
    if not ok then
    
        goto FLAG
    
    end
    
    --查询ip是否被禁止访问,如果存在则返回403错误代码
    
    is_block, err = conn:get(BUSINESS.."-BLOCK-"..ngx.var.remote_addr)
    
    if is_block == '1' then
    
        ngx.exit(403)
    
        goto FLAG
    
    end
    
    --查询redis中保存的ip的计数器
    
    ip_count, err = conn:get(BUSINESS.."-COUNT-"..ngx.var.remote_addr)
    
    if ip_count == ngx.null then --如果不存在,则将该IP存入redis,并将计数器设置为1、该KEY的超时时间为ip_time_out
    
        res, err = conn:set(BUSINESS.."-COUNT-"..ngx.var.remote_addr, 1)
    
        res, err = conn:expire(BUSINESS.."-COUNT-"..ngx.var.remote_addr, ip_time_out)
    
    else
    
      ip_count = ip_count + 1 --存在则将单位时间内的访问次数加1
    
        if ip_count >= ip_max_count then --如果超过单位时间限制的访问次数,则添加限制访问标识,限制时间为ip_block_time
    
            res, err = conn:set(BUSINESS.."-BLOCK-"..ngx.var.remote_addr, 1)
    
            res, err = conn:expire(BUSINESS.."-BLOCK-"..ngx.var.remote_addr, ip_block_time)
    
        else
    
            res, err = conn:set(BUSINESS.."-COUNT-"..ngx.var.remote_addr,ip_count)
    
            res, err = conn:expire(BUSINESS.."-COUNT-"..ngx.var.remote_addr, ip_time_out)
    
        end
    
    end
    
    -- 结束标记
    
    ::FLAG::
    
    local ok, err = conn:close()

    第四步,在/usr/local/src/openresty/nginx/conf/nginx.conf中的http{}里面添加以下location。

    location / {
    
                root   html;
    
                index  index.html index.htm;
    
    }
    
    location /lua {
    
                  set $business "lua";
    
                  access_by_lua_file /usr/local/src/openresty/nginx/conf/lua/access.lua;
    
                  default_type text/plain;
    
                  content_by_lua 'ngx.say("hello,lua!")';
    
    }
    
    location = /favicon.ico {
    
                       log_not_found off;
    
                       access_log off;
    
    }
    
    location /lua_redis {
    
                      default_type text/plain;
    
                      content_by_lua_file  /usr/local/src/openresty/nginx/conf/lua/redis.lua;
    
    }

    第五步,修改完nginx.conf后,重启nginx以及redis。

    命令:cd /usr/local/src/openresty/nginx/sbin

    ./nginx -s stop

    /usr/local/src/openresty/nginx/sbin/nginx -c /usr/local/src/openresty/nginx/conf/nginx.conf

    /usr/local/src/openresty/nginx/sbin/nginx -s reload

    ps -ef | grep nginx

    cd /usr/local/redis/bin

    pkill redis-server

    ./redis-server

    redis-server /usr/local/redis/etc/redis.conf

    ps -ef | grep redis

    netstat -nap | grep 6379

    第六步,访问w.w.w.w:8080/lua,并一直按F5刷新。

    连接redis命令:

    redis-cli

    127.0.0.1:6379> auth 123456

    127.0.0.1:6379> keys *

    1)"lua-COUNT-115.150.246.33"

    2)"lua-BLOCK-115.150.246.33"

    127.0.0.1:6379> get "lua-COUNT-115.150.246.33"

    "19"

    127.0.0.1:6379> get "lua-COUNT-115.150.246.33"

    (integer) 2

    127.0.0.1:6379> get "lua-COUNT-115.150.246.33"

    (integer) -2

    发现redis已经在统计访问lua页面的访问次数。

    这个key的过期时间是30秒,若30秒没有重复访问20次,则这个key就会消失。因此,正常用户一般不会触发这个封禁的脚本。

    当30秒内访问lua页面超过20次,触发了封禁脚本,页面显示“403 Forbidden”时,连接redis结果显示"lua-BLOCK-115.150.246.33",那这个key的过期时间是300秒,即300秒内这个ip无法继续访问w.w.w.w:8080/lua页面。

    这个脚本的目的:若一个IP在30秒内访问lua页面超过20次,则表明该IP访问频率太快,因此将该IP封禁5分钟。同时由于在redis中,key的超时时间设置为30秒,所以若两次访问间隔时间大于30秒,则将会重新开始计数。

    关机重启,nginx会自动启动

    第一步,修改/etc/rc.d/rc.local文件。

    在/etc/rc.d/rc.local文件最后一行下面另起一行添加下面的代码:

    /usr/local/src/openresty/nginx/sbin/nginx

    第二步,给予/etc/rc.d/rc.local权限。

    命令:cd /etc/rc.d

    chmod +x /etc/rc.d/rc.local

    第三步,服务器重启后,查看nginx是否成功自动启动。

    与“nginx启动和访问站点”中的第二步和第三步一样操作。

    命令:shutdown -r now 或 reboot 或 init 6 #立刻重启

    shutdown -r 10 #过10分钟自动重启

    关机重启,redis会自动启动

    使用redis启动/usr/local/redisfile/redis-4.0.10/utils中的脚本redis_init_script设置开机自启动。

    第一步,修改redis_init_script脚本代码。

    redis_init_script脚本代码如下:

    #!/bin/sh
    
    ...
    
    REDISPORT=6379
    
    #服务端所处位置
    
    EXEC=/usr/local/redis/bin/redis-server
    
    #客户端位置
    
    CLIEXEC=/usr/local/redis/bin/redis-cli
    
    #redis的PID文件位置,需要修改
    
    PIDFILE=/var/run/redis_6379.pid
    
    #redis的配置文件位置,需将${REDISPORT}修改为文件名
    
    CONF="/usr/local/redis/etc/redis.conf"
    
    ...

    第二步,将redis_init_script复制到/etc/rc.d/init.d目录下。

    redis_init_script复制到/etc/rc.d/init.d,复制粘贴的启动脚本会被命名为redisd(通常都以d结尾表示是后台自启动服务)。

    命令:cd /usr/local/redisfile/redis-4.0.10/utils

    cp redis_init_script /etc/rc.d/init.d/redisd

    chmod +x /etc/rc.d/init.d/redisd

    #设置为开机自启动服务器

    chkconfig redisd on

    在设置开机自启动时,发现错误:

    service redisd does not support chkconfig

    这个错误的解决办法是在启动脚本开头添加如下注释来修改运行级别,如下:

    #!/bin/sh

    # chkconfig: 2345 90 10

    再用命令:chkconfig redisd on设置即可。

    不进入redis根目录即可进行相应的操作

    打开服务:service redisd start

    关闭服务:service redisd stop

    不进入nginx根目录即可进行相应的操作

    第一步,新建nginx启动脚本代码。

    在文件夹/etc/init.d中新建名为nginx的文件,然后写入下面代码成为脚本文件。代码如下:

    #!/bin/bash
    # nginx Startup script for the Nginx HTTP Server
    # it is v.0.0.2 version.
    # chkconfig: - 85 15
    # description: Nginx is a high-performance web and proxy server.
    #              It has a lot of features, but it's not for everyone.
    # processname: nginx
    # pidfile: /var/run/nginx.pid
    # config: /usr/local/nginx/conf/nginx.conf
    nginxd=/usr/sbin/nginx
    nginx_config=/etc/nginx/nginx.conf
    nginx_pid=/var/run/nginx.pid
    RETVAL=0
    prog="nginx"
    # Source function library.
    . /etc/rc.d/init.d/functions
    # Source networking configuration.
    . /etc/sysconfig/network
    # Check that networking is up.
    [ ${NETWORKING} = "no" ] && exit 0
    [ -x $nginxd ] || exit 0
    # Start nginx daemons functions.
    start() {
    if [ -e $nginx_pid ];then
       echo "nginx already running...."
       exit 1
    fi
       echo -n $"Starting $prog: "
       daemon $nginxd -c ${nginx_config}
       RETVAL=$?
       echo
       [ $RETVAL = 0 ] && touch /var/lock/subsys/nginx
       return $RETVAL
    }
    # Stop nginx daemons functions.
    stop() {
            echo -n $"Stopping $prog: "
            killproc $nginxd
            RETVAL=$?
            echo
            [ $RETVAL = 0 ] && rm -f /var/lock/subsys/nginx /var/run/nginx.pid
    }
    # reload nginx service functions.
    reload() {
        echo -n $"Reloading $prog: "
        #kill -HUP `cat ${nginx_pid}`
        killproc $nginxd -HUP
        RETVAL=$?
        echo
    }
    # See how we were called.
    case "$1" in
    start)
            start
            ;;
    stop)
            stop
            ;;
    reload)
            reload
            ;;
    restart)
            stop
            start
            ;;
    status)
            status $prog
            RETVAL=$?
            ;;
    *)
            echo $"Usage: $prog {start|stop|restart|reload|status|help}"
            exit 1
    esac
    exit $RETVAL

    第二步,给予/etc/init.d/nginx文件权限。

    命令:chmod +x /etc/init.d/nginx

    # 设置开机自启

    命令:chkconfig --add nginx

    chkconfig nginx on

    # 检查nginx命令

    命令:service nginx

    /etc/init.d/nginx: line 20: [: =: unary operator expected

    Usage: nginx {start|stop|restart|reload|status|help}

    第三步,检查一下脚本是否有用。

    命令:/sbin/chkconfig nginx on

    sudo /sbin/chkconfig --list nginx

    如果结果显示“nginx 0:off 1:off 2:on 3:on 4:on 5:on 6:off”,则说明脚本文件有用。

    第四步,nginx启动、关闭以及重启命令。

    ps -ef | grep nginx

    systemctl start nginx

    systemctl stop nginx

    systemctl restart nginx

    service nginx start

    service nginx stop

    service nginx restart

  • 相关阅读:
    Apache Hive (三)Hive元数据信息对应MySQL数据库表
    Apache Hive (二)Hive安装
    Apache Hive (一)Hive初识
    C#使用NPOI导出excel设置单元格背景颜色
    Spark之 Spark Streaming整合kafka(并演示reduceByKeyAndWindow、updateStateByKey算子使用)
    Spark之 Spark Streaming流式处理
    Apache Flume的介绍安装及简单案例
    Kafka如何保证数据不丢失
    Ajax
    HttpComponents
  • 原文地址:https://www.cnblogs.com/interdrp/p/16645159.html
Copyright © 2020-2023  润新知