第1回では仕組みの動作原理とスクリプト全体を紹介し、 第2回では初期セットアップおよび cron による自動実行の設定方法をまとめました。
今回は、実際にこの仕組みを3か月ほど運用してみて分かってきた効果と、 万が一「ログインできない」といった問い合わせが発生した場合の、安全なリセット手順について整理しておきます。
運用結果
当初は、30分毎に cron でスクリプトを実行していました。
しかし実際に運用してみると、30分の間に 1000 回以上の POST /wp-login.php アクセスを行うIP が続出し、「もう少し早くブロックしたい…」という気持ちになります。
これはつまり、攻撃側から見ると30分で1000回超(1分あたり約30回以上)のパスワード試行が継続している状態であり、ログの肥大化やリソース消費の観点でも無視できないレベルです。
ブロック時には以下のような通知メールが送信されます。
条件: 過去 10 分間の POST /wp-login.php が 50 回以上
ブロック時間: 86400 秒(ipset: wplogin)
IP Count Site
----------------------------------------
203.0.113.55 1075 sample-site
---- debug files ----
last span log: /path/to/block/tmp/last-span.log
wp-login only: /path/to/block/tmp/last-wp-login.log
※ 上記の IP はドキュメント用のサンプル値です。実運用では実際のアクセス元IPに読み替えてください。
現在では、
- 計測時間:10分
- cron実行間隔:10分
- ブロック閾値:50回以上アクセスがあったらブロック
としています。
検出からブロックまでの時間を短縮することで、 攻撃トラフィックの早期遮断につながっています。
それでも、10分間で1000回を超えるアクセスしてくるIPも存在します。怖いですね。
気になるのは本スクリプトの実行によるサーバー負荷です。 本スクリプトを導入している EC2 インスタンスは t3.medium(2vCPU / 4GiB)という、さほど高性能とは言えない構成ですが、CloudWatch 上で CPU 使用率およびメモリ使用量を継続的にモニタリングしたところ、スクリプト実行タイミングにおいて明確な使用率の上昇は確認されませんでした。
Apache の access log を対象にした定期的な解析処理ではあるものの、 cron による10分毎の実行であれば、通常のWebサーバー運用に影響を及ぼすレベルの負荷は発生していないと考えられます。
なお、対象の WordPress サイトはもともとアクセス数が非常に多いわけではないため、 集計対象となるログの量も限定的である点には留意が必要です。 ログ解析の処理負荷はログファイルのサイズに依存するため、 トラフィック量の多いサイトでは実行間隔や閾値の調整を検討した方がよさそうですね。
ipset方式の正しいリセット方法
誤検知や問い合わせ対応時に、ブラックリストを安全にリセットする手順です。
全解除(安全)
ipset flush wplogin
wplogin セットに登録されているIPのみを削除します。
iptables 側のルールはそのまま維持されるため、安全に即時復旧が可能です。
特定IPのみ解除
ipset del wplogin 203.0.113.55
※ 203.0.113.55 は説明用のサンプルIPです。実際に解除したいIPへ置き換えて実行してください。
誤ってブロックされたIPのみをピンポイントで解除します。 他の攻撃元IPへの遮断状態には影響しません。
セット再作成
ipset destroy wplogin
ipset create wplogin hash:ip timeout 86400
セット自体を初期化したい場合の手順です。 iptables の参照先は同じままのため、ルールの再設定は不要です。
緊急時の正しい手順(現場向け)
「あ、誰かログインできない!」と言われた場合:
ipset list wplogin
ipset flush wplogin
まずは現在のブラックリスト内容を確認し、 必要に応じて即時に全解除することで復旧できます。
このように、ipset を利用した遮断方式では iptables のルールを変更することなく、安全かつ迅速な復旧が可能です。
まとめ
今回紹介した仕組みを実際に3か月ほど運用してみましたが、
wp-login.php へのブルートフォース攻撃に対して、ログの汚染や無駄なリクエストをかなり早い段階で遮断できるようになりました。
iptables のルールを増やすことなく、ipset による時限付きのブラックリスト登録だけで自動的にブロック/解除が行われるため、運用負荷もほとんどありません。
また、「ログインできない」といった問い合わせが発生した場合でも、
ipset flush による即時復旧が可能であり、現場対応の面でも扱いやすいと感じています。
マネージドな WAF と比較すると機能面では限定的ですが、 EC2 を直接公開している小規模構成においては、追加コストなしで導入できる軽量な防御策として十分に有用です。
WordPress をインターネットへ直接公開している環境では、 最低限の防御レイヤーとして導入しておいて損はない仕組みだと思います。