今天,咱們的一臺服務器出了問題: 被若干IP地址訪問某個接口,該接口會發送短信。html
因此,咱們能夠作兩件事: 1. nginx的層面封IP 。 2 linux server的層面封IPlinux
先看nginx : 很是簡單, 加上 deny xxx.x.x.x; 就能夠了。nginx
linux的層面: iptables -I INPUT -s 110.7.48.47 -j DROP程序員
就能夠把某個IP封掉。bash
目測,後者更方便一些。服務器
在nginx 層面的封禁, req仍是會打進來, 讓nginx 返回 403, 佔用資源。app
還能夠把以上步驟作成自動化的腳本,tcp
參考: http://www.cnblogs.com/huligong1234/p/7189426.html url
直接一步到位:spa
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
列出當前時刻, 全部的請求數大於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 $ 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