概要

  • Apache
  • Mod_Security
  • テキストファイル

連携によるWeb防御『ONE OUTS』3回目。

ここでは応用編として、筆者の具体的なチューニングや追加設定などをご紹介します。

Cron設定

前項で説明したone_outs.sh。これは、筆者はCron化して自動運用しています。そのため、スクリプトは以下のように簡素化しています。

#!/bin/bash
#
# ONE OUTS System - IP Blacklist Auto-Generator (for cron)
#
# このスクリプトは、Tor出口ノードのリストとApacheのエラーログから
# 不審なIPアドレスを抽出し、ModSecurity用のブラックリストを自動生成します。
# cronなどで定期的に実行することを想定しています。
#

# === 変数の定義 ===

# --- 基本設定 ---
SCRIPT_BASE_DIR="/usr/local/scripts/security"
APACHE_LOG_DIR="/var/log/apache2"
MODSEC_BLACKLIST_FILE="/etc/modsecurity/ip-blacklist.txt"

# --- 除外設定 ---
EXCLUDE_IPS_FILE="${SCRIPT_BASE_DIR}/conf/exclude_ips.txt"

# --- 中間ファイル設定 ---
TOR_EXIT_LIST_RAW="${SCRIPT_BASE_DIR}/work/tor_exit_nodes_raw.txt"
TOR_EXIT_LIST_IPS="${SCRIPT_BASE_DIR}/work/tor_exit_nodes_ips.txt"
SUSPICIOUS_IPS_DAILY="${SCRIPT_BASE_DIR}/work/suspicious_ips_daily.txt"
SUSPICIOUS_IPS_ALL="${SCRIPT_BASE_DIR}/work/suspicious_ips_all.txt"

# === 処理の開始 ===

# 1. Tor出口ノードリストの取得
curl -s -o "${TOR_EXIT_LIST_RAW}" "https://check.torproject.org/exit-addresses"
if [ $? -ne 0 ]; then
    # エラーが発生した場合は syslog に記録
    logger "ONE OUTS Script Error: Failed to download Tor exit node list."
    exit 1
fi
awk '/^ExitAddress/ {print $2}' "${TOR_EXIT_LIST_RAW}" | sort -u > "${TOR_EXIT_LIST_IPS}"

# 2. Apacheエラーログからの不審IP抽出
grep "ModSecurity" "${APACHE_LOG_DIR}/error.log" | \
    grep -o -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | \
    sort -u > "${SUSPICIOUS_IPS_DAILY}"

touch "${SUSPICIOUS_IPS_ALL}"
cat "${SUSPICIOUS_IPS_ALL}" "${SUSPICIOUS_IPS_DAILY}" | sort -u > "${SUSPICIOUS_IPS_ALL}.tmp" && mv "${SUSPICIOUS_IPS_ALL}.tmp" "${SUSPICIOUS_IPS_ALL}"

# 3. ブラックリストの生成
# 変更前のチェックサムを保存
PREV_CHECKSUM=$(md5sum "${MODSEC_BLACKLIST_FILE}" | awk '{print $1}')

# Torリストと不審IPリストを結合して一時ファイルを作成
cat "${TOR_EXIT_LIST_IPS}" "${SUSPICIOUS_IPS_ALL}" | sort -u > "${MODSEC_BLACKLIST_FILE}.tmp"

# 4. 除外IPの削除
if [ -f "${EXCLUDE_IPS_FILE}" ]; then
    grep -v -f "${EXCLUDE_IPS_FILE}" "${MODSEC_BLACKLIST_FILE}.tmp" > "${MODSEC_BLACKLIST_FILE}"
else
    mv "${MODSEC_BLACKLIST_FILE}.tmp" "${MODSEC_BLACKLIST_FILE}"
fi
rm -f "${MODSEC_BLACKLIST_FILE}.tmp" # -f オプションでファイルがなくてもエラーにならないように

# 変更後のチェックサムを取得
POST_CHECKSUM=$(md5sum "${MODSEC_BLACKLIST_FILE}" | awk '{print $1}')

# 5. ファイルに変更があった場合のみApacheをリロード
if [ "${PREV_CHECKSUM}" != "${POST_CHECKSUM}" ]; then
    logger "ONE OUTS Script: Blacklist updated. Reloading Apache."
    systemctl reload apache2.service
fi

exit 0

これをcrontabで設定。(その際にはchmod +x one_outs.shを忘れないように)

# ONE OUTS
0 4 * * * sleep $(shuf -i 0-59 -n 1)m && /home/hoverbucks/script/server/one_outs.sh

として実行します。この、実行分をランダムにするのは、リストが更新されるというトリガーをつかみにくくするためです。

スローロリス攻撃への対処

この、ONE_OUTSの自動実行を行った頃、サーバのレスポンスが悪くなると言う状況を確認しました。以下のようなログを確認(アクセス元などはダミーに置き換えています)

# [クライアントIP] [タイムスタンプ]
# --- 攻撃検知 (1/2): カスタムルールが矛盾したConnectionヘッダーを検知 ---
[Mon Oct 20 11:30:05 2025] [security2:error] [client 198.51.100.201] ModSecurity: Warning. ... [id "10001"] [msg "[CUSTOM RULE] Contradictory Connection header, possible Slowloris probe."] [hostname "your-domain.com"] [uri "/search?query=some-long-query"]

# --- 攻撃検知 (2/2): CRSの標準ルールも同じ異常を検知 (スコア+3) ---
# data "keep-alive, close" の部分で、実際にどのようなデータが送られてきたかを確認できます。
[Mon Oct 20 11:30:05 2025] [security2:error] [client 198.51.100.201] ModSecurity: Warning. ... [id "920210"] [msg "Multiple/Conflicting Connection Header Data Found"] [data "keep-alive, close"] [severity "WARNING"] [hostname "your-domain.com"] [uri "/search?query=some-long-query"]

# --- 最終報告: 合計スコアとブロックに至らなかった状況を記録 ---
# この攻撃単体ではスコアが3のため、ブロックしきい値の5には達していません。
# 他の攻撃と組み合わさった場合に、ブロックの判断材料となります。
[Mon Oct 20 11:30:05 2025] [security2:error] [client 198.51.100.201] ModSecurity: Warning. ... [id "980170"] [msg "Anomaly Scores: (Inbound Scores: blocking=3, detection=3, ... threshold=5)"] [hostname "your-domain.com"] [uri "/search?query=some-long-query"]

これは典型的なスローロリス攻撃。

「Connectionヘッダーにkeep-aliveとcloseを同時に送信する」ことで、コネクションを矛盾させリソースを奪い最終的に枯渇を狙うというのは、攻撃者がCRS(Core Rule Set)に基づいた防御を行っていると確認した際/または単純な威力偵察の際によく使う手です。

漫画『ドリフターズ』に曰く

「こりゃ堕とせんと思ったら
その時から目的は変わるのよ
占領からいやがらせに変わる」

この、いやがらせ目的のため、自分のサーバのリソースが奪われるという状況は見過ごせません。以下のような処置を設けます。