
UNIX Cafe | 第93回
PHPとBashで構築するWordPressリアルタイム監視システム
WordPressを運営していると、常に不安になるのが「不正アクセス」です。
ある朝、何気なく前日のサーバーログをチェックしていると、そこには、目を疑うような光景が・・・(@@;)
特定の海外IPアドレスから、wp-login.php や xmlrpc.php を執拗に狙った大量の脆弱性スキャナーの跡が、画面を埋め尽くしていたのです。
「これはちょっと放置できん・・・」(・_・、)
この「やられた感」が、今回のプロジェクトのきっかけになりました。「攻撃があったら、その瞬間にメールで知らせてくれる仕組みが欲しい」。そう思い立ち、シェルスクリプトを自作して監視を始めてみたものの、共有サーバー特有の「壁」にぶつかりました。今回は、その壁をどう乗り越え、自分だけの「お守り」を構築したのか、その記録を共有します。
1. 共有サーバーに立ちはだかる「ログの壁」
最初に作成したのは、サーバーの access_log を1分おきにスキャンするシンプルなBashスクリプトでした。しかし、テストをしても一向にメールが届きません。
原因を調べてみて分かったのは、エックスサーバー(共有プラン)の驚くべき仕様でした。
- 管理パネルのアクセスログ: システム側で集計された「結果」であり、ファイルではない。
- サーバー内のログファイル: リアルタイムに更新されず、1日に一度、まとめて書き出される。
つまり、「今この瞬間のアクセスログ」は、ユーザーが触れる場所には存在しないのです。これではリアルタイムの監視は不可能です。
2. UNIX流の解決策:無ければ作る「自作リアルタイムログ」
ここで諦めないのがUNIX流の考え方です。「サーバーがログをくれないなら、自分でログを吐き出す仕組みを作ればいい」という発想に切り替えます。
幸い、WordPressには必ず index.php という玄関口があります。ここに数行のPHPコードを仕込み、自分専用の「生きたログ」を生成することにしました。
index.php への追記(玄関にメモ帳を置く)
/public_html/index.php の先頭に以下のコードを追加します。
Xserver 用のPHPファイルです。ログファイルのパスは、お使いの環境によって異なります。
- サーバーIDの調べ方: 「エックスサーバーの管理パネルの一番上に表示されているIDです」
- フルパスの調べ方: 「
/home/サーバーID/ドメイン名/...という形になります」
// --- リアルタイムログ出力設定 ---
//サーバーIDとドメイン名をご自身のものに書き換えてください
$log_file = '/home/xs123456/pc-fan.net/script/my_access.log';
$log_data = sprintf(
"[%s] %s %s %s\n",
date('d/M/Y:H:i:s O'),
$_SERVER['REMOTE_ADDR'],
$_SERVER['REQUEST_METHOD'],
$_SERVER['REQUEST_URI']
);
file_put_contents($log_file, $log_data, FILE_APPEND | LOCK_EX);
// -----------------------------これで、誰かがサイトを訪れた瞬間に my_access.log へ足跡が刻まれるようになりました。
3. 門番となる監視スクリプトの設計
次に、この自作ログを監視するスクリプト scan_log.sh を作成します。ここで重要なのが、「しおり(ステート管理)」の概念です。
しおりを上手に使って二重通知を回避しないと、大量の通知が届いてメールボックスがパンクしてしまいます。そこで、last_line.txt というファイルに「前回何行目まで読んだか」を記録し、常に続きからスキャンする仕組みを導入します。
scan_log.sh のエッセンス
サーバーに設置するBashスクリプト
#!/bin/bash
# =================================================================
# UNIX Cafe ログ防衛システム (scan_log.sh)
# 役割: ログの新しい行だけをチェックし、攻撃を検知したらメール通知する
# =================================================================
# --- 設定エリア ---
# 1. サーバーIDとドメイン名をご自身のものに書き換えてください
LOG_FILE="/home/xs123456/pc-fan.net/log/access_log"
# 2. 状態保存ファイル(どこまで読んだか記録するしおり)
STATE_FILE="/home/xs123456/pc-fan.net/script/last_line.txt"
# 3. 通知先メールアドレスを書き換えてください
MAIL_TO="e-mail"
# 4. 検出キーワード(脆弱性スキャンの特徴的なパスやツール名)
PATTERNS="wp-login.php|xmlrpc.php|.env|sqlmap|nikto|acunetix|nessus"
# --- 処理開始 ---
# ログファイルが存在しない場合は、エラーを出さず終了
if [ ! -f "$LOG_FILE" ]; then
exit 0
fi
# 前回の最終行を取得(記録がなければ0行目から)
if [ -f "$STATE_FILE" ]; then
LAST_LINE=$(cat "$STATE_FILE")
# 数字以外が入っていた場合の対策
if ! [[ "$LAST_LINE" =~ ^[0-9]+$ ]]; then LAST_LINE=0; fi
else
LAST_LINE=0
fi
# 現在のログの総行数を取得
CURRENT_TOTAL_LINES=$(wc -l < "$LOG_FILE")
# ログがリセット(回転)されていたら、最初から読み直す
if [ "$CURRENT_TOTAL_LINES" -lt "$LAST_LINE" ]; then
LAST_LINE=0
fi
# 新しく増えた行だけを抽出してパターン検索
# tail で「前回読んだ次の行」から最後までを切り出し、grep で検索
NEW_HITS=$(tail -n +$((LAST_LINE + 1)) "$LOG_FILE" | grep -E "$PATTERNS")
# 攻撃が検出された場合のみメールを送信
if [ -n "$NEW_HITS" ]; then
# メールの本文作成
BODY=$(echo -e "脆弱性スキャナーと思われるアクセスを検出しました。\n\n【対象ログ】\n$LOG_FILE\n\n【検出内容】\n$NEW_HITS")
# メール送信(件名にはサーバー名を含める)
echo "$BODY" | mail -s "【重要】脆弱性スキャナ検知通知($(hostname))" "$MAIL_TO"
fi
# 今回読んだ最後の行数を保存(次回の開始位置にする)
echo "$CURRENT_TOTAL_LINES" > "$STATE_FILE"
exit 0
4. SSHとCronによる「24時間自動監視」
SSHでサーバーにログインし、パーミッションを調整(chmod 700)という数字を指定することで、所有者であるあなただけが実行・読み書きできるようになり、安全に動作させることができます。
実行コマンド:
chmod 700 /home/xs123456/pc-fan.net/script/scan_log.sh※作成したスクリプトを『プログラム』として動かすための設定です。自分だけが実行できるように権限を絞ります。
エックスサーバーのCron設定から設定を追加
- 実行間隔: 15分(通知の嵐を防ぎつつ、実用的な頻度)
- メンテナンス: 毎週日曜にログをリセット
不正アクセス監視(wp-login等への攻撃を検知してメール通知)
/bin/bash /home/xs123456/pc-fan.net/script/scan_log.sh > /dev/null 2>&1 | Cron設定一覧 | Cron追加設定 |
|---|---|
| 分 | 15 |
| 時間 | * |
| 日 | * |
| 月 | * |
| 曜日 | * |
| コマンド | /bin/bash /home/xs744164/pc-fan.net/script/scan_log.sh > /dev/null 2>&1 |
| メモ | 不正アクセス監視(wp-login等への攻撃を検知してメール通知) |
ログお掃除:毎週日曜に監視用ログを空にする
# ログ掃除としおりリセットのセット
cp /dev/null my_access.log && echo 0 > last_line.txt
| Cron設定一覧 | Cron追加設定 |
|---|---|
| 分 | * |
| 時間 | 3 |
| 日 | * |
| 月 | * |
| 曜日 | 0 |
| コマンド | cp /dev/null /home/xs744164/pc-fan.net/script/my_access.log && echo 0 > /home/xs744164/pc-fan.net/script/last_line.txt |
| メモ | ログお掃除:毎週日曜に監視用ログを空にする |
特に毎週の「お掃除コマンド」は重要です。ログを空にすると同時に、しおりも「0」に戻すセット処理をCronに仕込みました。
まとめ:自分だけの「お守り」を育てる
SSHでの操作やスクリプトの自作に挑んだことで、以前はブラックボックスだったサーバーの裏側が、手に取るように理解できるようになりました。
そんな時、サーバーから一通のメールが届きました。 「脆弱性スキャナーと思われるアクセスを検出しました」 ログを確認すると、/wp-login.php への不審なアクセスが正確に捉えられていました。
苦労して書き上げたスクリプトが、現実に自分のサイトを守ってくれている実感が湧き、深い安心感を覚えました。シンプルな道具を組み合わせ、仕組みを読み解きながら構築していく。この試行錯誤のプロセスこそが、まさに『UNIXの思想』そのものであると強く実感しています。」
さらに学びたいあなたへ
📘 用途ごとに選ぶ Linux のおすすめ本

