centos iptables 分析自动封锁
2018-07-07 本文已影响22人
9682f4e55d71
#!/bin/sh
# desc: 检查登陆页面 单个IP的访问次数, 加参数 -k 可直接加入到防火墙
# author: dbquan
# -_- 写了很多,其实就是一行命令搞定: tail -n 10000 /path_to/nginx-access.log | awk -F '|' '{if($7 ~ "?main_page=login") {print $1}}' | sort | uniq -c | sort -n -k 1 -r | head -n 10 | awk '{if($1>100) {print $0}}' | awk '{print $2}' | xargs -I {} echo "iptables -I INPUT 17 -s {}/24 -j DROP"
CHECK_ACCESS_FILE='/path_to/nginx-access.log' # 日志文件
CHECK_ACCESS_PAGE='?main_page=login' # 需要检查的页面
CHECK_ACCESS_TIMES=100 # 访问次数, 大于该次数则加入到防火墙
CHECK_LOG_TAIL_LINE_NUMBERS=10000 # 检查的日志行数
CHECK_KILL_LINES=25 # 排名前25的会被过滤出来
DATA_FROM='file' # file or netstat
IPT_INSERT_POSITION=17
ISKILL='N'
#BASE_PATH=$(cd `dirname $0`; pwd)
BASE_PATH="/data/bin/ip_check"
TMP_DATA_FILE="$BASE_PATH/tmp_data"
LOG_DIR="$BASE_PATH/logs"
usage()
{
echo "Usage: $0 [OPTION]"
echo " Show head count and ip information."
echo " -k Add matched ip to iptables."
}
get_count_ip()
{
echo "start to get ip and count from $DATA_FROM ..."
if [ "$DATA_FROM" = "file" ]; then
tail -n $CHECK_LOG_TAIL_LINE_NUMBERS $CHECK_ACCESS_FILE | \
awk -F '|' -v CHECK_ACCESS_PAGE="$CHECK_ACCESS_PAGE" '{if($7 ~ CHECK_ACCESS_PAGE) {print $1}}' | \
sort | uniq -c | sort -n -k 1 -r | \
head -n "$CHECK_KILL_LINES" > "$TMP_DATA_FILE"
else
# 已经建立的链接
netstat -an | grep ESTABLISHED | awk '{print $5}' | awk -F ':' '{print $1}' | grep -v -E '192.168|127.0' | sort | uniq -c | sort -rn -k 1 | head > "$TMP_DATA_FILE"
fi
if [ $? -eq 0 ]; then
echo " count ip($CHECK_ACCESS_PAGE)"
cat "$TMP_DATA_FILE"
else
echo "ERROR, exit $?"
exit $?
fi
}
add_to_iptables()
{
if [ "$ISKILL" = "Y" ]; then
echo -e '\nstart to add to iptables ...'
while read line
do
local count=`echo $line | awk '{print $1}'`
local ip=`echo $line | awk '{print $2}'`
local datetime=`date "+%Y%m%d %H:%M:%S"`
local cmd="iptables -I INPUT $IPT_INSERT_POSITION -s $ip/24 -j DROP -m comment --comment \"$datetime|$ip|$count\""
# 避免加入重复的记录
if [ `iptables -nL --line-numbers | grep "$ip" > /dev/null 2>&1 ; echo $?` -eq 1 ]; then
if [ $count -gt $CHECK_ACCESS_TIMES ]; then
eval $cmd
if [ $? -eq 0 ]; then
echo "$cmd [OK]"
[ -d "$LOG_DIR" ] || mkdir "$LOG_DIR" || "WARN: mkdir $LOG_DIR fail"
echo "[`date "+%Y%m%d %H:%M:%S"]` $cmd" >> "$LOG_DIR/`date "+%Y%m%d"`.log"
else
echo "ERROR, exit $?"
exit $?
fi
else
echo " << access times less than $CHECK_ACCESS_TIMES: $ip|$count"
fi
else
echo " >> $ip already in iptables"
fi
done < $TMP_DATA_FILE
fi
}
case "$1" in
"-k")
ISKILL='Y'
;;
"")
;;
*)
usage
exit
;;
esac
get_count_ip && \
add_to_iptables
if [ $? -eq 0 ]; then
echo "done"
else
echo "fail!"
fi