- Apacheのアクセスログから不審なエラーを選び
- アクセス元を調べ
- ログに出力する
というスクリプト。新サーバでも使っていましたが、終了の運びとなりました。
スクリプト内容
#!/bin/bash
# 変数定義
LOG_DIR="/var/log/bookstack"
ERROR_LOG="$LOG_DIR/bs_error.log"
COUNTRY_LIST="//home/hoge/script/config/country_list.csv"
OUTPUT_DIR="/home/hoge/script/log/blocked_list"
DATE=$(date +%Y%m%d)
LIST_FILE="$OUTPUT_DIR/ip.$DATE.csv"
RESULT_FILE="$OUTPUT_DIR/ip_list.$DATE.csv"
CRON_MODE=true # cron処理の場合はtrue、標準出力に残す場合はfalse
cd $LOG_DIR
# error.logからIPアドレスだけを抜き出します
awk 'match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) { print substr($0, RSTART, RLENGTH) }' $ERROR_LOG | sort > $LIST_FILE
# ip.YYYYMMDD.csvファイルがない場合にエラーを返します
if [ ! -f $LIST_FILE ]; then
echo "ファイル $LIST_FILE が存在しないので終了します。"
exit 1
fi
# 国コード,国の名前が書かれたcountry_list.csvがない場合にエラーを返します
if [ ! -f $COUNTRY_LIST ]; then
echo "ファイル $COUNTRY_LIST が存在しないので終了します。"
exit 1
fi
# IPアドレスに国名を付与したファイルを定義します。(ip_list.YYYYMMDD.csv)
> $RESULT_FILE
while read -r line; do
# IPアドレスを逆順に並び替えます。(例: 1.2.3.4 → 4.3.2.1)
ip_revers=$(echo "$line" | awk -F'.' '{print $4"."$3"."$2"."$1}')
# 並び替えたIPアドレスをcc.wariate.jpに並び替えて、国コードを抜き出します。(JP,CH,ESなど)
country_code=$(nslookup -type=TXT ${ip_revers}.cc.wariate.jp | grep '"' | awk -F'"' '{print $2}')
# 国コードをcountry_list.csvから参照して国名を抜き出します。
country_name=$(grep "$country_code" $COUNTRY_LIST | cut -d"," -f2)
# 標準出力に返す処理を行います。cron処理する場合はコメントアウトします。
if [ "$CRON_MODE" = false ]; then
echo "${line},${country_name}"
fi
# IPアドレス,国名の形式にして同ディレクトリのip_list.YYYYMMDD.csvに保存します
echo "${line},${country_name}" >> $RESULT_FILE
sleep 1
done < $LIST_FILE
# ip_list.csv.YYYYMMDDを読み込んで、IPアドレスをキー、国を値とする連想配列を作成します
declare -A countries
while read -r line; do
# CSVの1列目をIPアドレス、2列目を国とします
ip=$(echo $line | cut -d',' -f1)
country=$(echo $line | cut -d',' -f2)
# 連想配列に格納します
countries[$ip]=$country
done < $RESULT_FILE
# 結果を格納するための変数を定義します
result=""
# 連想配列を反復処理します
for ip in "${!countries[@]}"; do
# 各IPアドレスの件数を数えます
count=$(grep -c $ip $RESULT_FILE)
# 件数、IPアドレス、国をカンマ区切りで結合します
line="$count,$ip,${countries[$ip]}"
# 結果に追加します
result="$result\n$line"
done
# カウントした結果をcounted_ip.YYYYMMDD.csvに出力します
COUNTED_FILE="$OUTPUT_DIR/counted_ip.$DATE.csv"
echo -e $result > $COUNTED_FILE
# 最終結果をsorted_ip.$DATE.csvに出力します
SORTED_FILE="$OUTPUT_DIR/sorted_ip.$DATE.csv"
cat $COUNTED_FILE | LC_ALL=C sort -n -r > $SORTED_FILE
# 最終結果以外のログファイルを削除します
rm $LIST_FILE
rm $RESULT_FILE
rm $COUNTED_FILE
exit 0
このスクリプト、最初、それこそ日に10件もあればいい時代の頃に作ったモノで、Cron処理を行っていました。
しかし、アクセス数が(特にクローラーで)圧倒的になった今、このスクリプトは
- for / whileの多様
- 逐次nslookup
- さらに連想配列による処理
が重なり、ただのスワップ喰い虫となっていたのです。
- 今は別手段により不審なアクセスを弾いていること
- サーバの容量節約
のため、こちらは停止の運び。
2年以上にわたってよくぞここまで運用してくれたという感じです。
コメントを残す