shell+awk实现nginx自动拒绝指定IP访问。

回复 收藏
本帖最后由 ziwii 于 2016-1-16 17:15 编辑
解决思路来自ttlsa的文章《坏人还是有的(Nginx拒绝指定IP访问)》
http://www.ttlsa.com/nginx/nginx-deny-ip-access/
继上次发现某地区用户不断POST我司快速登录页面,并通过nginx本身的deny拒绝其IP访问后。四天时间里,该用户以一天四个IP的频率依然进行这种攻击。
烦不胜烦,今天更是发现此用户开始尝试在我下班时间攻击,在我上班时间则减缓频率试图模拟普通用户。{:4_104:}

{:4_102:}虽然该用户减缓了频率,但是流量图是不会说谎的,每次带来的10M+流量总是那么绚丽。手头的一项紧急任务刚刚结束,正有空档时间可以好好研究一下这个问题,日前看过一篇nginx拒绝指定IP访问的技术文章(就是上边那篇),解决方法清晰简单正好可以拿来用!

直接拿来用是不行的,基于自身情况对脚本进行了修改,以下为脚本内容:
  1. #! /bin/bash
  2. #block ip
  3. BLOCK_IP_FILE=/opt/webserver/nginx/etc/ext/deny-list.conf
  4. BLOCK_IP=/tmp/deny.conf
  5. NGINX_CMD=/etc/init.d/nginx
  6. DATE=$(date +"%Y%m%d")
  7. /bin/cp $BLOCK_IP_FILE $BLOCK_IP&&
  8. /bin/cat /var/log/nginx/uu898/user*${DATE} | /bin/awk '{if($6~/POST/ && $7~/uickChannel.aspx/ && $9~/200/)print $0}'|/bin/awk '{IP[$1]++}END{for (i in IP) print IP[i],i}'|/bin/awk '{if($1>50000)print "deny "$2";"}'>$BLOCK_IP &&
  9. /bin/grep -v -f $BLOCK_IP_FILE $BLOCK_IP >>$BLOCK_IP_FILE
  10. $NGINX_CMD configtest &&
  11. if [ $?eq0 ]
  12. then
  13. $NGINX_CMD reload
  14. fi


脚本为每30分钟执行一次,当获取到该IP针对该页面进行POST操作超过2W次则将其放入nginx的deny列表,并重载nginx配置。为了防止自己修改nginx配置时,脚本直接重载配置导致前端异常,所以在脚本中加入了配置检测判断,如果配置异常则不重载配置。

{:4_104:}突然发现自己真蠢,之前一直在烦恼2W次那个值要怎么确定才好。刚刚突然想到,我TM统计看一下正常IP一天的访问次数不就行了吗!!!!
结果如图(正常用户每天的次数不会超过20次,那么超过这个值的全部ban掉就好啦!Oh yeah!)
QQ截图20160116104206.png



2016-01-15 21:37 举报
已邀请:
0

xyl5869

赞同来自:

中间的正则完全看不懂啊
0

亮亮

赞同来自:

/bin/awk '{IP[$1]++}END{for (i in IP) print IP,i}'这一段看着怪怪的{:4_99:}有点不太理解
0

lyhabc

赞同来自:

location / {
deny 220.181.57.217;
deny 220.181.57.218;
deny 220.181.57.219;
allow all;
}

这样?干嘛不在iptables里配置
0

ziwii

赞同来自:

本帖最后由 ziwii 于 2016-1-16 17:57 编辑
亮亮 发表于 2016-1-16 10:23
/bin/awk '{IP[$1]++}END{for (i in IP) print IP,i}'这一段看着怪怪的有点不太理解
  1. {

  2.         ip[$1]++
  3. }
  4. END {
  5.         for(i in ip)
  6.         {
  7.                 print ip[i],i
  8.         }
  9. }

这是awk的for循环,将提取到的$1也就是IP作为一个数组下标,从上到下依次打印出IP出现次数(初始为1)和IP,如果ip重复,则IP出现次数加1。
是awk统计IP次数的一种固定格式。
0

ziwii

赞同来自:

