Penjelasan Mendalam

Aturan Cloudflare WAF yang Memicu CAPTCHA Challenge

Web Application Firewall (WAF) Cloudflare memungkinkan operator situs membuat aturan yang memicu CAPTCHA challenge berdasarkan atribut request tertentu — alamat IP, negara, path URL, bot score, header, atau kombinasi apapun. Memahami aturan mana yang memicu challenge membantu mendiagnosis kenapa Anda melihat CAPTCHA dan memilih pendekatan yang tepat untuk menanganinya.


Tindakan Aturan WAF yang Menghasilkan CAPTCHA

Aturan Cloudflare WAF mendukung beberapa tindakan. Tiga di antaranya menghadirkan challenge yang dapat di-solve:

Tindakan WAF Apa yang terjadi Status HTTP Metode CaptchaAI
Managed Challenge Cloudflare memutuskan: invisible challenge, Turnstile, atau JS 503 turnstile
JS Challenge Halaman JavaScript challenge 5 detik 503 cloudflare_challenge
Interactive Challenge CAPTCHA tradisional (legacy, deprecated) 403 turnstile
Block Hard 403, tidak ada challenge 403 N/A (tidak bisa di-solve)
Allow Lewati, tanpa pemeriksaan 200 N/A
Skip Lewati aturan WAF lainnya 200 N/A
Log Catat event, tidak ada tindakan 200 N/A

Managed Challenge (paling umum)

Managed Challenge adalah tindakan yang direkomendasikan Cloudflare. Ini secara adaptif menentukan jenis challenge per pengunjung:

WAF rule matches → Managed Challenge triggered
    ↓
Cloudflare evaluates visitor:
  ├─ Low risk → Invisible pass (no visible challenge)
  ├─ Medium risk → Turnstile widget (click to verify)
  └─ High risk → JavaScript challenge page
    ↓
Successful → qa_validation_cookie cookie issued

Pola Aturan WAF yang Umum

Operator situs membuat aturan WAF menggunakan bahasa ekspresi Cloudflare. Berikut pola yang paling sering memicu CAPTCHA untuk traffic otomatis:

Aturan Bot Score

# Challenge traffic with low bot scores
(cf.bot_management.score lt 30)
→ Action: Managed Challenge

# Challenge non-verified bots
(cf.bot_management.score lt 50 and not cf.bot_management.verified_bot)
→ Action: JS Challenge

Aturan bot score adalah pemicu paling umum untuk alat otomatisasi. Solver CaptchaAI mendapat skor setingkat manusia karena menggunakan browser nyata.

Aturan Berbasis Negara

# Challenge traffic from specific countries
(ip.geoip.country in {"CN" "RU" "VN" "IN"})
→ Action: Managed Challenge

# Block specific regions entirely
(ip.geoip.country eq "XX")
→ Action: Block

Aturan Berbasis Path

# Challenge login page access
(http.request.uri.path eq "/login" or http.request.uri.path eq "/signup")
→ Action: Managed Challenge

# Challenge API endpoints
(http.request.uri.path contains "/api/")
→ Action: JS Challenge

Aturan Berbasis Rate

# Challenge after high request rate
(cf.threat_score gt 10 and http.request.uri.path contains "/search")
→ Action: Managed Challenge

Aturan Berbasis Header

# Challenge requests with no Accept-Language header
(not http.request.headers["accept-language"])
→ Action: JS Challenge

# Challenge requests with suspicious UA
(http.user_agent contains "python" or http.user_agent contains "curl")
→ Action: Managed Challenge

Aturan Majemuk

# Multiple conditions
(cf.bot_management.score lt 30
 and http.request.uri.path contains "/api/"
 and ip.geoip.country ne "US")
→ Action: JS Challenge

Mengidentifikasi Aturan Mana yang Dipicu

Saat tantangan CAPTCHA muncul, Anda dapat mengidentifikasi aturan pemicu dari responsnya:

Dari Header HTTP

import requests

