H27.11、さらに修正しました。その4はこちら。
CentOSのフリーIDS、SWATCHのスクリプトを変更した。
前回の変更では、ログからうまくIPアドレスを抽出できなくて対処したが、1行中にIPアドレスが2つ出力されるようなパターンだとIPアドレスが拾えなかった。
主にメールログでこの現象があったが、2つマッチした場合、後半部分のIPアドレスがアクセス元である事が100%だった。そこで2つマッチした場合は2つめのIPアドレスを抽出するようswatch_action.shを書き換えた。
全文は以下。
#!/bin/bash
PATH=/bin:/sbin:/usr/bin
LANG=C
# ログを標準入力から取得
read LOG
# ログからIPアドレスを抽出
IPADDR=`echo $LOG | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'`
# IPアドレスが取得できなかった場合は対象ログを出力して終了
if [ "$IPADDR" = "" ]; then
echo "$LOG" >> /var/log/swatch/IPerr.log
exit
fi
# 1行に2つマッチした場合の抽出(後半部分のみを抽出)
matchaddr1=`echo $IPADDR | cut -d ' ' -f 1`
matchaddr2=`echo $IPADDR | cut -d ' ' -f 2`
if [ "$matchaddr2" ]; then
echo "`date` Complex matched: $matchaddr1 : $matchaddr2" >> /var/log/swatch/DMerr.log
IPADDR=$matchaddr2
echo "`date` Selected: $IPADDR" >> /var/log/swatch/DMerr.log
fi
# IPアドレスが取得できた場合の処理はここから
# IPアドレスをピリオドで分割
addr1=`echo $IPADDR|cut -d . -f 1`
addr2=`echo $IPADDR|cut -d . -f 2`
addr3=`echo $IPADDR|cut -d . -f 3`
addr4=`echo $IPADDR|cut -d . -f 4`
# IPアドレスがプライベートIPアドレスの場合は終了
if [ "$IPADDR" = "127.0.0.1" ]; then
exit
elif [ "$addr1" = "10" ]; then
exit
elif [ "$addr1" = "172" ] && [ $addr2 -ge 16 ] && [ $addr2 -le 31 ]; then
exit
elif [ "$addr1" = "192" ] && [ "$addr2" = "168" ]; then
exit
fi
# 不正アクセスログメッセージをIPアドレス別ログファイルに記録
echo "$LOG" >> /var/log/swatch/"$IPADDR"
# IPアドレス別ログファイルから累積不正アクセス数取得
cnt=`cat /var/log/swatch/$IPADDR | wc -l`
# 該当IPアドレスからの累積不正アクセス数が3以上の場合または
# 引数でlockと指定された場合アクセス規制
if [ $cnt -ge 3 ] || [ $# -eq 2 -a "$2" = "lock" ]; then
# 該当IPアドレスからのアクセスを拒否するルールを挿入
iptables -I INPUT -s $IPADDR -j DROP
# 上記ルールを24時間後に削除するスケジュールを登録
echo "iptables -D INPUT -s $IPADDR -j DROP > /dev/null 2>&1" | \
at now+24hour > /dev/null 2>&1
echo "`date` $IPADDR $cnt lock!"
else
echo "`date` $IPADDR $cnt"
fi
PATH=/bin:/sbin:/usr/bin
LANG=C
# ログを標準入力から取得
read LOG
# ログからIPアドレスを抽出
IPADDR=`echo $LOG | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'`
# IPアドレスが取得できなかった場合は対象ログを出力して終了
if [ "$IPADDR" = "" ]; then
echo "$LOG" >> /var/log/swatch/IPerr.log
exit
fi
# 1行に2つマッチした場合の抽出(後半部分のみを抽出)
matchaddr1=`echo $IPADDR | cut -d ' ' -f 1`
matchaddr2=`echo $IPADDR | cut -d ' ' -f 2`
if [ "$matchaddr2" ]; then
echo "`date` Complex matched: $matchaddr1 : $matchaddr2" >> /var/log/swatch/DMerr.log
IPADDR=$matchaddr2
echo "`date` Selected: $IPADDR" >> /var/log/swatch/DMerr.log
fi
# IPアドレスが取得できた場合の処理はここから
# IPアドレスをピリオドで分割
addr1=`echo $IPADDR|cut -d . -f 1`
addr2=`echo $IPADDR|cut -d . -f 2`
addr3=`echo $IPADDR|cut -d . -f 3`
addr4=`echo $IPADDR|cut -d . -f 4`
# IPアドレスがプライベートIPアドレスの場合は終了
if [ "$IPADDR" = "127.0.0.1" ]; then
exit
elif [ "$addr1" = "10" ]; then
exit
elif [ "$addr1" = "172" ] && [ $addr2 -ge 16 ] && [ $addr2 -le 31 ]; then
exit
elif [ "$addr1" = "192" ] && [ "$addr2" = "168" ]; then
exit
fi
# 不正アクセスログメッセージをIPアドレス別ログファイルに記録
echo "$LOG" >> /var/log/swatch/"$IPADDR"
# IPアドレス別ログファイルから累積不正アクセス数取得
cnt=`cat /var/log/swatch/$IPADDR | wc -l`
# 該当IPアドレスからの累積不正アクセス数が3以上の場合または
# 引数でlockと指定された場合アクセス規制
if [ $cnt -ge 3 ] || [ $# -eq 2 -a "$2" = "lock" ]; then
# 該当IPアドレスからのアクセスを拒否するルールを挿入
iptables -I INPUT -s $IPADDR -j DROP
# 上記ルールを24時間後に削除するスケジュールを登録
echo "iptables -D INPUT -s $IPADDR -j DROP > /dev/null 2>&1" | \
at now+24hour > /dev/null 2>&1
echo "`date` $IPADDR $cnt lock!"
else
echo "`date` $IPADDR $cnt"
fi
IPアドレスそのものが拾えなかった場合、IPerr.logにその行が出力される。また、2つIPアドレスがマッチした場合、DMerr.logに2つのIPと選択したIPが出力される。
これでしばらくは大丈夫だろう・・・。