基于Nginx实现限制某IP短时间访问次数


Posted in Servers onMarch 31, 2021

如何设置能限制某个IP某一时间段的访问次数是一个让人头疼的问题,特别面对恶意的ddos攻击的时候。其中CC攻击(Challenge Collapsar)是DDOS(分布式拒绝服务)的一种,也是一种常见的网站攻击方法,攻击者通过代理服务器或者肉鸡向向受害主机不停地发大量数据包,造成对方服务器资源耗尽,一直到宕机崩溃。

cc攻击一般就是使用有限的ip数对服务器频繁发送数据来达到攻击的目的,nginx可以通过HttpLimitReqModul和HttpLimitZoneModule配置来限制ip在同一时间段的访问次数来防cc攻击。

HttpLimitReqModul用来限制连单位时间内连接数的模块,使用limit_req_zone和limit_req指令配合使用来达到限制。一旦并发连接超过指定数量,就会返回503错误。

HttpLimitConnModul用来限制单个ip的并发连接数,使用limit_zone和limit_conn指令

这两个模块的区别HttpLimitReqModul是对一段时间内的连接数限制,HttpLimitConnModul是对同一时刻的连接数限制

HttpLimitReqModul 限制某一段时间内同一ip访问数实例

http{
  ...
  #定义一个名为allips的limit_req_zone用来存储session,大小是10M内存,
  #以$binary_remote_addr 为key,限制平均每秒的请求为20个,
  #1M能存储16000个状态,rete的值必须为整数,
  #如果限制两秒钟一个请求,可以设置成30r/m
  limit_req_zone $binary_remote_addr zone=allips:10m rate=20r/s;
  ...
  server{
    ...
    location {
      ...

      #限制每ip每秒不超过20个请求,漏桶数burst为5
      #brust的意思就是,如果第1秒、2,3,4秒请求为19个,
      #第5秒的请求为25个是被允许的。
      #但是如果你第1秒就25个请求,第2秒超过20的请求返回503错误。
      #nodelay,如果不设置该选项,严格使用平均速率限制请求数,
      #第1秒25个请求时,5个请求放到第2秒执行,
      #设置nodelay,25个请求将在第1秒执行。

      limit_req zone=allips burst=5 nodelay;
      ...
    }
    ...
  }
  ...
}

HttpLimitZoneModule 限制并发连接数实例

limit_zone只能定义在http作用域,limit_conn可以定义在http server location作用域

http{
  ...
  #定义一个名为one的limit_zone,大小10M内存来存储session,
  #以$binary_remote_addr 为key
  #nginx 1.18以后用limit_conn_zone替换了limit_conn
  #且只能放在http作用域
  limit_conn_zone  one $binary_remote_addr 10m; 
  ...
  server{
    ...
    location {
      ...
      limit_conn one 20;     #连接数限制
      #带宽限制,对单个连接限数,如果一个ip两个连接,就是500x2k
      limit_rate 500k;      
      ...
    }
    ...
  }
  ...
}

nginx白名单设置

以上配置会对所有的ip都进行限制,有些时候我们不希望对搜索引擎的蜘蛛或者自己测试ip进行限制,
对于特定的白名单ip我们可以借助geo指令实现。

1.

