帮朋友维护他那个网站的服务器,最近突然流量大涨,服务器压力也陡增。上去看了一下nginx日志,有大量的POST某几个特定php请求,一个IP一秒钟就POST四五个。基本都是什么reg.php,login.php,article_add.php这一类的。明显是一群装了自动发帖机的肉鸡或者个人机在进行***。

说好听点,也就是发点广告贴,说不好了,挂点***什么的也是难说的。虽然说这个网站的论坛和后台的php已经没有那些注册发贴机可以利用的漏洞了,完全是白刷,但是也相当的消耗系统资源和带宽。每次请求也都会转到后端去调用mysql什么的。正常访问都巨慢,本来流量就有限,不带这么玩的。

服务器是我给装的FreeBSD,非常稳定,也编译了内核加载了ipfw,比较好办。不过一开始太小看这帮孙子了,尝试手工封锁,过滤出IP以后,手工运行ipfw封ip,结果搞了一个多小时,还是没完没了的,就干脆写两个脚本来干这事,放到crontab里面自动跑。

脚本一:过滤自动发贴IP -- tail.sh

   
   
   
   
  1. #!/bin/sh 
  2.  
  3. tail -F /var/log/nginx-access.log | grep -E "/member/article_add.php|/member/login.php|/include/vdimgck.php" | awk '{print $1}' | grep -v your_admin_ip >> /usr/local/etc/nginx/ipfw.rules.tmp & 

详细解说一下,tail -F 是不断的滚动日志,-F代表无论日志是否rotate,都滚动这个文件名。跟-f是有区别的。然后grep正则匹配多个过滤条件,然后用awk打印ip,然后去掉你自己的远端管理ip,追加输出给一个叫ipfw.rules.tmp的临时文件。

脚本一执行一次即可,无需重复执行。

 

脚本二:注册机IP去重,放入ipfw脚本中 -- ipfw.sh

 

   
   
   
   
  1. #!/bin/sh 
  2. cat /usr/local/etc/nginx/ipfw.rules.tmp | sort -u > /usr/local/etc/nginx/ipfw.rules 
  3.  
  4. ipfw -f flush 
  5.  
  6. ipfw add 00100 allow ip from any to any via lo0 
  7. ipfw add 00200 deny ip from any to 127.0.0.0/8 
  8. ipfw add 00300 deny ip from 127.0.0.0/8 to any 
  9. ipfw add 00400 deny ip from any to ::1 
  10. ipfw add 00500 deny ip from ::1 to any 
  11. ipfw add 00600 allow ipv6-icmp from :: to ff02::/16 
  12. ipfw add 00700 allow ipv6-icmp from fe80::/10 to fe80::/10 
  13. ipfw add 00800 allow ipv6-icmp from fe80::/10 to ff02::/16 
  14. ipfw add 00900 allow ipv6-icmp from any to any ip6 icmp6types 1 
  15. ipfw add 01000 allow ipv6-icmp from any to any ip6 icmp6types 2,135,136 
  16.  
  17. ipfw add 10010 deny udp from any to any 80 
  18.  
  19. seq=10100 
  20. for i in $(cat /usr/local/etc/nginx/ipfw.rules); do 
  21.         ipfw add $seq deny all from $i to any 80 
  22.         seq=$(($seq+1)) 
  23. done 

逐行解释一下

02. 将脚本一生成的临时文件排序去重后放入新的文件中(将第二行替换成下面这行就是封锁C类的IP地址段了)

   
   
   
   
  1. cat /usr/local/etc/nginx/ipfw.rules.tmp | awk -F'.' '{print $1"."$2"."$3".0/24"}' | sort -u > /usr/local/etc/nginx/ipfw.rules 

04. 强制删除所有ipfw规则

06-15. ipfw原有默认规则。04行删除了,要重新补回去。

17. 拒绝80端口udp连接,就是所谓的阿拉丁DDoS***

19. 规则序号,从10100开始

20. 循环去重后的ip地址列表

21. ipfw添加到规则$seq序号,拒绝所有来自$i到任意的80端口连接

22. 序号累加。

ipfw可以在一个规则序号里添加多个ip,之所以做了序号累加,主要是ipfw在删除某个规则时,是按照规则序号删除,不是按照ip删除。都放在一个里面,一删就全删了。如果有哪个特定ip需要访问网站,只要删除对应的单个序号就好了。

脚本放入crontab里面,每12小时运行一次,其实我手工运行了几次,2个多小时,已经封锁了将近300个ip了,以福建莆田的ip最多,其次是厦门,泉州,福州的IP。其他各省也有一些,但是很少。

 

上谷歌查了一下,福建的莆田,厦门,泉州是全国垃圾邮件和垃圾帖子最大的集散地。看到这三个地方的IP,直接封IP段就对了,27.159.0.0/16,就这样封,不用留面子。

 

熟悉iptables,把脚本改成iptables,就可以用在linux下面了。

这些论坛自动注册发贴机实在是讨厌的要死。

还有个注意事项,tail的内容,可以直接打印在屏幕上,但是往磁盘上写是有缓冲的,也就是系统输入输出的buffer,这个buffer要累积达到16k才会往磁盘上写入并flush掉。所以,如果***ip很少的话,一开始创建的临时文件并不会马上接收到内容,需要等一会才可以。