Nginx 使用---拒絕指定IP訪問

一、問題描述

服務器可能會受到攻擊者的惡意訪問,攻擊者IP會不斷的猜測路徑,上傳文件(木馬);或者進行短信消耗;或者破解密碼,等等行爲。我們要做的是,對這些惡意的訪問IP進行攔截。

二、Nginx的日誌格式

因爲首先一定是要查看日誌的,所以首先熟悉下Nginx的日誌格式描述:

 log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"'
                       '$upstream_addr $upstream_response_time $request_time ';
    access_log  logs/access.log  main;

相關說明解釋

  1. $remote_addr 與$http_x_forwarded_for 用以記錄客戶端的ip地址;
  2. $remote_user :用來記錄客戶端用戶名稱;
  3. $time_local : 用來記錄訪問時間與時區;
  4. $request : 用來記錄請求的url與http協議;
  5. $status : 用來記錄請求狀態;成功是200,
  6. $body_bytes_s ent :記錄發送給客戶端文件主體內容大小;
  7. $http_referer :用來記錄從那個頁面鏈接訪問過來的;
  8. $http_user_agent :記錄客戶端瀏覽器的相關信息;

其實nginx access日誌的格式不是一成不變的,是可以自定義的。在nginx的nginx.conf配置文件找到:log_format 這裏就是日誌的格式。

配置access log日誌的存儲位置及文件

access_log  /usr/local/nginx/log/access.log  main;

注意:access.log文件是可以按日期進行分割的,方便查看及處理 

三、一個攻擊案例說明

nginx日誌如下:

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)" "-"

195.154.216.165 這個ip不斷的猜測路徑、試圖往服務器上傳文件(木馬)。

查看日誌中這個ip出現的次數。

[root@z-dig www]# grep '195.154.216.165' 2015-11-28.access.log|wc -l
289
[root@z-dig www]#

查看訪問者的IP地址中檢索訪問者的城市,州和國家/地區等信息。

[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]#

法國的哥們竟然試了280多次!辛苦了。

用 shell 和定時任務來實現吧。>_<

網站跑在 Nginx 上,所以可以使用 Nginx 的 Deny 來拒絕攻擊者的IP訪問。

那麼思路就出來了,定期(五分鐘或十分鐘)獲取攻擊者的IP,將IP放入到黑名單(Nginx 配置文件),並 reload 使其生效。

由於前期規劃的比較好,網站的訪問日誌放在了一個指定的目錄,Nginx 的錯誤日誌也放在了一個指定的目錄。網站的訪問日誌每日進行切割。Nginx 的錯誤日誌沒有進行切割。

下面就是我的思路和操作步驟:

通過 Nginx 的錯誤日誌(爲什麼不使用訪問日誌)來獲取攻擊者的IP。之前沒有對 Nginx 的錯誤日誌進行定時切割,爲了方便統計攻擊者的IP所以,編寫腳本並加入定時任務,使錯誤日誌每小時切割一次,並且每小時對黑名單文件進行清空。

錯誤日誌切割、清空黑名單腳本:

[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 : [email protected]

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。

[root@z-dig scripts]# cat block-ip.sh 
#!/bin/bash
# Author  : Mr.Zhou
# Email   : [email protected]
# 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 進去。

[root@z-dig conf]# grep blockip.conf nginx.conf
  include website/blockip.conf;
[root@z-dig conf]#

blockip.conf 文件格式如下:

[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則什麼都不做。

[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

[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,看是否有變化。

[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

[root@z-dig ~]# grep '195.154.188.224' /data/logs/nginx/error.log |grep -v 'access forbidden' |wc -l

[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!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章