shell入門26-監(jiān)控網絡,nginx腳本分析,異常登陸IP過濾

最后練幾個典型腳本

一,監(jiān)控網絡連接狀態(tài)腳本

腳本

#!/bin/bash
# 功能描述:監(jiān)控網絡連接狀態(tài)腳本

# 所有TCP連接的個數
TCP_Total=$(ss -s |awk '$1=="TCP"{print $2}')
# 所有UDP連接的個數
TCP_Total=$(ss -s |awk '$1=="UDP"{print $2}')
# 所有UNIX socket連接個數
Unix_sockets_Total=$(ss -ax |awk 'BEGIN{count=0} {count++} END{print count}')

# 所有處理Listen監(jiān)聽狀態(tài)的TCP端口個數
TCP_Listen_Total=$(ss -antlpH |awk 'BEGIN{count=0} {count++} END{print count}')


# 所有處于ESTABLISHED狀態(tài)的TCP連接個數
TCP_Estab_Total=$(ss -antpH |awk 'BEGIN{count=0} /^ESTAB/{count++} END{print count}')

# 所有處于SYN-RECV狀態(tài)的TCP連接個數
TCP_SYN_RECV_Total=$(ss -antpH |awk 'BEGIN{count=0} /^SYN-RECV/{count++} END{print count}')

# 所有處于TIME-WAIT狀態(tài)的TCP連接個數
TCP_TIME_WAIT_Total=$(ss -antpH |awk 'BEGIN{count=0} /^TIME-WAIT/{count++} END{print count}')

# 所有處于TIME-WAIT1狀態(tài)的連接個數
TCP_TIME_WAIT1_Total=$(ss -antpH |awk 'BEGIN{count=0} /^TIME-WAIT1/{count++} END{print count}')

# 所有處于TIME-WAIT2狀態(tài)的TCP連接個數
TCP_TIME_WAIT2_Total=$(ss -antpH |awk 'BEGIN{count=0} /^TIME-WAIT2/{count++} END{print count}')

# 所有遠程主機的TCP連接次數
TCP_Remote_Count=$(ss -antH | awk '$1!~/LISTEN/{IP[$5]++} END{ for(i in IP){print IP[i],i} }' |sort -nr)
# 每個端口被訪問的次數
TCP_Port_Count=$(ss -antH |sed -r 's/ +/ /g' |awk -F"[ :]" '$1!~/LISTEN/{port[$5]++} END{for (i in port) {print port[i],i}}' |sort -nr)
# 定義輸出顏色
SUCCESS="echo -en \\033[1;32m" # 綠色
NORMAL="echo -en \\033[0;39m" #黑色

# 顯示TCP連接總數
tcp_total(){
  echo -n "TCP連接總數:"
  $SUCCESS
  echo "$TCP_Total"
  $NORMAL
}
# 顯示處于LISTEN狀態(tài)的TCP端口個數
tcp_listen(){
  echo -n "處于LISTEN狀態(tài)的TCP端口個數:"
  $SUCCESS
  echo "$TCP_Listen_Total"
  $NORMAL
}
# 顯示處于ESTABLISHED狀態(tài)的TCP連接個數
tcp_estab(){
  echo -n "處于ESTAB狀態(tài)的TCP連接個數:"
  $SUCCESS
  echo "$TCP_Estab_Total"
  $NORMAL
}
# 顯示處于SYN-RECV狀態(tài)的TCP連接個數
tcp_syn_recv(){
  echo -n "處于SYN-RECV狀態(tài)的TCP連接個數:"
  $SUCCESS
  echo "$TCP_SYN_RECV_Total"
  $NORMAL
}
# 顯示處于TIME-WAIT狀態(tài)的TCP連接個數
tcp_time_wait(){
  echo -n "處于TIME-WAIT狀態(tài)的TCP連接個數:"
  $SUCCESS
  echo "$TCP_TIME_WAIT_Total"
  $NORMAL
}
# 顯示處于TIME-WAIT1狀態(tài)的TCP連接個數
tcp_time_wait1(){
  echo -n "處于TIME-WAIT1狀態(tài)的TCP連接個數:"
  $SUCCESS
  echo "$TCP_TIME_WAIT1_Total"
  $NORMAL
}
# 顯示處于TIME-WAIT2狀態(tài)的TCP連接個數
tcp_time_wait2(){
  echo -n "處于TIME-WAIT2狀態(tài)的TCP連接個數:"
  $SUCCESS
  echo "$TCP_TIME_WAIT2_Total"
  $NORMAL
}
# 顯示UDP連接總數
udp_total(){
  echo -n "UDP連接總數:"
  $SUCCESS
  echo "$UDP_Total"
  $NORMAL
}
# 顯示UNIX socket連接總數
unix_total(){
  echo -n "Unix socket連接總數:"
  $SUCCESS
  echo "$Unix_sockets_Total"
  $NORMAL
}
# 顯示每個遠程主機的訪問次數
remote_count(){
  echo -n "每個遠程主機與本機的并發(fā)連接數:"
  $SUCCESS
  echo "$TCP_Remote_Total"
  $NORMAL
}
# 顯示每個端口的并發(fā)連接數
port_count() {
  echo "每個端口的并發(fā)連接數:"
  $SUCCESS
  echo "$TCP_Port_Count"
  $NORMAL
}