http{
   geo $limited{
    default 1;
    #google
    64.233.160.0/19 0;
    65.52.0.0/14 0;
    66.102.0.0/20 0;
    66.249.64.0/19 0;
    72.14.192.0/18 0;
    74.125.0.0/16 0;
    209.85.128.0/17 0;
    216.239.32.0/19 0;
    #M$
    64.4.0.0/18 0;
    157.60.0.0/16 0;
    157.54.0.0/15 0;
    157.56.0.0/14 0;
    207.46.0.0/16 0;
    207.68.192.0/20 0;
    207.68.128.0/18 0;
    #yahoo
    8.12.144.0/24 0;
    66.196.64.0/18 0;
    66.228.160.0/19 0;
    67.195.0.0/16 0;
    74.6.0.0/16 0;
    68.142.192.0/18 0;
    72.30.0.0/16 0;
    209.191.64.0/18 0;
    #My IPs
    127.0.0.1/32 0;
    123.456.0.0/28 0; #example for your server CIDR
  }

geo指令定义了一个白名单$limited变量,默认值为1,如果客户端ip在上面的范围内,$limited的值为0

2.使用map指令映射搜索引擎客户端的ip为空串,如果不是搜索引擎就显示本身真是的ip,这样搜索引擎ip就不能存到limit_req_zone内存session中,所以不会限制搜索引擎的ip访问

map $limited $limit {
1 $binary_remote_addr;
0 "";
}

3.设置limit_req_zone和limit_req

limit_req_zone $limit zone=foo:1m rate=10r/m;

limit_req zone=foo burst=5;

最后我们使用ab压php-fpm的方式,对上面的方法效果实际测试下

例1:限制只允许一分钟内只允许一个ip访问60次配置,也就是平均每秒1次

首先我们准备一个php脚本放在根目录下$document_root

test.php

<?
for( $i=0; $i < 1000; $i++)
echo 'Hello World';
?>

nginx配置增加limit_req_zone 和 limit_req

http{
  ...
  limit_req_zone $binary_remote_addr zone=allips:10m rate=60r/m;
  ...
  server{
    ...
    location {
      ...
      limit_req zone=allips;
      ...
    }
    ...
  }
  ...
}
# ab -n 5 -c 1 http://blog.rekfan.com/test.php
127.0.0.1- - [22/Dec/2012:06:27:06 +0000] "GET /test.php HTTP/1.0" 200 11000 "-" "Rekfan_Server/1.2.6"
127.0.0.1 - - [22/Dec/2012:06:27:06 +0000] "GET /test.php HTTP/1.0" 503 537 "-" "Rekfan_Server/1.2.6"
127.0.0.1 - - [22/Dec/2012:06:27:07 +0000] "GET /test.php HTTP/1.0" 503 537 "-" "Rekfan_Server/1.2.6"
127.0.0.1 - - [22/Dec/2012:06:27:07 +0000] "GET /test.php HTTP/1.0" 503 537 "-" "Rekfan_Server/1.2.6"
127.0.0.1 - - [22/Dec/2012:06:27:07 +0000] "GET /test.php HTTP/1.0" 503 537 "-" "Rekfan_Server/1.2.6"

未设置brust和nodelay可以看到该配置只允许每秒访问1次,超出的请求返回503错误

http{
  ...
  limit_req_zone $binary_remote_addr zone=allips:10m rate=60r/m;
  ...
  server{
    ...
    location {
      ...
      limit_req zone=allips burst=1 nodelay;
      ...
    }
    ...
  }
  ...
}

# ab -n 5 -c 1 http://blog.rekfan.com/test.php
127.0.0.1- - [22/Dec/2012:07:01:00 +0000] "GET /test.php HTTP/1.0" 200 11000 "-" "Rekfan_Server/1.2.6"
127.0.0.1 - - [22/Dec/2012:07:01:00 +0000] "GET /test.php HTTP/1.0" 200 11000 "-" "Rekfan_Server/1.2.6"
127.0.0.1 - - [22/Dec/2012:07:01:01 +0000] "GET /test.php HTTP/1.0" 503 537 "-" "Rekfan_Server/1.2.6"
127.0.0.1 - - [22/Dec/2012:07:01:01 +0000] "GET /test.php HTTP/1.0" 503 537 "-" "Rekfan_Server/1.2.6"
127.0.0.1 - - [22/Dec/2012:07:01:01 +0000] "GET /test.php HTTP/1.0" 503 537 "-" "Rekfan_Server/1.2.6"

设置brust=1和nodelay后允许第1秒处理两个请求。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Servers 相关文章推荐
Centos7.7 64位利用本地完整安装包安装lnmp/lamp套件教程
Mar 09 Servers
Nginx服务器添加Systemd自定义服务过程解析
Mar 31 Servers
nginx proxy_cache 缓存配置详解
Mar 31 Servers
Nginx工作原理和优化总结。
Apr 02 Servers
apache基于端口创建虚拟主机的示例
Apr 24 Servers
制作能在nginx和IIS中使用的ssl证书
Jun 21 Servers
Nginx图片服务器配置之后图片访问404的问题解决
Mar 21 Servers
配置Kubernetes外网访问集群
Mar 31 Servers
为Centos安装指定版本的Docker
Apr 01 Servers
Mac电脑OS系统下安装Nginx的详细教程
Apr 14 Servers
Apache POI操作批量导入MySQL数据库
Jun 21 Servers
VMware虚拟机安装 Windows Server 2022的详细图文教程
Sep 23 Servers
Nginx tp3.2.3 404问题解决方案
Mar 31 #Servers
解决Nginx 配置 proxy_pass 后 返回404问题
nginx配置ssl实现https的方法示例
Mar 31 #Servers
Nginx解决前端访问资源跨域问题的方法详解
Mar 31 #Servers
nginx实现发布静态资源的方法
Nginx中break与last的区别详析
nginx网站服务如何配置防盗链(推荐)
You might like
php学习笔记 php中面向对象三大特性之一[封装性]的应用
2011/06/13 PHP
PHP实现通过中文字符比率来判断垃圾评论的方法
2014/10/20 PHP
PHP输入流php://input实例讲解
2015/12/22 PHP
PHP识别二维码的方法(php-zbarcode安装与使用)
2016/07/07 PHP
PHP制作登录异常ip检测功能的实例代码
2016/11/16 PHP
详解thinkphp中的volist标签
2018/01/15 PHP
js调用flash的效果代码
2008/04/26 Javascript
基于jQuery的判断iPad、iPhone、Android是横屏还是竖屏的代码
2014/05/11 Javascript
jQuery实现的小图列表,大图展示效果幻灯片示例
2016/10/25 Javascript
bootstrap jquery dataTable 异步ajax刷新表格数据的实现方法
2017/02/10 Javascript
微信小程序商城项目之侧栏分类效果(1)
2017/04/17 Javascript
JavaScript判断输入是否为数字类型的方法总结
2017/09/28 Javascript
如何去除vue项目中的#及其ie9兼容性
2018/01/11 Javascript
微信小程序踩坑记录之解决tabBar.list[3].selectedIconPath大小超过40kb
2018/07/04 Javascript
快速解决vue-cli在ie9+中无效的问题
2018/09/04 Javascript
vue中$nextTick的用法讲解
2019/01/17 Javascript
node.js Promise对象的使用方法实例分析
2019/12/26 Javascript
深入理解javascript中的this
2021/02/08 Javascript
python自定义异常实例详解
2017/07/11 Python
在Python中实现替换字符串中的子串的示例
2018/10/31 Python
python绘制多个子图的实例
2019/07/07 Python
Python的Lambda函数用法详解
2019/09/03 Python
美国最大的无人机经销商:DroneNerds
2018/03/20 全球购物
为什么要使用servlet
2016/01/17 面试题
经济系大学生求职信
2013/10/01 职场文书
电气工程及自动化专业自荐书范文
2013/12/18 职场文书
初中美术教学反思
2014/01/29 职场文书
房地产营销策划方案
2014/02/08 职场文书
乡镇八一建军节活动方案
2014/08/24 职场文书
六一儿童节开幕词
2015/01/29 职场文书
大学毕业生自我评价
2015/03/02 职场文书
残联2016年全国助残日活动总结
2016/04/01 职场文书
大学生暑期社会实践的个人总结!
2019/07/17 职场文书
导游词之河姆渡遗址博物馆
2019/10/10 职场文书
Python基础之tkinter图形化界面学习
2021/04/29 Python
MongoDB 常用的crud操作语句
2021/06/20 MongoDB