lyhabc 发表于 2016-1-16 10:42
location / {
deny 220.181.57.217;
deny 220.181.57.218;

是在nginx的配置文件中include deny-list.conf。deny-list.conf中 文件以 deny 1.1.1.1;的格式保存。
写在这里,如果误封了普通用户的IP,可以在nginx访问日志中看到其访问状态是被拒绝了。
0

lyhabc

赞同来自:

用awk遍历数组有点复杂,适合 老手,不适合新手
访问控制
限制只让某个ip访问
allow 219.232.244.234;
deny all;

禁止某个IP或者IP段访问站点的设置方法
首先建立下面的配置文件放在nginx的conf目录下面,命名为deny.ip
cat deny.ip
deny 192.168.1.11;
deny 192.168.1.123;
deny 10.0.1.0/24;

在nginx的配置文件nginx.conf中加入:include deny.ip;
铭哥也有教
0

lyhabc

赞同来自:

//方法一 将黑白名单写在虚拟主机配置文件
//wordpress.conf
server
{
listen 8080;
server_name a.com www.b.com www.c.com;
#if ($host != 'www.b.com' ) {     
#rewrite ^/(.*)$ http://www.b.com/$1 permanent;  
}
index index.html index.htm index.php;
root /data/www2;

location ~ \.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9001;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/www2$fastcgi_script_name;
}



#黑名单
deny 219.232.244.225;
deny 219.232.244.234;
allow all;


#白名单
allow 127.0.0.1;
allow 192.168.31.141;
deny all;


}



//方法二 首先建立下面的配置文件放在nginx的conf目录下面,命名为deny.ip
cat deny.ip
deny 192.168.1.11;
deny 192.168.1.123;
deny 10.0.1.0/24;

在nginx的配置文件nginx.conf中加入:include deny.ip;
reload一下nginx服务:/usr/local/nginx/sbin/nginx -s reload 就可以生效了。



//方法三
//wordpress.conf
server
{
listen 8080;
server_name a.com www.b.com www.c.com;
#if ($host != 'www.b.com' ) {     
#rewrite ^/(.*)$ http://www.b.com/$1 permanent;  
}
index index.html index.htm index.php;
root /data/www2;

location ~ \.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9001;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/www2$fastcgi_script_name;
}

#某个目录下限制ip   /uc_server/目录
    location /uc_server/ {
        allow 192.168.31.0/24;
        deny all;
    }


}

//方法四
server
{
listen 8080;
server_name a.com www.b.com www.c.com;
#if ($host != 'www.b.com' ) {     
#rewrite ^/(.*)$ http://www.b.com/$1 permanent;  
}
index index.html index.htm index.php;
root /data/www2;

location ~ \.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9001;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/www2$fastcgi_script_name;
}

#某个目录下限制ip   /uc_server/目录
#location /uc_server/ {
#allow 192.168.31.0/24;
#deny all;
#}
   
   
#针对目录限制php解析
location ~ .*(diy|template|attachments|forumdata|attachment|image/.*\.php$ {
deny all;
}
}


//方法五
server
{
listen 8080;
server_name a.com www.b.com www.c.com;
#if ($host != 'www.b.com' ) {     
#rewrite ^/(.*)$ http://www.b.com/$1 permanent;  
}
index index.html index.htm index.php;
root /data/www2;

location ~ \.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9001;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/www2$fastcgi_script_name;
}

#根据user_agent控制
if ($http_user_agent ~ 'bingbot/2.0|MJ12bot/v1.4.2|Spider/3.0|YoudaoBot|Tomato|Gecko/20100315'){
return 403;
}

}

curl -A 'SDFSDF bingbot/2.0asd' 'http://www.a.com/sdf/sdf.php' -I   //-A 模拟useragent
0

boy461205160

赞同来自:

lyhabc 发表于 2016-1-16 12:06
//方法一 将黑白名单写在虚拟主机配置文件
//wordpress.conf
server

处理问题的思路清晰
0

亮亮

赞同来自:

ziwii 发表于 2016-1-16 11:32
这是awk的for循环,将提取到的$1也就是IP作为一个数组下标,从上到下依次打印出IP出现次数(初始为1) ...

知道是数组了还是觉得怪怪的不太能理解{:4_102:},这种固定格式我想还是死记住比较好
0

渐行渐远

赞同来自:

厉害
0

蔡炳森

赞同来自:

学习了,看来shell还是要加深学习。
0

has

赞同来自:

看看

回复帖子,请先登录注册

退出全屏模式 全屏模式 回复
评分
  • 评分区间
  • 学分
  • -30 ~ 30
可选评分理由: