- A+
闲来无事,登陆服务器,发现有个IP不断的猜测路径、试图往服务器上传文件(木马)。于是查看了之前的日志,无奈鄙站被攻击者盯上了,不断的有不同的IP试图上传木马。看来坏人还是有的。由于不想让鄙站沦为肉鸡,所以就想写个简单的脚本,来阻止攻击者的IP访问。
攻击者:
1 2 3 4 5 6 7 8 |
195.154.216.165 - - [28/Nov/2015:23:10:40 +0800] "POST /wp-content/themes/twentyten/404.php HTTP/1.1" 404 27 "http://www.z-dig.com/11m.php" "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)" "-" 195.154.216.165 - - [28/Nov/2015:23:10:40 +0800] "POST /wp-content/themes/twentythirteen/404.php HTTP/1.1" 404 27 "http://www.z-dig.com/11m.php" "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)" "-" 195.154.216.165 - - [28/Nov/2015:23:10:40 +0800] "POST /wp-content/themes/twentytwelve/404.php HTTP/1.1" 404 27 "http://www.z-dig.com/11m.php" "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)" "-" 195.154.216.165 - - [28/Nov/2015:23:10:40 +0800] "POST /wp-content/uploads/phptest.php HTTP/1.1" 404 27 "http://www.z-dig.com/11m.php" "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)" "-" 195.154.216.165 - - [28/Nov/2015:23:10:41 +0800] "POST /xyr/confings.asp HTTP/1.1" 404 1569 "http://www.z-dig.com/11m.php" "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)" "-" 195.154.216.165 - - [28/Nov/2015:23:10:41 +0800] "POST /xz.asp;.jpg HTTP/1.1" 404 564 "http://www.z-dig.com/11m.php" "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)" "-" 195.154.216.165 - - [28/Nov/2015:23:10:41 +0800] "POST /yanyu/?q={${eval%28$_POST[u]%29}} HTTP/1.1" 404 1569 "http://www.z-dig.com/11m.php" "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)" "-" 195.154.216.165 - - [28/Nov/2015:23:10:42 +0800] "POST /ztxxw/Images/images.asp HTTP/1.1" 404 1569 "http://www.z-dig.com/11m.php" "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)" "-" |
1 2 3 |
[root@z-dig www]# grep '195.154.216.165' 2015-11-28.access.log|wc -l 289 [root@z-dig www]# |
1 2 3 4 5 6 7 8 9 10 11 |
[root@z-dig www]# curl ipinfo.io/195.154.216.165;echo'' { "ip": "195.154.216.165", "hostname": "fr.07.gs", "city": "", "region": "", "country": "FR", "loc": "48.8600,2.3500", "org": "AS12876 ONLINE S.A.S." } [root@z-dig www]# |
法国的哥们竟然试了180多次!辛苦了。
用 shell 和定时任务来实现吧。>_<
网站跑在 Nginx 上,所以可以使用 Nginx 的 Deny 来拒绝攻击者的IP访问。
那么思路就出来了,定期(五分钟或十分钟)获取攻击者的IP,将IP放入到黑名单(Nginx 配置文件),并 reload 使其生效。
由于前期规划的比较好,网站的访问日志放在了一个指定的目录,Nginx 的错误日志也放在了一个指定的目录。网站的访问日志每日进行切割。Nginx 的错误日志没有进行切割。
下面就是我的思路和操作步骤:
通过 Nginx 的错误日志(为什么不使用访问日志)来获取攻击者的IP。之前没有对 Nginx 的错误日志进行定时切割,为了方便统计攻击者的IP所以,编写脚本并加入定时任务,使错误日志每小时切割一次,并且每小时对黑名单文件进行清空。
错误日志切割、清空黑名单脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
[root@z-dig scripts]# cat rotate-nginx-error-logs.sh #!/bin/bash # Rotate nginx error logs and clean block ip 's configure file # Nginx pid file : /application/nginx/logs/nginx.pid # Nginx error logs directory : /data/logs/nginx # Block Ip 's configure file : /application/nginx/conf/website/blockip.conf # Default log name : error.log # Author : Mr.Zhou # E-mail : zhou@z-dig.com NGX_PID=/application/nginx/logs/nginx.pid NGINX_CMD=/application/nginx/sbin/nginx LOGS_DIR=/data/logs/nginx LOG_NAME=error.log BLOCK_IP_FILE=/application/nginx/conf/website/blockip.conf cd $LOGS_DIR && /usr/bin/rename $LOG_NAME $(/bin/date +%F-%H -d "last hour").$LOG_NAME $LOG_NAME && /bin/kill -USR1 $(cat $NGX_PID) >$BLOCK_IP_FILE && $($NGINX_CMD -s reload) [root@z-dig scripts]# |
获取攻击者IP脚本:
该脚本从 Nginx 的错误日志中统计出超过20次试图猜测路径或上传文件的IP,并将这些IP加入到 Nginx 的配置文件。若有新增加的IP则 reload Nginx 使配置文件生效,若没有新增IP则不进行reload。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[root@z-dig scripts]# cat block-ip.sh #!/bin/bash # Author : Mr.Zhou # Email : zhou@z-dig.com # Website : http://www.z-dig.com # block ip ERR_LOG=/data/logs/nginx/error.log BLOCK_IP_FILE=/application/nginx/conf/website/blockip.conf BLOCKED_IP=/dev/shm/blocked-ip.txt BLOCK_IP=/dev/shm/block-ip.txt NGINX_CMD=/application/nginx/sbin/nginx /bin/cp $BLOCK_IP_FILE $BLOCKED_IP && /bin/sed -nr 's#.*[^0-9](([0-9]+\.){3}[0-9]+).*#\1#p' $ERR_LOG |/bin/awk '{IP[$1]++}END{for (i in IP) print IP[i],i}'|/bin/awk '{if($1>20)print "deny "$2";"}' >$BLOCK_IP && /bin/grep -v -f $BLOCK_IP_FILE $BLOCK_IP >>$BLOCK_IP_FILE && $($NGINX_CMD -s reload) [root@z-dig scripts]# |
将拒绝指定IP访问的配置文件(黑名单)单独存放,并在 nginx 主配置文件中 include 进去。
1 2 3 |
[root@z-dig conf]# grep blockip.conf nginx.conf include website/blockip.conf; [root@z-dig conf]# |
blockip.conf 文件格式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[root@z-dig website]# cat blockip.conf deny 195.154.211.220; deny 195.154.188.28; deny 195.154.188.186; deny 180.97.106.161; deny 180.97.106.162; deny 180.97.106.36; deny 195.154.180.69; deny 195.154.211.26; deny 221.229.166.247; deny 180.97.106.37; deny 195.154.216.164; deny 195.154.216.165; [root@z-dig website]# |
将脚本放入定时任务执行:
每小时对 Nginx 的错误日志进行切割并且清空一次被拒绝访问IP的配置文件,若不清空的话,此IP将终生不能访问,若它再次攻击则会再次进入黑名单,>_<。 清空命令放在了切割脚本的尾部。
可以自己决定统计频率,根据指定的频率执行脚本,获取攻击者的IP,若此IP已经在黑名单中,则会忽略掉(由于错误日志一小时切割一次,所以在一小时内会出现重复的IP)。然后把剩下的新攻击者的IP追加到黑名单。并 reload Nginx 。若没有新增的攻击者IP则什么都不做。
1 2 3 4 5 6 7 8 |
[root@z-dig ~]# crontab -l # rotate nginx log everyday 00 00 * * * /bin/bash /application/scripts/rotate-nginx-logs.sh &>/dev/null # rotate nginx error log every hour and clean the block ip file 00 */1 * * * /bin/bash /application/scripts/rotate-nginx-error-logs.sh &>/dev/null # check hacker's ip every ten minutes */10 * * * * /bin/bash /application/scripts/block-ip.sh &>/dev/null [root@z-dig ~]# |
以下是脚本运行一段时间的攻击者IP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[root@z-dig ~]# cat /application/nginx/conf/website/blockip.conf deny 195.154.211.220; deny 195.154.188.28; deny 195.154.188.186; deny 180.97.106.161; deny 180.97.106.162; deny 180.97.106.36; deny 195.154.180.69; deny 195.154.211.26; deny 221.229.166.247; deny 180.97.106.37; deny 195.154.216.164; deny 195.154.216.165; [root@z-dig ~]# |
过段时间,再列出一份黑名单IP,看是否有变化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
[root@z-dig ~]# cat /application/nginx/conf/website/blockip.conf deny 195.154.188.224; [root@z-dig ~]# curl ipinfo.io/195.154.188.224;echo '' { "ip": "195.154.188.224", "hostname": "195-154-188-224.rev.poneytelecom.eu", "city": "", "region": "", "country": "FR", "loc": "48.8600,2.3500", "org": "AS12876 ONLINE S.A.S." } [root@z-dig ~]# grep '195.154.188.224' /data/logs/nginx/error.log |wc -l 102 [root@z-dig ~]# grep '195.154.188.224' /data/logs/nginx/error.log |grep -v 'access forbidden' |wc -l 24 [root@z-dig ~]# [root@z-dig ~]# tail -n 1 /data/logs/nginx/error.log 2015/11/30 10:47:53 [error] 30754#0: *37828 access forbidden by rule, client: 195.154.188.224, server: www.z-dig.com, request: "GET / HTTP/1.1", host: "www.z-dig.com", referrer: "http://www.z-dig.com" [root@z-dig ~]# |
看来多少还是管点用的。一共 access forbidden by rule 了 102-24=78 次。
适当的改改脚本,保存黑名单的历史数据,定期将大于1000的IP直接放入iptables!