print_info() {
  echo -e "------------------------------------"
  $1
}

print_info tcp_total
print_info tcp_listen
print_info tcp_estab
print_info tcp_syn_recv
print_info tcp_time_wait
print_info tcp_time_wait1
print_info tcp_time_wait2
print_info udp_total
print_info unix_total
print_info remote_count
print_info port_count
echo -e "--------------------------------------------------"

效果

bash netstat.sh 
------------------------------------
TCP連接總數:0
------------------------------------
處于LISTEN狀態(tài)的TCP端口個數:5
------------------------------------
處于ESTAB狀態(tài)的TCP連接個數:6
------------------------------------
處于SYN-RECV狀態(tài)的TCP連接個數:0
------------------------------------
處于TIME-WAIT狀態(tài)的TCP連接個數:0
------------------------------------
處于TIME-WAIT1狀態(tài)的TCP連接個數:0
------------------------------------
處于TIME-WAIT2狀態(tài)的TCP連接個數:0
------------------------------------
UDP連接總數:
------------------------------------
Unix socket連接總數:161
------------------------------------
每個遠程主機與本機的并發(fā)連接數:
------------------------------------
每個端口的并發(fā)連接數:
2 33741
2 22
1 55248
1 55246
1 43418
--------------------------------------------------

二,Nginx日志分析腳本

日志樣例

