什么是CC攻击

CC(ChallengeCollapsar,挑战黑洞)攻击是DDoS攻击的一种类型,使用代理服务器向受害服务器发送大量貌似合法的请求。CC根据其工具命名,攻击者使用代理机制,利用众多广泛可用的免费代理服务器发动DDoS攻击。许多免费代理服务器支持匿名模式,这使追踪变得非常困难。
CC攻击的原理就是攻击者控制某些主机不停地发大量数据包给对方服务器造成服务器资源耗尽,一直到宕机崩溃。CC主要是用来攻击页面的,每个人都有这样的体验:当一个网页访问的人数特别多的时候,打开网页就慢了,CC就是模拟多个用户(多少线程就是多少用户)不停地进行访问那些需要大量数据操作(就是需要大量CPU时间)的页面,造成服务器资源的浪费,CPU长时间处于100%,永远都有处理不完的连接直至就网络拥塞,正常的访问被中止。

合理配置Nginx模块增强安全性

什么是漏斗算法

漏斗算法(Leaky Bucket),该算法有两种处理方式Traffic Shaping和Traffic Policing

在桶满水之后,常见的两种处理方式为:

  1. 暂时拦截住上方水的向下流动,等待桶中的一部分水漏走后,再放行上方水。

  2. 溢出的上方水直接抛弃。

将水看作网络通信中数据包的抽象,则方式1起到的效果称为Traffic Shaping,方式2起到的效果称为Traffic Policing

由此可见,Traffic Shaping的核心理念是"等待",Traffic Policing的核心理念是"丢弃"。它们是两种常见的流速控制方法

什么是令牌桶算法

令牌桶算法是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常用的一种算法。典型情况下,令牌桶算法用来控制发送到网络上的数据数目,并允许突发数据的发送。

令牌桶这种控制机制基于令牌桶中是否存在令牌来指示什么时候可以发送流量。令牌桶中的每一个令牌都代表一个字节。如果令牌桶中存在令牌,则允许发送流量;如果令牌桶中不存在令牌,则不允许发送流量。因此,如果突发门限被合理地配置并且令牌桶中有足够的令牌,那么流量就可以以峰值速率发送。令牌桶算法的基本过程如下:

1.假如用户配置的平均发送速率为10r/s,则每隔0.1秒一个令牌被加入到桶中;

2.假设桶最多可以存发b个令牌。如果令牌到达时令牌桶已经满了,那么这个令牌会被丢弃;

3.当一个n个字节的数据包到达时,就从令牌桶中删除n个令牌,并且数据包被发送到网络;

4.如果令牌桶中少于n个令牌,那么不会删除令牌,并且认为这个数据包在流量限制之外;

5.算法允许最长b个字节的突发,但从长期运行结果看,数据包的速率被限制成常量r。对于在流量限制外的数据包可以以不同的方式处理:

5.1.它们可以被丢弃;

5.2.它们可以排放在队列中以便当令牌桶中累积了足够多的令牌时再传输;

5.3.它们可以继续发送,但需要做特殊标记,网络过载的时候将这些特殊标记的包丢弃。

Nginx的limit_req源码解析

以Nginx1.21.4源码包举例,文件路径为:src\http\modules\ngx_http_limit_req_module.c 441-481行

if (rc == 0) {
    ngx_queue_remove(&lr->queue);
    ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);

    ms = (ngx_msec_int_t) (now - lr->last);

    if (ms < -60000) {
        ms = 1;

    } else if (ms < 0) {
        ms = 0;
    }

    excess = lr->excess - ctx->rate * ms / 1000 + 1000;

    if (excess < 0) {
        excess = 0;
    }

    *ep = excess;

    if ((ngx_uint_t) excess > limit->burst) {
        return NGX_BUSY;
    }

    if (account) {
        lr->excess = excess;

        if (ms) {
            lr->last = now;
        }

        return NGX_OK;
    }

    lr->count++;

    ctx->node = lr;

    return NGX_AGAIN;
}