def check_cloudflare_rule_info(url):
    """Extract WAF rule information from Cloudflare challenge response."""
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 Chrome/120.0.0.0",
        "Accept": "text/html,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
    }

    response = requests.get(url, headers=headers, timeout=15, allow_redirects=False)

    info = {
        "status": response.status_code,
        "cf_ray": response.headers.get("cf-ray", ""),
        "cf_cache_status": response.headers.get("cf-cache-status", ""),
        "server": response.headers.get("server", ""),
    }

    # Challenge-specific info
    html = response.text

    if response.status_code == 503:
        if "jschl" in html:
            info["challenge_type"] = "JS Challenge (IUAM or WAF rule)"
        elif "challenge-platform" in html:
            info["challenge_type"] = "Managed Challenge"
        elif "cf-turnstile" in html:
            info["challenge_type"] = "Turnstile (Managed Challenge)"

    elif response.status_code == 403:
        if "cf-ray" in str(response.headers):
            info["challenge_type"] = "WAF Block (no challenge)"
        else:
            info["challenge_type"] = "Origin 403 (not Cloudflare)"

    return info

Dari ID Cloudflare Ray

Setiap respons Cloudflare menyertakan header cf-ray. Operator situs dapat menggunakan Ray ID ini di dashboard Cloudflare (Keamanan > Events) untuk melihat aturan mana yang dipicu dan tindakan apa yang diambil.


Solve Challenge yang Dipicu WAF

Strategi berdasarkan jenis challenge

import requests
import time

API_KEY = "YOUR_API_KEY"

def solve_cloudflare_challenge(url, challenge_type):
    """Solve Cloudflare challenge based on WAF rule action."""

    if challenge_type == "managed_challenge":
        # Managed Challenge typically renders as Turnstile
        method = "turnstile"
        sitekey = extract_turnstile_sitekey(url)
    elif challenge_type == "js_challenge":
        # JavaScript Challenge page
        method = "cloudflare_challenge"
        sitekey = "managed"
    else:
        raise ValueError(f"Unknown challenge type: {challenge_type}")

    submit = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": method,
        "sitekey": sitekey,
        "pageurl": url,
        "json": 1,
    })

    task_id = submit.json()["request"]

    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": 1,
        }).json()

        if result.get("status") == 1:
            return result["request"]

    raise TimeoutError("Challenge solve timed out")


def extract_turnstile_sitekey(url):
    """Fetch page and extract Turnstile sitekey."""
    import re
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 Chrome/120.0.0.0",
    }
    response = requests.get(url, headers=headers, timeout=15)
    match = re.search(r'data-sitekey=["\']([0-9x][A-Za-z0-9_-]+)["\']', response.text)
    return match.group(1) if match else None

Node.js

const axios = require("axios");

const API_KEY = "YOUR_API_KEY";

async function solveWAFChallenge(url, challengeType) {
  const method =
    challengeType === "js_challenge" ? "cloudflare_challenge" : "turnstile";
  const sitekey =
    challengeType === "js_challenge" ? "managed" : await extractSitekey(url);

  const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
    params: {
      key: API_KEY,
      method,
      sitekey,
      pageurl: url,
      json: 1,
    },
  });

  const taskId = submit.data.request;

  for (let i = 0; i < 60; i++) {
    await new Promise((r) => setTimeout(r, 5000));

    const result = await axios.get("https://ocr.captchaai.com/res.php", {
      params: { key: API_KEY, action: "get", id: taskId, json: 1 },
    });

    if (result.data.status === 1) {
      return result.data.request;
    }
  }

  throw new Error("Challenge solve timed out");
}

