nginx | ip限制和限流

4,774 阅读1分钟

一、屏蔽IP

1、从日志查找要屏蔽的IP

logs目录下:awk '{print $1}' access.log |sort |uniq -c|sort -n

可以看到IP的访问次数

2、在conf目录下,添加IP黑名单
  • 新建文件:blockip.conf 写入:deny 127.0.0.1;

  • nginx_conf中引入:

    location /tb/ {
        alias   html/tb/;
        index  index.html;
        try_files $uri $uri/ /tb/index.html;
        include blockip.conf; #黑名单,可以在http, server, location, limit_except语句块
    }
    
3、屏蔽与开放IP

被屏蔽的IP,再次访问时,会显示403

deny 127.0.0.1; #屏蔽单个IP
allow 127.0.0.1; #允许单个IP
deny all; #屏蔽所有IP
allow all; #运行所有IP
4、IP监控脚本

shell脚本分析日志,自动屏蔽恶意IP;摘自网上,可用性未测;

需要分割日志。因为是单位时间内访问过高才仍为是攻击者,而日志是全部的。

nginx可以配置日志切割

#! /bin/bash
log_nginx="/var/log/nginx"	# nginx日志文件
blockfile="/usr/local/nginx/conf/website" #ip黑名单那
 
#取出日志中符合条件的ip写入ip.txt,并过滤掉重复的
grep "app/user/getCode" $log_nginx/access.log | awk '{print $1}' | sort -rn |uniq -c |awk '{print $2}' > /home/shell/ip.txt
 
for ip in `cat /home/shell/ip.txt`
do
    result=$(grep $ip $blockfile/blockip.conf)
 
#判断ip是否已经被屏蔽
    if [ -z "$result" ]; then
 
#分析ip请求的次数
    count=$(grep $ip $log_nginx/access.log|grep "app/user/getCode"|wc -l)
 
#请求次数大于等于20次就进行屏蔽
        if [ $count -ge 20 ]; then
        echo "deny $ip;" >> $blockfile/blockip.conf
        fi
    fi
done
 
#重启nginx
/usr/local/nginx/sbin/nginx -s reload

二、访问限制模块

1、limit_req_zone:限制每个IP的请求数
http {
    #定义一个名为ttlsa_com的请求限制块
    
    #块的容量为10m,使用$binary_remote_addr变量, 可以将每条状态记录的大小减少到64个字节,这样1M的内存可以保存大约1万6千个64字节的记录。
    #如果限制域的存储空间耗尽了,对于后续所有请求,服务器都会返回 503
    
    #rete是请求速度,每秒/分钟处理请求数;30r/m,表示2秒处理一个请求。
    #超过请求速度的请求将被延迟,直到被延迟的请求超过了定义的阈值,这时请求将被终止并返回503,阈值默认是0
	
    limit_req_zone $binary_remote_addr zone=ttlsa_com:10m rate=1r/s;
	limit_req_zone $binary_remote_addr $uri zone=two:3m rate=1r/s; #$uri表示同个ip访问同个uri,才会进入限制
    
	server {
		location  ^~ /download/ {  
            #允许超过频率限制的请求数不多于5个。
            #burst=5,相当于设置一个大小为5的缓冲区,超过了访问频次的请求会先放到这个缓冲区中等待。
            #但是这个缓冲区大小只有5,超过缓冲区的请求会直接503
            
            #nodelay是无延迟的意思,表示请求超过频次时,可提供处理(burst + rate)个请求的能力
            #请求超过(burst + rate)的时候就会直接返回503,永远不存在请求需要等待的情况。
            #注意:不存在单独使用nodelay的情况。nodelay是和burst配合使用的
			limit_req zone=ttlsa_com burst=5 nodelay; 
			alias /data/www.ttlsa.com/download/;
        }
	}
}

limit_req_zone:http;定义一个会话区,记录会话状态信息。以$binary_remote_addr为key;也就是说一个IP就是一个会话;

limit_req_conn:;指定一个会话的最大请求数;

limit_req:http, server, location

limit_req_status:http, server, location,设置拒绝请求的响应状态码,默认是503

2、limit_conn_zone:限制每个IP的并发连接数
http{
    # $binary_remote_addr是限制同一客户端ip地址;
    limit_conn_zone $binary_remote_addr zone=limit:10m;
    limit_conn_zone $server_name zone=perserver:10m;
    limit_conn_log_level info;

    server {
        location  ^~ /download/ {  
            limit_conn perserver 1000; #表示该服务提供的总连接数最大不超过1000,超过的请求会被拒绝
            limit_conn limit 4; #表示每个IP的最大并发连接数为4
            limit_rate 200k; #这里是对连接的限速,不是对IP的限速
            alias /data/www.ttlsa.com/download/;
        }
    }
}

zone:块的意思

limit_conn_zone:http;定义一个会话区,记录会话状态信息。以$binary_remote_addr为key;也就是说一个IP就是一个会话;

limit_conn:http, server, location

limit_rate:http, server, location, if in location;每个连接的速率限制;

limit_conn_status:http, server, location;指定超过限制事返回的状态码,默认是503;

3、白名单

如果 Nginx 前面有 lvs 或者 haproxy 之类的负载均衡或者反向代理,nginx 获取的都是来自负载均衡的连接或请求,这时不应该限制负载均衡的连接和请求,就需要 geo 和 map 模块设置白名单了;

geo $whiteiplist  {
    default 1;
    10.11.15.1610;
}
map $whiteiplist $limit {
    1$binary_remote_addr;
    0"";
}

limit_req_zone $limit zone=one:10m rate=10r/s;
limit_conn_zone $limit zone=addr:10m;