linux , nginx: 封禁IP的辦法【轉】


今天,我們的一台服務器出了問題: 被若干IP地址訪問某個接口,該接口會發送短信。

所以,我們可以做兩件事: 1. nginx的層面封IP 。  2  linux server的層面封IP

先看nginx : 非常簡單,  加上  deny xxx.x.x.x; 就可以了。

linux的層面:  iptables -I INPUT -s 110.7.48.47 -j DROP

就可以把某個IP封掉。

目測,后者更方便一些。

在nginx 層面的封禁, req還是會打進來, 讓nginx 返回 403,  占用資源。

還可以把以上步驟做成自動化的腳本,

參考: http://www.cnblogs.com/huligong1234/p/7189426.html

下面是如何做成自動化的封禁IP

直接一步到位:

1. 修改crontab :    $ crontab -e

*/2 * * * * sh /opt/check_black_ip.sh

2. 增加這個文件:

tail -n10000 /usr/local/nginx/logs/access.log | awk '{print $1,$7}' | grep send_login_token | awk '{print $1}' | sort | uniq -c | sort -rn | awk '{if($1>30)print "deny "$2";"}' > /usr/local/nginx/conf/blacklist.append.conf
/usr/local/nginx/sbin/nginx -s reload

 

3. 確保你的nginx配置如下:

http{
    # ....
    include blacklist.conf;
}

 

下面是具體的原理和過程:

1. 確定好nginx的日志文件的位置,  例如:   /usr/local/nginx/logs/access.log  ( 如果你用了logrotate, 那么這個文件可能是每天更新一次 )

2. 使用命令:

$ tail -n50000 /usr/local/nginx/logs/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | | awk '{if($1>100)print "deny "$2";"}'

第一部分:  awk '{print $1}'  只打印出 所有log的ip (第一個被空格截斷的內容)

sort 是排序(按照字母順序)

uniq -c 是對所有內容進行去重,並且計數

sort -rn 是反向排序。 根據計數的結果。

所以,上面的命令,會給出如下結果:

 182.84.132.13
 117.82.174.128
 182.150.146.215
 182.148.58.231
 116.7.219.28
 182.150.28.110
 36.7.122.26

最后一部分的:  awk '{if($1>100) .... }'是一個bash腳本,會找到所有出現過100次的ip, 然后輸出一段deny這樣的文本:

deny 182.84.132.13;
deny 117.82.174.128;
deny 182.150.146.215;
deny 182.148.58.231;
deny 116.7.219.28;
deny 182.150.28.110;
deny 36.7.122.26;
deny 110.7.48.47;
deny 124.127.182.6;
deny 110.188.153.219;

 

最后的最后,把上數的結果, 使用 ">" (覆蓋文件)  或者 ">>" (追加文件) 操作符到blacklist.conf文件中。 完整命令為:

$ tail -n50000 /usr/local/nginx/logs/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | awk '{if($1>100)print "deny "$2";"}' >> /usr/local/nginx/conf/blacklist.conf

nginx中的配置如下:

http{
    # ....
    include blacklist.conf;
}

進一步的,我們可以只針對某個url的訪問進行統計, 代碼如下:

$ tail -n10000 /usr/local/nginx/logs/access.log | awk '{print $1,$7}' | grep send_login_token | awk '{print $1}' | sort | uniq -c | sort -rn | awk '{if($1>30)print "deny "$2";"}' >> /usr/local/nginx/conf/blacklist.conf

 

上面代碼,會查看過去10000行nginx記錄,找到對於訪問 "/interface/..../send_login_token " 的request, 進行ip的計數,對於超過30次訪問的,直接封ip

根據當前時刻的ip訪問, 自動封禁ip 的腳本.

列出當前時刻, 所有的請求數大於10的ip地址: netstat -an | grep ^tcp.*:80 | egrep -v 'LISTEN|127.0.0.1' | awk -F"[ ]+|[:]" '{print $6}' | sort | uniq -c |sort -rn | awk '{ if ($1>10){print $2}}'

解釋:

1. netstat -an -a 表示列出所有, -n 表示列出來的都是 數字(例如 3.3.3.4 , 而不是名稱) 例如:

# netstat -an
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:3020            0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:3021            0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:3022            0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:3023            0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:35888           0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:3000            0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:3001            0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:3002            0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:3003            0.0.0.0:*               LISTEN     
tcp        0      0 172.18.230.209:80       118.112.56.229:6785     TIME_WAIT  
tcp        0      0 172.18.230.209:37220    218.5.173.146:1521      ESTABLISHED
tcp        0      0 172.18.230.209:80       182.84.139.53:1817      ESTABLISHED
tcp        0      0 172.18.230.209:37212    218.5.173.146:1521      ESTABLISHED
tcp      401      0 172.18.230.209:38086    140.205.140.205:80      CLOSE_WAIT 

 

2. $ netstat -an |grep ^tcp.*:80 是對當前的鏈接中,找到所有的要訪問80端口的請求. 例如:

# netstat -an | grep ^tcp.*:80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN     
tcp        0      0 172.18.230.209:80       118.112.56.229:7873     TIME_WAIT  
tcp        0      0 172.18.230.209:80       118.112.56.229:7426     ESTABLISHED
tcp      401      0 172.18.230.209:38086    140.205.140.205:80      CLOSE_WAIT 
tcp        0      0 172.18.230.209:80       182.84.139.53:49165     TIME_WAIT  
tcp        0      0 172.18.230.209:80       180.108.11.25:15104     TIME_WAIT 

 

3. $ netstat -an |grep ^tcp.*:80 | egrep -v 'LISTEN|127.0.0.1' , 這句話是對 "127.0.0.1' 或者 LISTEN 做個排除. 去掉本地的請求, 去掉 正在 LISTEN的接口

4. awk -F"[ ]+|[:]" '{print $6}' 這里是對結果做個處理, 把某一行的結果, 按照 空格或者 ':' 冒號來分割,取得第六個.(起始的是第一個), 例如:

tcp        0      0 172.18.230.209:80       118.112.56.229:7873     TIME_WAIT

按照空格或者: 來分割的話,第六個就是 118.112.56.229, 這個就是正在請求的IP

5. sort: 按照字母順序排序. uniq -c 表示 去重,並且加上 出現的次數. sort -r 表示 翻轉排序. -n 表示按照數字的大小排序.

6. awk '{if ($1>$num){print $2}} 處理結果, 找到滿足條件的, 然后打印出來.

完整版, 根據每秒ip的訪問上線,來自動封禁的腳本 :

#!/bin/bash
num=100 #  每秒某個ip的訪問上限
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

 

解封IP的方法

先用這個命令看到所有被封禁的IP $ iptables -L -n -v --line-numbers

iptables -L -n -v --line-numbers
Chain INPUT (policy ACCEPT 289 packets, 71013 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
        0     0 DROP       all  --  *      *       45.77.183.135        0.0.0.0/0           
        0     0 DROP       all  --  *      *       120.239.199.152      0.0.0.0/0           
        0     0 DROP       all  --  *      *       47.52.132.105        0.0.0.0/0

然后用這個命令恢復:  iptables -D INPUT ( 例如:iptables -D INPUT 1 就是刪掉上面的第一條 45.77.183.135 )

 

轉自

linux , nginx: 封禁IP的辦法 (自動化腳本封ip, 根據瞬時的請求總量,或者根據日志 - 為程序員服務 http://ju.outofmemory.cn/entry/343736


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM