セキュリティ

WAF ルールを自分で書く — 既定のまま使わずに、実際の攻撃に合わせる

WAF は有効にしただけでも一定の効果がありますが、
自分のサイトに実際に来ている攻撃に合わせると、精度が大きく上がります。

まずログを見る

推測でルールを書かず、実際のアクセスログを集計します。

# 404 が多いパス = 攻撃の試行
awk '$9==404 {print $7}' access.log | sort | uniq -c | sort -rn | head -30

公開直後のサイトでも、次のようなリクエストがすぐ並びます。

/.env
/wp-login.php
/.git/config
/phpmyadmin/
/actuator/health

存在しないパスへの執拗なアクセスは、すべて探索行為です。

存在しないものへのアクセスをブロックする

自サイトが PHP を使っていないなら、.php へのアクセスは100%攻撃です。

(http.request.uri.path contains ".php")
or (http.request.uri.path contains "/wp-")
or (http.request.uri.path contains "/.git")
or (http.request.uri.path contains "/.env")

誤検知の心配が無いため、迷わずブロックできます。
これだけで不正アクセスのログが大幅に減ります。

管理画面を国とIPで絞る

(http.request.uri.path contains "/dashboard"
 and ip.geoip.country ne "JP")

国内からしか運用しないなら、これで大半の総当たりが届かなくなります。
固定IPがあるなら、IPで絞るほうがさらに確実です。

ログイン試行にレート制限をかける

パス: /login/
メソッド: POST
しきい値: 10リクエスト / 1分 / 同一IP
アクション: 1時間ブロック

アプリ側の制限と二重にかけるのが要点です。
WAF 側で止まれば、アプリまで到達しません。

誤検知を確認してからブロックする

いきなりブロックにすると、正規のユーザーを弾く危険があります。

段階1: ログのみ(1週間)  → 何が引っかかるか確認
段階2: チャレンジ表示     → 疑わしいものに確認を求める
段階3: ブロック

特に検索エンジンのクローラーを弾かないよう注意します。
User-Agent だけでの判定は偽装されるので、正規のクローラーは
IPの逆引きで検証する仕組みを使います。

オリジンへの直接アクセスを塞ぐ

WAF を通さずにサーバーへ直接アクセスされたら意味がありません。
オリジン側でも WAF の IP レンジ以外を拒否します。

ufw default deny incoming
for ip in $(curl -s https://www.cloudflare.com/ips-v4); do
    ufw allow from $ip to any port 443 proto tcp
done

これを忘れると、実IPが判明した時点で WAF が迂回されます。

効果を測る

導入前: 1日あたりの不正アクセス試行 約2,400件
導入後: オリジンに到達した試行      約30件

ブロック数の推移を記録しておくと、ルールの効果が判断できます。

まとめ

  • 推測せず、自分のログから実際の攻撃を見る
  • 使っていない技術のパス(.php /wp- .env)は迷わずブロック
  • 管理画面は国・IPで絞る
  • ログイン試行のレート制限はWAFとアプリで二重に
  • ログのみ → チャレンジ → ブロックの順で慎重に上げる
  • オリジンへの直接アクセスを必ず塞ぐ