?????????這段腳本的作用是通過分析 Nginx 的訪問日志,檢測異常的 IP 地址,并使用 iptables
封禁這些 IP。
#!/bin/bash# 配置變量
LOG_FILE="/usr/local/nginx/logs/access.log"
THRESHOLD=10
DROP_LOG_FILE="/tmp/drop_ip.log"
DATE=$(date +"%d/%b/%Y:%H:%M")# 檢測異常 IP
ABNORMAL_IP=$(tail -n5000 "$LOG_FILE" | grep "$DATE" | awk '{a[$1]++} END {for(i in a) if(a[i]>'$THRESHOLD') print i}')# 封禁異常 IP
for IP in $ABNORMAL_IP; do# 檢查 IP 是否已經被封禁if ! iptables -C INPUT -s "$IP" -j DROP &> /dev/null; then# 封禁 IPiptables -I INPUT -s "$IP" -j DROPecho "$(date +'%F_%T') $IP - Access count exceeded threshold ($THRESHOLD)" >> "$DROP_LOG_FILE"fi
done
以下是腳本的詳細解析和一些需要注意的地方:
腳本功能
配置變量:
LOG_FILE
:指定 Nginx 的訪問日志文件路徑。THRESHOLD
:設置訪問次數的閾值,超過此值的 IP 將被認定為異常。DROP_LOG_FILE
:記錄被封禁 IP 的日志文件路徑。DATE
:獲取當前時間,格式為日/月/年:時:分
,用于篩選日志中當前時間的記錄。
檢測異常 IP:
使用
tail -n5000 "$LOG_FILE"
獲取日志文件的最后 5000 行。使用
grep "$DATE"
篩選出當前時間的記錄。使用
awk
統計每個 IP 的訪問次數,并篩選出訪問次數超過閾值的 IP。
封禁異常 IP:
遍歷檢測到的異常 IP。
使用
iptables -C INPUT -s "$IP" -j DROP
檢查該 IP 是否已經被封禁。如果未被封禁,則使用
iptables -I INPUT -s "$IP" -j DROP
將其封禁,并將封禁信息記錄到DROP_LOG_FILE
中。
注意事項
日志格式依賴:
腳本假設 Nginx 的日志格式是標準的 Combined Log Format,其中第一個字段是 IP 地址。如果日志格式不同,需要調整
awk
的字段索引。
時間格式匹配:
DATE
的格式需要與 Nginx 日志中的時間格式完全匹配。如果日志中的時間格式不同(例如包含毫秒或時區信息),腳本可能無法正確篩選記錄。
權限問題:
腳本需要以 root 用戶運行,因為
iptables
命令需要管理員權限。
性能問題:
如果日志文件非常大,
tail -n5000
和grep
操作可能會消耗較多資源。可以考慮優化日志處理方式,例如定期清理日志或使用更高效的數據處理工具。
誤封風險:
腳本簡單地根據訪問次數封禁 IP,可能會誤封正常用戶(例如爬蟲或高頻訪問的合法用戶)。建議結合其他檢測機制(如訪問頻率、請求類型等)來提高準確性。
日志記錄:
封禁日志記錄到
/tmp/drop_ip.log
,但/tmp
目錄可能會被定期清理。建議將日志存儲到更安全的路徑,例如/var/log
。
改進建議
日志格式檢查:在腳本開頭檢查日志文件是否存在以及是否符合預期格式。
動態閾值:根據流量情況動態調整閾值,而不是固定值。
白名單機制:維護一個白名單,避免誤封重要 IP。
持久化封禁規則:使用
iptables-save
和iptables-restore
保存和恢復規則,避免系統重啟后規則丟失。日志清理:定期清理封禁日志文件,避免文件過大。