解决http慢请求攻击

因网站需通过安全公司的安全测试扫描,扫描中出现了http慢请求攻击问题,经过一番查询和尝试配置后,解决方法如下:

在nginx中添加如下配置
http {

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

server {

limit_conn addr 5;
limit_req zone=one burst=5 nodelay;

send_timeout 30s;
client_max_body_size 2M;
client_body_buffer_size 16k;
client_header_buffer_size 1m;
large_client_header_buffers 4 8k;
client_body_timeout 20s;
client_header_timeout 10s;
client_body_in_single_buffer on;
client_body_in_file_only clean;
client_body_temp_path 1 2;
}

limit_req_zone 参数配置:
该参数配置分为两段,第一段放在http{}内,另一段放在server{}内

放在http{} 内

示例:
limit_req_zone $binary_remote_addr zone=one:10m rate=200r/s;

第一个参数:$binary_remote_addr 表示通过remote_addr这个标识来做限制,“binary_”的目的是缩写内存占用量,是限制同一客户端ip地址。
第二个参数:zone=mylimit:10m表示生成一个大小为10M,名字为one的内存区域,用来存储访问的频次信息。
第三个参数:rate=1r/s表示允许相同标识的客户端的访问频次,这里限制的是每秒1次,还可以有比如30r/m的。

放在server{}内

示例:
limit_req zone=one burst=5 nodelay;

第一个参数:zone=one 设置使用哪个配置区域来做限制,与上面limit_req_zone 里的name对应。
第二个参数:burst=5,重点说明一下这个配置,burst爆发的意思,这个配置的意思是设置一个大小为5的缓冲区当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内。
第三个参数:nodelay,如果设置,超过访问频次而且缓冲区也满了的时候就会直接返回503,如果没有设置,则所有请求会等待排队。

http_limit_conn_module 参数配置
参数含义:这个模块用来限制单个IP的请求数。并非所有的连接都被计数。只有在服务器处理了请求并且已经读取了整个请求头时,连接才被计数。

该参数配置分为两段,第一段放在http{}内,另一段放在server{}内

放在http{} 内

示例:
limit_conn_zone $binary_remote_addr zone=addr:10m;

第一个参数:$binary_remote_addr 表示通过remote_addr这个标识来做限制,“binary_”的目的是缩写内存占用量,是限制同一客户端ip地址
第二个参数:zone=mylimit:10m表示生成一个大小为10M,名字为addr的内存区域,用来存储访问的频次信息。

放在server{}内

示例:
limit_conn addr 5;

第一个参数:zone=addr 设置使用哪个配置区域来做限制,与上面limit_conn_zone 里的name对应
第二个参数:一次只允许每个IP地址5个连接。

send_timeout 30s;
服务端向客户端传输数据的超时时间。

client_max_body_size 2M;
此指令设置NGINX能处理的最大请求主体大小。 如果请求大于指定的大小,则NGINX发回HTTP 413(Request Entity too large)错误。 如果服务器处理大文件上传,则该指令非常重要。

client_body_buffer_size 16k;
此指令设置用于请求主体的缓冲区大小。 如果主体超过缓冲区大小,则完整主体或其一部分将写入临时文件。 如果NGINX配置为使用文件而不是内存缓冲区,则该指令会被忽略。 默认情况下,该指令为32位系统设置一个8k缓冲区,为64位系统设置一个16k缓冲区。 该指令在NGINX配置的http,server和location区块使用。

client_header_buffer_size 1m;
此指令与client_body_buffer_size类似。 它为请求头分配一个缓冲区。 如果请求头大小大于指定的缓冲区,则使用large_client_header_buffers指令分配更大的缓冲区

large_client_header_buffers 4 8k;
此指令规定了用于读取大型客户端请求头的缓冲区的最大数量和大小。 这些缓冲区仅在缺省缓冲区不足时按需分配。 当处理请求或连接转换到保持活动状态时,释放缓冲区。

client_body_timeout 20s;
指定客户端与服务端建立连接后发送 request body 的超时时间。如果客户端在指定时间内没有发送任何内容,Nginx 返回 HTTP 408(Request Timed Out)。

client_header_timeout 10s;
客户端向服务端发送一个完整的 request header 的超时时间。如果客户端在指定时间内没有发送一个完整的 request header,Nginx 返回 HTTP 408(Request Timed Out)。

client_body_in_single_buffer on;
该指令设置NGINX将完整的请求主体存储在单个缓冲区中。 默认情况下,指令值为off。 如果启用,它将优化读取$request_body变量时涉及的I/O操作。

client_body_in_file_only clean;
此指令禁用NGINX缓冲区并将请求体存储在临时文件中。 文件包含纯文本数据。 该指令在NGINX配置的http,server和location区块使用。 可选值有:
off:该值将禁用文件写入
clean:请求body将被写入文件。 该文件将在处理请求后删除。
on: 请求正文将被写入文件。 处理请求后,将不会删除该文件。

client_body_temp_path 1 2;
此指令指定存储请求正文的临时文件的位置。 除了位置之外,指令还可以指定文件是否需要最多三个级别的文件夹层次结构。 级别指定为用于生成文件夹的位数。

以上是针对http慢请求攻击的解决方法,但是使用showhttptest工具测试并未感觉能解决http慢请求的问题;如果大家有具体方法可直接留言或发邮件告知我,感谢大家。

下面是slowhttptest工具的使用方法:

slowhttptest介绍
Slowhttptest是依赖HTTP协议的慢速攻击DoS攻击工具,设计的基本原理是服务器在请求完全接收后才会进行处理,如果客户端的发送速度缓慢或者发送不完整,服务端为其保留连接资源池占用,大量此类请求并发将导致DoS。

攻击模式
slowloris:完整的http请求是以\r\n\r\n结尾,攻击时仅发送\r\n,少发送一个\r\n,服务器认为请求还未发完,就会一直等待直至超时。等待过程中占用连接数达到服务器连接数上限,服务器便无法处理其他请求。
slow http post:原理和slowloris有点类似,这次是通过声明一个较大的content-length后,body缓慢发送,导致服务器一直等待
slow read attack:向服务器发送一个正常合法的read请求,请求一个很大的文件,但认为的把TCP滑动窗口设置得很小,服务器就会以滑动窗口的大小切割文件,然后发送。文件长期滞留在内存中,消耗资源。这里有两点要注意:

tcp窗口设置要比服务器的socket缓存小,这样发送才慢。
请求的文件要比服务器的socket缓存大,使得服务器无法一下子将文件放到缓存,然后去处理其他事情,而是必须不停的将文件切割成窗口大小,再放入缓存。同时攻击端一直说自己收不到。

centos安装方式
yum install slowhttptest -y即可

也可编译安装,但我是使用kali系统的slowhttptest的,大家根据自己系统情况使用相关命令安装

参数说明
-g 在测试完成后,以时间戳为名生成一个CVS和HTML文件的统计数据
-H SlowLoris模式
-B Slow POST模式
-R Range Header模式
-X Slow Read模式
-c number of connections 测试时建立的连接数
-d HTTP proxy host:port 为所有连接指定代理
-e HTTP proxy host:port 为探测连接指定代理
-i seconds 在slowrois和Slow POST模式中,指定发送数据间的间隔。
-l seconds 测试维持时间
-n seconds 在Slow Read模式下,指定每次操作的时间间隔。
-o file name 使用-g参数时,可以使用此参数指定输出文件名
-p seconds 指定等待时间来确认DoS攻击已经成功
-r connections per second 每秒连接个数
-s bytes 声明Content-Length header的值
-t HTTP verb 在请求时使用什么操作,默认GET
-u URL 指定目标url
-v level 日志等级(详细度)
-w bytes slow read模式中指定tcp窗口范围下限
-x bytes 在slowloris and Slow POST tests模式中,指定发送的最大数据长度
-y bytes slow read模式中指定tcp窗口范围上限
-z bytes 在每次的read()中,从buffer中读取数据量

示例
slowloris模式:
slowhttptest -c 1000 -H -g -o my_header_stats -i 10 -r 200 -t GET -u https://host.example.com/index.html -x 24 -p 3

slow post模式:
$ slowhttptest -c 3000 -B -g -o my_body_stats -i 110 -r 200 -s 8192 -t FAKEVERB -u http://host.example.com/loginform.html -x 10 -p 3

slow read模式:
$ slowhttptest -c 8000 -X -r 200 -w 512 -y 1024 -n 5 -z 32 -k 3 -u https://host.example.com/resources/index.html -p 3

真实测试命令:
slowhttptest -c 8000 -X -r 200 -w 512 -y 1024 -n 5 -z 32 -k 3 -l 360 -u http://host.example.com -p 3

本文参考链接:
https://www.321dz.com/2019.html
https://www.cnblogs.com/manybirds/p/10309585.html
https://www.cnblogs.com/manybirds/p/10309585.html

如有不对的地方请大家指出并告知,感谢。

发表评论