async function extractSitekey(url) {
  const response = await axios.get(url, {
    headers: {
      "User-Agent": "Mozilla/5.0 Chrome/120.0.0.0",
    },
  });
  const match = response.data.match(/data-sitekey=["']([0-9x][A-Za-z0-9_-]+)["']/);
  return match ? match[1] : null;
}

Perubahan Aturan WAF dan Dampaknya

Operator situs sering menyesuaikan aturan WAF. Perubahan ini memengaruhi otomatisasi:

Perubahan Efek pada otomatisasi Cara mendeteksi
Aturan ditambahkan Challenge baru muncul pada path yang sebelumnya berhasil Pantau perubahan status 503/403
Aturan dihapus Challenge menghilang 200 di mana sebelumnya 503
Tindakan ditingkatkan (Block → Managed) Challenge yang bisa di-solve menjadi hard block 403 bukan 503
Tindakan dilonggarkan (Block → Managed) Hard block menjadi challenge yang bisa di-solve 503 dengan halaman challenge
Threshold diubah (bot score 30 → 50) Lebih banyak request di-challenge Frekuensi challenge meningkat
Cakupan path diubah URL berbeda terpengaruh Path baru mengembalikan challenge

Strategi Pemantauan

import requests
import time

def monitor_cloudflare_protection(urls, interval=3600):
    """Monitor protection changes across URLs."""
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 Chrome/120.0.0.0",
        "Accept": "text/html,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
    }

    last_status = {}

    while True:
        for url in urls:
            try:
                response = requests.get(
                    url, headers=headers, timeout=15, allow_redirects=False
                )
                status = response.status_code
                has_challenge = status == 503 or "cf-turnstile" in response.text

                current = {"status": status, "challenge": has_challenge}
                previous = last_status.get(url)

                if previous and current != previous:
                    print(f"[CHANGE] {url}")
                    print(f"  Before: {previous}")
                    print(f"  After:  {current}")

                last_status[url] = current

            except requests.RequestException as e:
                print(f"[ERROR] {url}: {e}")

        time.sleep(interval)

Pemecahan Masalah

Gejala Kemungkinan Aturan WAF Solusi
Challenge hanya di /login Aturan berbasis path Solve challenge untuk path tersebut
Challenge hanya dari IP datacenter Bot score atau aturan reputasi IP Gunakan egress jaringan yang diotorisasi atau solve challenge
Challenge berbeda per negara Aturan berbasis negara Gunakan proxy di negara yang diizinkan atau solve
Challenge setelah N request Aturan berbasis rate Kurangi rate request atau solve setiap challenge
Challenge selalu JS (bukan Turnstile) Tindakan JS Challenge (bukan Managed) Gunakan metode cloudflare_challenge
403 tanpa challenge Tindakan Block (tidak bisa di-solve) Ubah IP, header, atau pola request

Pertanyaan yang sering diajukan

Bisakah saya melihat aturan WAF yang digunakan situs?

Tidak. Aturan WAF bersifat privat bagi operator situs. Anda hanya dapat menyimpulkan aturan dari perilaku — path mana yang memicu challenge, dari IP mana, dan jenis challenge apa yang muncul.

Apakah aturan WAF berlaku untuk semua paket Cloudflare?

Aturan WAF kustom tersedia di semua paket berbayar (Pro, Business, Enterprise). Paket gratis memiliki aturan WAF terbatas. Namun, Managed Challenge tersedia di semua paket termasuk Free.

Bisakah aturan WAF memicu challenge berbeda untuk path berbeda?

Ya. Setiap aturan WAF dapat memiliki tindakan berbeda dan mencocokkan path berbeda. Sebuah situs mungkin menggunakan Managed Challenge untuk /login dan JS Challenge untuk endpoint /api/.

Seberapa sering situs mengubah aturan WAF-nya?

Bervariasi. Situs e-commerce sering menyesuaikan aturan saat event penjualan. Situs yang security-conscious mungkin memperbarui aturan setiap minggu. Sebagian besar situs jarang mengubah aturan setelah setup awal.

Apakah solve WAF challenge memengaruhi request berikutnya?

Ya. Setelah di-solve, cookie qa_validation_cookie membiarkan request berikutnya lewat tanpa challenge selama ~30 menit. Cookie terikat dengan IP dan User-Agent Anda.


Ringkasan

Aturan Cloudflare WAF memicu CAPTCHA challenge berdasarkan kondisi yang dapat dikonfigurasi: bot score, negara, path, header, atau rate. Tindakan paling umum adalah Managed Challenge, yang secara adaptif dikonversi Cloudflare menjadi invisible challenge, Turnstile, atau JS. Solve dengan CaptchaAI menggunakan metode turnstile atau cloudflare_challenge tergantung apa yang dirender. Hard block (403) dari aturan WAF tidak bisa di-solve — ubah pola request atau IP Anda.

Artikel Terkait

  • Cloudflare Challenge vs Turnstile: Cara Mendeteksi
  • Cloudflare Challenge: Parameter Halaman dan Alur Token
  • Cara Solve Cloudflare Turnstile dengan API
Komentar dinonaktifkan untuk artikel ini.