18/08/2017 下午 2:36 沙发
厉害了老哥,晚辈佩服佩服。脚本玩得66的,我目前在用iptables来做非法ip的屏蔽,看到了此文,学习了! :mrgreen:
12/09/2016 下午 3:16 板凳
百度云观测啊 https://ticket-baidu.kf5.com/posts/view/4536/
12/09/2016 下午 3:15 地板
博主,你的IP有的是百度云观测的,最新的发现https://ticket-baidu.kf5.com/posts/view/4536/
25/07/2016 下午 9:48 4楼
今天我的博客也被人猜测路径了,竟然用的评论方式,评论了54次,那个人的ip事180.97.106.162。搜这个ip,搜到这的。
12/09/2016 下午 2:15 1层
@KeithYu 同样搜这个IP 搜到这里了。最后发现里面有的IP 是百度云观测的
https://ticket-baidu.kf5.com/posts/view/4536/
20/04/2016 上午 9:44 5楼
这个怎样防止误杀正常的搜索引擎?
21/04/2016 上午 9:54 1层
@蚊子 过滤bot
18/03/2016 上午 11:27 6楼
这个有风险,现在很多运营商做劫持,正常用户都是代理服务器出来的,你会屏蔽掉正常用户
17/12/2015 上午 10:41 7楼
学习了
12/12/2015 上午 1:43 8楼
表示我的网站一直有人在猜密码。。。
错误限制在2次之内,锁定2次将延长锁定时间到10天。。。。
可是猜密码ip不是固定的,不知道怎么ban
06/12/2015 下午 11:46 9楼
if ($request_method = POST) {
return 405;
}
04/12/2015 下午 3:50 10楼
CDN在前端这个无效吧
05/12/2015 下午 1:01 1层
@叮里个咚 要获取真实IP
04/12/2015 下午 2:13 11楼
nginx + lua +redis 来搞
04/12/2015 下午 2:20 1层
@默北 waf
04/12/2015 下午 2:24 2层
@www.z-dig.com 没用这个。
03/12/2015 下午 3:44 12楼
cool 我们也使用了这种方式限制IP,思路一样,但是这种实现比我们简练,学习了
04/12/2015 下午 12:07 1层
@异类深呼吸 www.z-dig.com
互相学习
04/12/2015 下午 12:18 1层
@异类深呼吸 你们怎样实现的?
30/11/2015 下午 4:47 13楼
Nginx 拒绝指定IP访问,Nginx 还可以实现这个功能?非常的牛逼额
20/04/2016 上午 9:42 1层
@香港虚拟主机 这是最基本的功能咯,apache也是一样有这个功能的;
也可放在.htaccess文件里禁止,不用重启服务;