首页 存档 技术 查看内容

自建CDN实战经验合集之基础waf防护系统的实现

2018-3-30 13:00 |来自: 互联网 487 0

摘要: 1 概述 WEB安全中除典型攻击外(如SQL注入、文件上传、敏感文件泄漏等),近些年来CC攻击也逐渐走向”正轨”,占有相当比例。结合业务场景,我们也使用ngx_lua实现了CDN waf防护系统,本文主要分享传统Nginx防CC的一 ...



1 概述



WEB安全中除典型攻击外(如SQL注入、文件上传、敏感文件泄漏等),近些年来CC攻击也逐渐走向”正轨”,占有相当比例。结合业务场景,我们也使用ngx_lua实现了CDN waf防护系统,本文主要分享传统Nginx防CC的一些经验,以及自建CDN waf防护系统中基础模块的实现。



2Nginx CC防护经验



早期线上做CC防护,通常是限制IP访问、同一IP请求数、并发数来实现,主要模块有:


通常结合Core模块limite_rate做限速、map模块做变量映射、Geo模块做白名单策略等等。


具体Nginx模块的详细简介以及安装过程,则不再赘述,有兴趣的看客可以直接查看官方文档。

http://nginx.org/en/docs/


2.1 IP访问限制


针对IP做访问限制,一般可使用allow/deny指令,即http_access_module模块,默认自带(除非编译显式指明--without-http_access_module)。被deny拦截的请求返回403。


参考实例:

location /health_status {
 allow 127.0.0.1;    #放行IP
 deny 192.168.10.25/32;  #拒绝指定IP
 allow 192.168.10.0/24;  #放行网段
 #deny 2001:0db8::/32;  #支持ipv6
 #deny unix:/tmp/test.sock; #1.5.3 版本支持UNIX域    
 deny all;        #默认规则

经验:

(1) 规则匹配自上而下、精细规则要靠前写、不要漏写默认规则;


(2) 通常将allow、deny条目写成规则文件如blockip.conf ,通过 include blockip.conf引入, 可在http、server、location及limit_except配置段中引入;


(3) 更改规则需重载nginx生效,由于无法预知攻击者IP,并不适合动态防CC。适合针对特定站点/路径 做访问保护,如CDN健康状态页只允许本机、中央机访问。


2.2请求数限制


ngx_http_limit_req_module模块可通过预先定义的键值来限制请求处理的频率,默认自带(除非编译显式指明--without-http_limit_req_module)。如果定义客户端IP为键值,则可以针对同一IP单位时间内的请求数做限制(无论这些请求是否处理),是”请求数量层面限制”。


限流原理是” leaky bucket”(漏桶算法):服务器以恒定的速率处理请求,超出处理速率的请求放在burst队列中延迟处理,严重超出的请求(大于恒定处理速率 burst队列上限)则直接丢弃。


参考示例:针对动态页面做请求限制

http {
 ...
 limit_req_zone $binary_remote_addr zone=dynamic_req_limit:20m rate=20r/s; 
 server {
  ...
  location ~* .*\.(aspx|jsp|php)($|\?) {
   ...
   limit_req zone=dynamic_req_limit burst=100;
   limit_req_log_level error;
   limit_req_status 403;
  }
 }
}


配置说明:

(1) 定义$binary_remote_addr为KEY,即客户端IP作为"请求标识"(用于计数);


(2) zone=req_limit:20m 生成大小20m、名为dynamic_req_limit的内存区域, 用于存储访问频次信息;


(3) rate=20r/s 表示相同"请求标识"(即IP相同)的请求、每秒处理20个;


(4) zone=dynamic_req_limit burst=100在location配置段下,是指针对动态请求(aspx|jsp|php)限制同一IP每秒最多处理20次请求,burst为缓冲队列,超出20小于120的请求可进入队列延迟处理,超出120以上的请求会被丢弃并默认返回503;


(5) limit_req_log_level error 用于记录日志0.8.18 版本支持;


(6) limit_req_status 403 被拒绝的请求(即超出rate burst总上限)默认返回503,在1.3.15 版本后支持自定义状态码,这里修改为403。


经验:

(1) 1.7.6 版本前,KEY只能是单个变量;更高版本KEY支持多个变量、文本等组合,CDN场景下通常是将”IP 访问URI”作为唯一标识,来做策略限制,如:

limit_req_zone $binary_remote_addr$request_uri zone=req_limit:20m rate=1r/s;


(2) limit_req 指令可配置nodelay参数,若未设置nodelay,则当前时刻处于burst队列的请求需到下一秒执行;设置nodelay会强制将当前burst队列请求也同一时刻处理(增大瞬间吞吐),即此刻请求要么被处理、要么被丢弃,burst队列为空;

limit_req zone=dynamic_req_limit burst=100 nodelay;


(3) $binary_remote_addr为固定4字节,相比$remote_addr(7~15字节)节约内存;状态位(即频次信息)32位平台占用64字节,64位平台占用128字节,因此64位平台上,1M zone可保存约8000个IP状态。具体zone大小可根据key值大小、rate限制频率及Web服务QPS来推算;


(4) $binary_remote_addr仅代表TCP连接的对端IP地址,在前端有代理转发、负载均衡器、CDN场景等情况下,该值不能作为req_limit key(并非用户真实IP),比如通过HTTP header提取用户真实IP,参考如下

map $http_x_forwarded_for $ClientRealIp {
 ""  $remote_addr;
 ~^(?P
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部