懂王一定懂nginx系列(二):nginx封禁恶意请求,没有人比我更懂

标题纯属开玩笑哈,不要介意,更多nginx内容请访问从今天开始种树

前言

恶意请求实属烦人,几分钟都能请求几百次,对于小站而言无疑增加了大量负担,辛辛苦苦原创的内容,几分钟被这些恶意请求白嫖个干干净净,泪目。所以针对性的搜集实验了一些方法来尽可能避免这些恶意请求的访问,希望能帮助各位需要的懂懂们。

直接开整

封禁一些特有请求头

作为一个爬虫小手,对毫不限制的请求次数是深恶痛绝,而且大部分人应对基本反爬还会伪造个请求头什么的,但是下面这个ip真是把流氓精神体现得淋漓尽致。
在这里插入图片描述
它的访问次数没有截全,一秒钟大概请求了100多个网页,这个请求头Scrapy/1.7.3 (+https://scrapy.org)是不是很熟悉,没错它就是大名鼎鼎的Scrapy爬取的。

测试

首先编写了一段python代码来伪造这个请求头请求:

import requests
header = {
    "User-Agent":"Scrapy/1.7.3 (+https://scrapy.org)"
}
url = "http://www.happyhong.cn"
resp = requests.get(url,headers=header)
print(resp.status_code)
>>200  #返回的是200

伪造访问
可以看出访问是成功的,因为返回码时200

对付这种特有的请求头,可以在配置文件中添加这个试试,我测试了一下是可以的:

server{
    listen 80;
    server_name www.happyhong.cn ;
    .....
    省略
    .....
	if ($http_user_agent = 'Scrapy/1.7.3 (+https://scrapy.org)' ) 
	{ 
		return 403; 
	}
}

访问失败
返回了403,与我们配置的一样。这种方法对于小站来说是可以一试的,不过对于大站来说貌似很少用,包括我自己运维的系统也没用这种方式,下面是更直接的方式,封禁恶意IP。

封禁恶意请求IP

只要在网上一搜nginx封禁恶意IP其实就有很多文章,这里还是提一下,毕竟是个比较重要的方法。类似于防火墙,nginx也可以设置黑白名单,可以选择让哪些IP访问不了,前提是根据你的需求获得一些恶意请求IP

获取IP

需求1:获取各个IP访问次数
cat /usr/local/nginx/logs/access.log|awk '{print $1}'  |sort |uniq -c|sort -n

懂王一定懂nginx系列(二):nginx封禁恶意请求,没有人比我更懂_第1张图片

需求2:根据特定URL获取IP访问次数
cat /usr/local/nginx/logs/access.log|awk '{print $1,$7}' |grep -i -E "happyhong.cn"  |sort |uniq -c|sort -n

懂王一定懂nginx系列(二):nginx封禁恶意请求,没有人比我更懂_第2张图片

建立黑名单

因为要以定时任务方式采集,所以最好弄成shell脚本形式。

vi get_blacklist.sh

#针对需求1
cat /usr/local/nginx/logs/access.log|awk '{print $1}'  |sort |uniq -c|sort -n>>blacklist.conf
#针对需求2,注意使用>> 表示追加
cat /usr/local/nginx/logs/access.log|awk '{print $1,$7}' |grep -i -E "happyhong.cn"  |sort |uniq -c|sort -n>>blacklist.conf

定时任务

crontab -e
# 10分钟采集一次,自己定时间了
*/10 * * * * /usr/local/nginx/get_blacklist.sh

配置nginx.conf

找到配置文件

find / -name nginx.conf

可以添加在http, server, location, limit_except语句块中,这里添加在serverlocation下面:

location / {
	
	...

	include blacklist.conf;        
}

重新加载配置文件

/usr/local/nginx/sbin/nginx -t #检测一下配置文件语法是否正确
/usr/local/nginx/sbin/nginx -s reload

只允许特定请求

比如我的博客,根本就没有使用PUT、DELETE这样的方法,不过看了日志有很多请求是使用这两种方式,很明显就不是正常人类行为,直接限定死请求方式。

server{
    listen 80;
    server_name www.happyhong.cn ;
    .....
    省略
    .....
        if ($request_method !~* GET|POST) {
            return 405;
        }
 }

限制同一个ip的访问频率方法

http{
    ...

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

    limit_req_zone $binary_remote_addr zone=happy:10m rate=20r/s;
    ...
    server{
        ...
        location {
            ...
            #限制每ip每秒不超过20个请求,漏桶数burst为5
            #brust的意思就是当每秒超过20个请求时,5个以内的请求会被延迟访问,超过5个的直接返回503
            #nodelay,设置该选项,将严格使用平均速率限制请求数,超过请求频率的直接返回503
            limit_req zone=happy burst=5 nodelay;
            ...
        }
        ...
    }
    ...
}

补充说明下参数:

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

$server_name是限制同一server最大并发数;

limit_conn为限制并发连接数;

limit_rate为限制下载速度;

拓展

这个方式倒是没尝试过,有兴趣的可以试一试。直接从服务器层面禁止比nginx层面禁止要好很多,这样不会再接受到该IP的请求。

手动封IP

单个IP的命令是
iptables -I INPUT -s 10.235.65.103 -j DROP

封IP段的命令是
iptables -I INPUT -s 10.235.65.0/16 -j DROP
封整个段的命令是
iptables -I INPUT -s 112.36.1.0/8 -j DROP
解封
iptables -F
清空
iptables -D INPUT 数字
service iptables save
service iptables restart
iptables -L -n

iptables自动封IP

#!/bin/bash
num=100 #上限
list=`netstat -an |grep ^tcp.*:80|egrep -v 'LISTEN|127.0.0.1'|awk -F"[ ]+|[:]" '{print $6}'|sort|uniq -c|sort -rn|awk '{if ($1>$num){print $2}}'`
for i in $list
do
      iptables -I INPUT -s $i --dport 80 -j DROP
done

结束

本文就关于nginx恶意访问提供了一些解决思路,可能适用于你,如果有帮助请帮忙点个赞。更多内容请访问从今天开始种树,关注下面的公众号,当然不关注也无所谓。
在这里插入图片描述

你可能感兴趣的:(nginx,linux学习,nginx,linux)