172.40.62.167 - - [30/Sep/2018:22:38:57 +0800] "GET /styles/blue-theme.css HTTP/1.1" 200 130510 "-" "http://127.0.0.1/setup.php" "Mozilla/5.0 (X11;Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
172.40.58.146 - - [19/Nov/2018:09:01:46 +0800] "GET /course HTTP/1.1" 404 169 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0"
172.40.58.152 - - [19/Nov/2018:08:58:40 +0800] "GET /favicon.ico HTTP/1.1"200 32988 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0"
172.40.58.144 - - [16/Apr/2019:19:36:18 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
172.40.58.212 - - [16/Apr/2019:19:39:23 +0800] "GET /favicon.ico HTTP/1.1" 200 81145 "http://172.40.50.118/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
172.40.58.48 - - [16/Apr/2019:19:36:45 +0800] "GET /index.html HTTP/1.1" 200 32988 "http://172.40.50.120/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
172.40.58.212 - - [16/Apr/2019:19:36:56 +0800] "GET /test.html HTTP/1.1" 404 571 "http://172.40.50.118/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
[root@127 shell_demo]# 

腳本

#!/bin/bash
# 功能描述:NGINX標準日志分析腳本
# 統(tǒng)計信息包括:
#1.頁面訪問量PV
#2.用戶量UV
#3.人均訪問量
#4.每個IP的訪問次數
#5.HTTP狀態(tài)碼統(tǒng)計
#6.累計頁面字節(jié)流量
#7.熱點數據


GREEN_COL='\033[32m'
NONE_COL='\033[0m'
line='echo ++++++++++++++++++++++++++++++++++'

# read -p "請輸入日志文件:" logfile
logfile="$1"
echo

# 判斷日志文件是否存在
if [ ! -f $logfile ]; then
  echo "$logfile文件不存在。"
  exit
fi


# 統(tǒng)計頁面訪問量(PV)
# PV=$(cat $logfile|wc -l)
PV=$(sed -n '$=' $logfile)

# 統(tǒng)計用戶數量(UV)
# UV=$(cut -f1 -d' ' $logfile|sort |uniq |wc -l)
UV=$(awk '{IP[$1]++} END{ print length(IP)}' $logfile)

# 統(tǒng)計人均訪問次量
Average_PV=$(echo "scale=2;$PV/$UV" |bc)

# 統(tǒng)計每個IP的訪問次數
#declare -A IP
#while read ip other
#do
#  let IP[$ip]+=1
#done < $logfile
IP=$(awk '{IP[$1]++} END{for (i in IP) {print i, "\t的訪問次數為:",IP[i]}"\r"}' $logfile |sort -rn -k3)

# 統(tǒng)計各種HTTP狀態(tài)碼個數
#declare -A IP
#while read ip dash user time zone method file protocol code size other
#do
#  let STATUS[$code]++
#done < $logfile
STATUS=$(awk '{IP[$9]++} END{for (i in IP){print i "狀態(tài)的次數:",IP[i]}"\r"}' $logfile | sort -rn -k2)

# 統(tǒng)計網頁累計訪問字節(jié)大小
#while read ip dash user time zone method file protocol code size other
#do
#  let Body_size+=$size
#done < $logfile
Body_size=$(awk '{SUM+=$10} END{print SUM}' $logfile)

# 統(tǒng)計熱點數據
#declare -A URI
#while read ip dash user time zone method file protocol code size other
#do
#  let URI[$file]++
#done < $logfile
URI=$(awk '{IP[$7]++} END{for (i in IP){if (IP[I]>=2) {print i "的訪問次數:",IP[i]}}}' $logfile)

echo -e "\033[91m\t日志分析數據報表\033[0m"

# 顯示PV和UV訪問量,平均用戶訪問量
$line
echo -e "累計PV量:$GREEN_COL$PV$NONE_COL"
echo -e "累計UV量:$GREEN_COL$UV$NONE_COL"
echo -e "平均用戶訪問量:$GREEN_COL$Average_PV$NONE_COL"

# 顯示網頁累計訪問字節(jié)數
$line
echo -e "累計訪問字節(jié)數:$GREEN_COL$Body_size$NONE_COL Byte"

# 顯示指定的HTTP狀態(tài)碼數量
$line
#for i in 200 404 500
#do
#  if [ ${STATUS[$i]} ]; then
#    echo -e "$i 狀態(tài)碼次數:$GREEN_COL ${STATUS[$i]} $NONE_COL"
#  else
#    echo -e "$i 狀態(tài)碼次數:$GREEN_COL 0 $NONE_COL"
#  fi
#done
echo "$STATUS"

# 顯示每個IP的訪問次數
$line
#for i in ${!IP[@]}
#do
#  printf "%-15s的訪問次數為:$GREEN_COL$s$NONE_COL\n" $i ${IP[$i]}
#done
echo "$IP"

# 顯示訪問量大于500的URI
echo -e "$GREEN_COL 訪問量大于500的URI:$NONE_COL"
#for i in "${!URI[@]}"
#do
#  if [ ${URI["$i"]} -gt 500 ]; then
#    echo "----------------------------------"
#    echo "$i"
#    echo "$URI[$i]}次"
#    echo "-----------------------------------"
#  fi
#done
echo "$URI"

效果

[root@127 shell_demo]# bash nginx_log.sh access.log 

        日志分析數據報表
++++++++++++++++++++++++++++++++++
累計PV量:7
累計UV量:6
平均用戶訪問量:1.16
++++++++++++++++++++++++++++++++++
累計訪問字節(jié)數:245383 Byte
++++++++++++++++++++++++++++++++++
200狀態(tài)的次數: 3
404狀態(tài)的次數: 2
32988狀態(tài)的次數: 1
304狀態(tài)的次數: 1
++++++++++++++++++++++++++++++++++
172.40.58.212   的訪問次數為: 2
172.40.62.167   的訪問次數為: 1
172.40.58.48    的訪問次數為: 1
172.40.58.152   的訪問次數為: 1
172.40.58.146   的訪問次數為: 1
172.40.58.144   的訪問次數為: 1
 訪問量大于500的URI:

三,異常IP過濾

腳本

#!/bin/bash
# 功能描述:分析系統(tǒng)登陸日志,過濾異常IP地址,并通過防火墻禁用該IP

# 強制退出時,關閉所有后臺進程
trap 'kill $one_pid; kill $five_pid; kill $fifteen_pid; exit' EXIT INT

# 日志文件路徑
LOGFILE=/var/log/demo_secure
BLOCKFILE=/tmp/blockip.txt

one_minute(){
  while :; do
    # 獲取計算機當前時間,以及1分鐘前的時間,時間格式
    # %b(月份簡寫,Jan) %e(日期,1) %T(時間 18:00:00)
    # LANG=C的作用是否防止輸出中文
    # 使用local定義局部變量的好處是多個函數使用相同的變量名也不會沖突
    local curtime_month=$(LANG=C date +"%b")
    local curtime_day=$(LANG=C date +"%e")
    local curtime_time=$(LANG=C date +"%T")
    local one_minus_ago=$(LANG=C date -d "1 minutes ago" +"%T")
    # 將當前時間轉換為距離1970-01-01 00:00:00的秒數,方便后期計算
    local curtime_seconds=$(LANG=C date +"%s")
    # 分析1分鐘內所有的日志,如果密碼失敗則過濾倒數第4列的IP地址
    # 通過管道對過濾的IP進行計數統(tǒng)計,提取密碼失敗次數大于等于3次的IP地址
    # awk調用外部Shell的變量時,雙引號在外面表示字符串("''"),單引號在外邊表示數字('""')
    pass_fail_ip=$(awk ' 
        $1=="'$curtime_month'" && \
        $2=='"$curtime_day"' && \
        $3>="'$one_minus_ago'" && \
        $3<="'$curtime_time'" \
        { if ($6=="Failed" && $9!="invalid") { print $(NF-3)}}'
    $LOGFILE | \
        awk '{IP[$1]++} END{ for (i in IP) { if (IP[i]>=3) {print i}}}')
    # 將密碼失敗次數大于3次的IP寫入黑名單文件,
    # 每次寫入前,都需要判斷黑名單中是否已經存在該IP
    # 寫入黑名單時附加時間標記,實現僅將IP放入黑名單特定的時間,
    # 如:密碼失敗3次后,禁止該 IP在20分鐘內再次訪問服務器
    for i in $pass_fail_ip; do
      if ! grep -q "$i" $BLOCKFILE; then
        echo "$curtime_seconds $i" >> $BLOCKFILE
      fi
    done

    # 提取無效帳戶登錄服務器3次的IP地址,并將其加入黑名單
    user_invalid_ip=$(awk '
        $1=="'$curtime_month'" && \
        $2=='"$curtime_day"' && \
        $3>="'$one_minus_ago'" && \
        $3<="'$curtime_time'" \
        { if ($6=="Invalid") {print $(NF-2)}}' $LOGFILE | \
        awk '{IP[$1]++} END{for (i in IP) {if (IP[i]>=3) {print i}}}')
    
    for j in $user_invalild_ip; do
        if ! grep -q "$j" $BLOCKFILE; then
          echo "$curtime_seconds $j" >> $BLOCKFILE
        fi
    done
    sleep 60
  done
}

# 每隔20分鐘檢查一次黑名單,清理大于20分鐘的黑名單IP
clear_blockip() {
  while : ; do
    sleep 1200
    local curtime_seconds=$(LANG=C date +"%s")
    tmp=$(awk -v now=$curtime_seconds '(now-$1)>=12000 {print $2}' $BLOCKFILE)
    for i in $tmp; do
        sed -i "/$i/d" $BLOCKFILE
    done
  done
}

touch $BLOCKFILE
one_minute & 
one_pid="$!"
clear_blockip
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容