前回は、iptables と ipset を組み合わせて wp-login.php への執拗なアクセス元を自動的に遮断する仕組みと、そのスクリプト全体を紹介しました。
今回は、そのスクリプトを実際のサーバー上で動作させるために必要な初期セットアップ手順と、cron を用いた定期実行の設定方法についてまとめていきます。
初期セットアップ(最初に1回だけ)
まずは、IPアドレスの集合を管理するためのツールである ipset をインストールします。
この仕組みでは、遮断対象IPの管理を iptables ではなく ipset 側で行うため、必須のコンポーネントとなります。
dnf install -y ipset
whitelist(管理者IPなど)
誤検知によって自分自身のログインがブロックされる事態を防ぐため、 管理者IPや信頼できるネットワークをホワイトリストとして登録しておきます。
CIDR 指定を行うため、hash:net を使用します。
※ 以下の IP/CIDR はドキュメント用のサンプル値です。実運用では、必ず自分の管理用グローバルIPや社内ネットワークに置き換えてください。
ipset create wplogin_whitelist hash:net
ipset add wplogin_whitelist 203.0.113.10/32
ipset add wplogin_whitelist 198.51.100.0/24
blacklist(攻撃元IP)
攻撃元IPを登録するためのブラックリスト用セットを作成します。
ここでは timeout を指定しておくことで、
一定時間経過後に自動的にブロックが解除されるようになります。
ipset create wplogin hash:ip timeout 86400
iptables 設定(順序重要)
iptables 側には、ipset を参照するルールを1行ずつ追加します。
ホワイトリスト → ブラックリストの順で評価されるよう、 ルールの挿入順序が重要になります。
iptables -I INPUT 1 -m set --match-set wplogin_whitelist src -j ACCEPT
iptables -I INPUT 2 -p tcp -m multiport --dports 80,443 -m set --match-set wplogin src -j DROP
実行
スクリプトに実行権限を付与し、まずは手動で動作確認を行います。 ログの出力内容を確認することで、想定通りに検出処理が行われているかをチェックできます。
chmod 700 /path/to/block/wp-login-blocker.sh
bash -x /path/to/block/wp-login-blocker.sh
※ 本記事中の /path/to/... は匿名化したプレースホルダです。実際の設置先パスに合わせて読み替えてください。
cron 登録
問題なく動作することを確認したら、cron に登録して定期的に実行します。 これにより、ログ解析〜ブラックリスト登録の一連の処理が自動化されます。
# /etc/cron.d/cron-file
# ブロックせずに検知だけを行う場合
*/30 * * * * root /path/to/block/wp-login-blocker.sh --no-block >> /path/to/block/tmp/wp-login-blocker.log 2>&1
# ブロックする場合
*/30 * * * * root /path/to/block/wp-login-blocker.sh >> /path/to/block/tmp/wp-login-blocker.log 2>&1
確認ポイント
以下のファイルやコマンド出力を確認し、 検出およびブロック処理が正常に行われていることをチェックします。
/path/to/block/tmp/hits.raw/path/to/block/tmp/hits.tsvipset list wplogin- 通知メール
運用上の重要ポイント
ブロック解除について
ブロックは完全に自動で解除されます。
- timeout 経過後に ipset から削除
- iptables ルールは維持
解除処理用のスクリプトを別途用意する必要はありません。
再起動対策
ipset のセット内容は、サーバー再起動時に消去されます。
ただし、wp-login 攻撃は継続的に発生するため、 再起動後も再検知されることを前提に、復元処理を行わない運用も一般的です。
誤検知対策
誤検知を減らしたい場合は、以下のような調整を検討します。
- ステータスコード 200 / 302 のみ対象にする
- 閾値を 30〜50 に引き上げる
次回は、実際に本仕組みを運用してみた結果と、 「ログインできない」といった問い合わせが発生した際のトラブルシュート方法について紹介します。