ban特征
需要有tcpdump工具
apt-get install tcpdump
tcpdump -s0 -A -n -i any | grep -o -E '(GET|POST|HEAD).*'
tcpdump -s0 -A -n -i any | grep -o -E '(GET|POST|HEAD|Host).*'
tcpdump还有其他的命令:
tcpdump -s0 -A -n -i any | grep ^User-Agent
tcpdump -s0 -A -n -i any | grep -o -E '(X-Forwarded-For).*'
tcpdump -s0 -A -n -i any | grep -o -E '(Referer).*'
像这种某一个页面被重复请求,并且服务器CPU和流量大增,那肯定是cc了。
我们需要使用nginx来限制访问频率,以及ban掉这些特征
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
listen 80;
server_name www.mysite.com;
#访问日志
# access_log /mnt/www/mysite/logs/access.log;
#error_log /mnt/www/mysite/logs/access.log;
#静态文件直接从目录返回
location ^~ /static/ {
root /mnt/www/mysite/app;
}
#搜索页面判断来路,并且设置
location ^~ /search {
#非淘客喵来路全部禁止访问搜索
if ($http_referer !~* .*\.mysite.com){
return 403;
}
#deny all;
#搜索限制访问次数
limit_conn addr 2;
limit_req zone=one burst=3 nodelay;
proxy_pass http://127.0.0.1:8000;
break;
}
#其他页面
location / {
#限制访问次数
limit_conn addr 3;
limit_req zone=one burst=5;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
#文件不存在则转到gunicorn服务
if (!-f $request_filename) {
proxy_pass http://127.0.0.1:8000;
break;
}
}
}
BAN IP
用这个命令查看大于并发大于20的IP,里面有些是服务器的云盾或者之类的IP段,ban掉就无法访问了
#查询访问次数大于20次的ip
#-c 2000的意思是,总访问数达到2000次退出并返回结果
tcpdump -i eth1 -tnn dst port 80 -c 2000 | awk -F"." '{print $1"."$2"."$3"."$4}' | sort | uniq -c | sort -nr |awk -v str=20 '{if ($1>str){print $1,$3}}'| head -20
监听到有很多ip大量访问,最前面是访问次数。
那么我们可以写一个脚本利用iptables防火墙ban掉他们。
cd /root
vi deny.sh
写入以下脚本
#!/bin/bash
#Author:ZhangGe&Corek
#Desc:Auto Deny Black_IP Script.
#Date:2016-11-16
#从第一个参数取得限制阈值,如果未设置最高并发,将设置为30
if [[ -z $1 ]];then
num=30
else
num=$1
fi
#进入到脚本所在目录
cd $(cd $(dirname $BASH_SOURCE) && pwd)
#取得当前请求大于阈值$num的IP列表
iplist=`tcpdump -i eth1 -tnn dst port 80 -c 5000 | awk -F"." '{print $1"."$2"."$3"."$4}' | sort | uniq -c | sort -nr |awk -v str=$num '{if ($1>str){print $3}}'`
#循环IP列表进行筛选和处理
if [[ ! -z $iplist ]];
then
for black_ip in $iplist
do
#取得IP所在段
ip_section=`echo $black_ip | awk -F"." '{print $1"."$2"."$3}'`
#先检查白名单中是否存在匹配的IP段(为了支持整段IP为白名单)
grep -q $ip_section ./white_ip.txt
if [[ $? -eq 0 ]];then
#若发现black_ip和白名单的一个段匹配,则写入到待验证列表,并暂时放过
echo $black_ip >>./recheck_ip.txt
else
#若不再白名单当中,则直接将black_ip加入到防火墙的DROP规则当中,并记录
#封单IP
#iptables -nL | grep $black_ip || iptables -I INPUT -s $black_ip -j DROP
#echo $black_ip >>./black_ip.txt
#直接封IP段
iptables -nL | grep $ip_section.0/24 || iptables -I INPUT -s $ip_section.0/24 -j DROP
echo $ip_section.0/24 >>./black_ip.txt
fi
done
fi
保存后。
我们建立一个白名单txt,把服务器IP和爬虫IP以及阿里云云盾的IP段写进去,要是这些IP被ban掉,web就无法访问了
比如
vi white_ip.txt
#写入
#服务器的IP
106.14.30.*
#云盾IP
140.205.16.*
保存。
运行,后面的参数20表示这段结果中访问数大于20的段全部ban掉
nohup ./deny.sh 20
附上iptables的操作
#查看ban掉的IP
iptables -nL
#清空iptables防火墙的记录
iptables -F
#将某个ip单独ban
iptables -I INPUT -s 115.219.59.126 -j DROP
#将某个IP取消屏蔽
iptables -D INPUT -s 119.182.160.132 -j DROP
#屏蔽ip段
iptables -I INPUT -s 115.219.59.0/24 -j DROP
2017年8月1日更新
其实最有用的还是屏蔽来路,现在的很多CC都是用脚本嵌套刷,来路都是各种乱七八糟的网页。
编辑站点nginx配置文件
cd /etc/nginx/sites-available
vi mysite
内容如下
server {
listen 80;
server_name www.mysite.com;
#修改最大上传为10M,默认为2M,超出大小出现413 Request Entity Too Large错误
client_max_body_size 10M;
#搜索页面防CC
location ^~ /search {
set $deny 1;
if ($http_referer ~* .*\.mysite.com){
set $deny 0;
}
if ($http_referer ~* .*\.baidu.com){
set $deny 0;
}
if ($http_referer ~* .*\.sogou.com){
set $deny 0;
}
if ($http_referer = ''){
set $deny 0;
}
#如果来路验证不通过,则拒绝
if ($deny = 1){
rewrite .+ http://www.163.com redirect;
#rewrite ^/(.*) http://www.163.com redirect;
#return 403;
}
#将访客IP加入headers中,否则获取到的将是127.0.0.1
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
#如果请求的文件不存在,则将路由转发到gunicorn的8000端口
if (!-f $request_filename) {
proxy_pass http://127.0.0.1:8000;
break;
}
}
#默认请求,nginx反向代理(动态页面转发至gunicorn)
location / {
#将访客IP加入headers中,否则获取到的将是127.0.0.1
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
#如果请求的文件不存在,则将路由转发到gunicorn的8000端口
if (!-f $request_filename) {
proxy_pass http://127.0.0.1:8000;
break;
}
}
#静态文件请求转发给目录
location ^~ /static/ {
root /var/www/mysite/app;
}
}
立竿见影,加上这个nginx配置,然后重启nginx。
马上带宽就降了。