excess初始值是0,假设现在ctx->rate是2000(即2 request/s),这次请求距离上次请求是400ms。

那么excess = 0 – 2000 * 400 / 1000 + 1000 = 200。如果limit->burst是0,那么200 > 0,会返回NGX_BUSY即HTTP 503。

假如burst是1,limit->burst即是1000,那么如果请求是每隔400ms来一个,共需5个才会填满limit->burst(每个请求将会增加200 excess),到第6个才会返回503。

修改Nginx配置

HTTP全局设置

定位置http{}模块中,增加如下两条内容:

limit_req_zone $binary_remote_addr zone=limit_req:10m rate=30r/s;
limit_conn_zone $binary_remote_addr zone=limit_conn:10m;

配置解读:

$binary_remote_addr:限制同一客户端ip地址

zone:zonename:10m:设定一个区域,名字可以任意起,应与下边继续做的配置相对应

  10m:$binary_remote_addr的长度为4字节,会话长度信息为32 bytes ,当设置 1MB的zone时,如果使用 $binary_remote_addr 的方式,该zone将可以存放约32768个会话。10m即该值乘10
  rate=30r/s:表示允许相同标识的客户端的访问频次,这里限制的是每秒30次,即每秒只处理30个请求,当然也有rate=30r/m  这种设置,即每分钟处理30个请求

Location设置

定位置server{}下的location{}模块中,增加如下内容:

limit_req zone=limit_req burst=50 nodelay;
limit_conn limit_conn 30;

配置解读:

第一行:
limit_req:为调用该功能
zone:应与HTTP全局配置的zone名相对应
burst:是指突发式请求的峰值,burst指定的请求数量,不会马上进行处理,而是按照rate指定的值,以固定的速率进行处理。
以本次设置参数举例:若每秒有100个请求,那么30个会正常处理,50个会放入请求队列,20个会直接丢弃返回HTTP 503
nodelay:如果设置,会在瞬时提供处理(burst + rate)个请求的能力,请求超过(burst + rate)的时候就会直接返回503,永远不存在请求需要等待的情况。(这里的rate的单位是:r/s)

第二行:
limit_conn:调用该功能
第二个limit_conn:HTTP全局配置中对应的zone
30:限制同一地址的并发数量

配置完成后使用 nginx -s reload 命令重载nginx配置

扩展配置

limit_req_status:用于修改在遭受拒绝时候的状态码,通常在配置了limit_req后nginx拒绝时会返回503。而444是nginx自定义的一个非标准状态码,它会立即关闭连接,连响应头也不给客户端发。可以在受到恶意攻击时使用这个状态码

fail2ban配置

增加fail2ban的过滤器

cd /etc/fail2ban/filter.d/
vim nginx_cc.conf

[Definition]

failregex = ^<HOST> .* "(GET|POST).*HTTP.*" (400|404|503) .*$
ignoreregex = .*(robots.txt|favicon.ico|jpg|png)

整体来说这是一个正则表达式,会过滤出不包含访问robots.txt、favicon(收藏图片)的所有HTTP400、404、503结果

增加fail2ban配置

参考如下:

vim /etc/fail2ban/jail.local

[nginx_cc]
enabled = true
port = http,https                                       #端口
filter = nginx_cc                                       #过滤器名称,要与刚才创建的名称对应
action = iptables[name=nginx, port="http,https", protocol=tcp]                #使用iptables禁用其对HTTP、HTTPS的访问
logpath = /var/log/nginx/access.log                              #nginx日志位置
maxretry = 10                                         #最大重试次数
findtime = 60                                         #日志文件中分析错误连接数的时间(单位秒)
bantime = 600   

应用配置

systemctl restart fail2ban

查看与删除禁用

查看:

fail2ban-client status

fail2ban-client status nginx_cc

解除禁用:

fail2ban-client set nginx_cc unbanip 1.1.1.1
上一篇 下一篇