2026年5月20日

2026年5月20日

WordPressのCloudflare WAFを設定する方法

はじめに

Cloudflare WAFはWordPressサイトへのリクエストをエッジサーバーでフィルタリングし、攻撃がオリジンサーバーに到達する前にブロックします。無料プランでも基本的なWAF機能が利用でき、有料プランではWordPress専用のマネージドルールセットを利用できます。

症状・原因

  • サーバー側でのWAF設定(ModSecurity等)が難しい共有ホスティングを使っている
  • Cloudflareを既に導入しているがWAFの設定ができていない
  • 特定の攻撃パターン(wp-login.phpブルートフォース等)をサーバーの手前でブロックしたい
  • IPベースでなくリクエスト内容でフィルタリングしたい

解決手順

ステップ1:Cloudflare の現在のセキュリティ設定を確認する

# Cloudflare API でゾーン情報を確認
# ZONE_ID と API_TOKEN は Cloudflare ダッシュボードで取得

ZONE_ID="your_zone_id"
API_TOKEN="your_api_token"

# 現在のWAF設定を確認
curl -s -X GET \
    "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/firewall/waf/packages" \
    -H "Authorization: Bearer ${API_TOKEN}" \
    -H "Content-Type: application/json" | python3 -m json.tool

# セキュリティレベルを確認
curl -s -X GET \
    "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/settings/security_level" \
    -H "Authorization: Bearer ${API_TOKEN}" | python3 -m json.tool

ステップ2:Cloudflare カスタムWAFルールを設定する

# Cloudflare ダッシュボード → Security → WAF → Custom rules で設定

# ① wp-login.php へのブルートフォースを制限(GUIで設定)
# ルール名: Protect WordPress Login
# 条件: URI Path equals "/wp-login.php"
#       AND Request Method equals "POST"
# アクション: Managed Challenge(人間確認)
# 注意: 自分のIPはBypassルールで除外する

# ② xmlrpc.php を完全ブロック
# ルール名: Block xmlrpc.php
# 条件: URI Path equals "/xmlrpc.php"
# アクション: Block

# ③ 管理画面を自社IPのみ許可
# ルール名: Protect wp-admin
# 条件: URI Path contains "/wp-admin"
#       AND NOT IP Source Address in {your.ip.address}
# アクション: Block

# Cloudflare API でカスタムルールを作成
curl -s -X POST \
    "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/firewall/rules" \
    -H "Authorization: Bearer ${API_TOKEN}" \
    -H "Content-Type: application/json" \
    -d '{
        "filter": {
            "expression": "(http.request.uri.path eq \"/xmlrpc.php\")",
            "paused": false
        },
        "action": "block",
        "description": "Block xmlrpc.php"
    }'

ステップ3:WordPress マネージドルールセットを有効化する(有料プラン)

# Cloudflare Pro以上: WordPress 専用マネージドルールセットを有効化
# ダッシュボード → Security → WAF → Managed rules
# → Cloudflare Managed Ruleset を ON
# → Cloudflare WordPress Ruleset を ON

# API で WordPress マネージドルールセットを有効化
curl -s -X PUT \
    "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/firewall/waf/packages/PACKAGE_ID/groups/GROUP_ID" \
    -H "Authorization: Bearer ${API_TOKEN}" \
    -H "Content-Type: application/json" \
    -d '{"mode": "on"}'

# マネージドルールが含む保護:
# - WordPress コアの既知の脆弱性
# - WooCommerce の脆弱性
# - 人気プラグインの CVE
# - ブルートフォース対策

ステップ4:レート制限ルールを設定する

# Cloudflare ダッシュボード → Security → WAF → Rate limiting rules

# ① wp-login.php: 1分間に5回超えたらチャレンジ
# ルール名: Login Rate Limit
# 条件: URI Path equals "/wp-login.php"
# 特性: IP (クライアントIPでカウント)
# 閾値: 5リクエスト / 60秒
# アクション: Managed Challenge

# ② wp-json API: DDoS対策
# ルール名: REST API Rate Limit
# 条件: URI Path starts with "/wp-json"
# 閾値: 100リクエスト / 60秒
# アクション: Block

# ③ サイト全体: 大量リクエストをブロック
# 閾値: 1000リクエスト / 60秒
# アクション: Block

# API でレート制限を設定
curl -s -X POST \
    "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/rate_limits" \
    -H "Authorization: Bearer ${API_TOKEN}" \
    -H "Content-Type: application/json" \
    -d '{
        "match": {
            "request": {"url_pattern": "*/wp-login.php*", "methods": ["POST"]}
        },
        "threshold": 5,
        "period": 60,
        "action": {"mode": "challenge", "timeout": 600}
    }'

ステップ5:WordPress と Cloudflare を統合する

// functions.php: Cloudflare の本物のIPを取得

add_action('init', function(): void {
    // Cloudflare から送られる本物のクライアントIP
    if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
        $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
    }
}, 1);

// Cloudflare の IP レンジかどうかを確認
function is_cloudflare_ip(string $ip): bool {
    $cloudflare_ranges = [
        '103.21.244.0/22', '103.22.200.0/22', '103.31.4.0/22',
        '104.16.0.0/13', '104.24.0.0/14', '108.162.192.0/18',
        '131.0.72.0/22', '141.101.64.0/18', '162.158.0.0/15',
        '172.64.0.0/13', '173.245.48.0/20', '188.114.96.0/20',
        '190.93.240.0/20', '197.234.240.0/22', '198.41.128.0/17',
    ];

    foreach ($cloudflare_ranges as $range) {
        [$subnet, $bits] = explode('/', $range);
        $ip_long = ip2long($ip);
        $subnet_long = ip2long($subnet);
        $mask = -1 << (32 - (int)$bits);
        if (($ip_long & $mask) === ($subnet_long & $mask)) {
            return true;
        }
    }
    return false;
}
# Cloudflare が有効かどうかを確認
curl -sI https://example.com/ | grep -i "cf-ray\|server: cloudflare"
# CF-Ray ヘッダーが返れば Cloudflare 経由

# ファイアウォールのイベントログを確認
# Cloudflare ダッシュボード → Security → Events
# ブロック・チャレンジされたリクエストを確認

注意事項

  • Cloudflareの無料プランではカスタムWAFルールが5つまでです。最も重要なxmlrpc.phpのブロックとwp-login.phpのレート制限を優先してください
  • 管理画面(wp-admin)をIPでブロックする場合、外出先から管理できなくなります。完全IPブロックより「Managed Challenge」(CAPTCHA)アクションの方が運用しやすい場合があります
  • Cloudflareの「I'm Under Attack!」モードは全訪問者にJavaScriptチャレンジを表示するため、攻撃を受けていない通常時は使用しないでください。レート制限とWAFルールで段階的に対応してください

まとめ

Cloudflare WAFの設定は①CF-Rayヘッダー確認でCloudflare経由を確認、②カスタムルールでxmlrpc.phpをBlock・wp-login.phpにManaged Challenge、③WordPress管理画面を自社IPのみ許可、④レート制限でwp-login.phpは5回/分・wp-jsonは100回/分、⑤HTTP_CF_CONNECTING_IPでPHP側に本物のクライアントIPを渡します。

お気軽にご相談ください

お見積りへ お問い合わせへ