Teknik Açıklamalar

CAPTCHA Mücadelelerini Tetikleyen Cloudflare WAF Kuralları

Cloudflare'in Web Uygulaması Güvenlik Duvarı (WAF), site operatörlerinin belirli istek özelliklerine (IP adresi, ülke, URL yolu, bot puanı, başlıklar veya herhangi bir kombinasyon) dayalı olarak CAPTCHA zorluklarını tetikleyen kurallar oluşturmasına olanak tanır. Hangi kuralların zorlukları tetiklediğini anlamak, neden CAPTCHA gördüğünüzü teşhis etmenize ve bununla başa çıkmak için doğru yaklaşımı seçmenize yardımcı olur.


CAPTCHA'lar üreten WAF kural eylemleri

Cloudflare WAF kuralları çeşitli eylemleri destekler. Bunlardan üçü çözülebilir zorluklar sunuyor:

WAF eylemi Ne olur? HTTP durumu CaptchaAI yöntemi
Yönetilen Mücadele Cloudflare karar verir: görünmez, Turnstile veya JS mücadelesi 503 turnstile
JS Yarışması 5 saniyelik JavaScript meydan okuma sayfası 503 cloudflare_challenge
Etkileşimli Mücadele Geleneksel CAPTCHA (eski, kullanımdan kaldırıldı) 403 turnstile
Engelle Sert 403, zorluk yok 403 N/A (çözülemez)
İzin ver Geçin, kontrol yok 200 N/A
Atla Kalan WAF kurallarını atla 200 N/A
Günlük Olayı günlüğe kaydet, eylem yok 200 N/A

Yönetilen Mücadele (en yaygın)

Yönetilen Mücadele Cloudflare'in önerilen eylemidir. Ziyaretçi başına meydan okuma türüne uyarlanabilir bir şekilde karar verir:

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_session_cookie cookie issued

Ortak WAF kural kalıpları

Site operatörleri Cloudflare'in ifade dilini kullanarak WAF kuralları oluşturur. Otomatik trafik için CAPTCHA'ları tetikleme olasılığı en yüksek olan kalıplar şunlardır:

Bot puanı kuralları

# 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

Bot puanı kuralları, otomasyon araçları için en yaygın tetikleyicidir. CaptchaAI'nin API çözücüleri, gerçek tarayıcılar kullandıkları için insan düzeyinde puanlar alırlar.

Ülke bazlı kurallar

# 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

Yol tabanlı kurallar

# 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

Orana dayalı kurallar

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

Başlığa dayalı kurallar

# 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

Bileşik kurallar

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

Hangi kuralın tetiklendiğini belirleme

Bir CAPTCHA sınaması göründüğünde, tetikleyici kuralı yanıttan belirleyebilirsiniz:

HTTP başlıklarından

import requests

def check_cloudflare_rule_info(url):
    """Extract WAF rule information from Cloudflare doğrulama akışı 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

Cloudflare Ray ID'den

Her Cloudflare yanıtı bir cf-ray başlığı içerir. Site operatörleri, tam olarak hangi kuralın tetiklendiğini ve hangi eylemin gerçekleştirildiğini görmek için Cloudflare'in kontrol panelinde (Güvenlik > Etkinlikler) bu Ray ID'yi kullanabilir.


WAF'ın tetiklediği zorlukları çözme

Mücadele türüne dayalı strateji

import requests
import time

API_KEY = "YOUR_API_KEY"

def solve_cloudflare_challenge(url, challenge_type):
    """Solve Cloudflare doğrulama akışı 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;
}

WAF kuralı değişiklikleri ve etkileri

Site operatörleri sıklıkla WAF kurallarını ayarlar. Bu değişiklikler otomasyonu etkiler:

Değiştir Otomasyon üzerindeki etkisi Nasıl tespit edilir
Kural eklendi İşe yarayan yollarda yeni zorluklar ortaya çıkıyor 503/403 durum değişikliklerini izleyin
Kural kaldırıldı Meydan okuma ortadan kalkıyor Daha önce 503'ün olduğu yerde 200
İşlem iletildi (Yönetilen → Bloğu) Çözülebilir zorluk zorlu bir blok haline geliyor 503 yerine 403
İşlem gevşetildi (→ Bloku Yönetildi) Sert blok çözülebilir bir zorluk haline geliyor 503, meydan okuma sayfasıyla birlikte
Eşik değişti (bot puanı 30 → 50) Daha fazla isteğe itiraz edildi Artan meydan okuma sıklığı
Yol kapsamı değişti Etkilenen farklı URL'ler Yeni yollar zorluklarla geri dönüyor

İzleme stratejisi

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)

Sorun giderme

Belirti Olası WAF kuralı Düzeltme
Yalnızca /login'de meydan okuma Yol tabanlı kural Bu yol için mücadeleyi çözün
Yalnızca veri merkezi IP'lerinden gelen sorgulama Bot puanı veya IP itibar kuralı Kendi sunucu altyapınız'lerini kullanın veya zorlukları çözün
Zorluk ülkeye göre değişir Ülke bazlı kural İzin verilen ülkede proxy kullanın veya sorunu çözün
N istekten sonra meydan okuma Orana dayalı kural İstek oranını düşürün veya her zorluğu çözün
Her zaman JS'ye meydan okuyun (asla Turnstile) JS Mücadelesi eylemi (Yönetilen değil) cloudflare_challenge yöntemini kullanın
403 hiçbir meydan okuma olmadan Blok eylemi (çözülemez) IP'yi, başlıkları veya istek modelini değiştirin

Sık sorulan sorular

Bir sitenin hangi WAF kurallarını kullandığını görebilir miyim?

Hayır. WAF kuralları site operatörüne özeldir. Kuralları yalnızca davranışlardan çıkarabilirsiniz; hangi yolların zorlukları tetiklediği, hangi IP'lerden ve hangi zorluk türünün göründüğü.

WAF kuralları tüm Cloudflare planları için geçerli midir?

Özel WAF kuralları tüm ücretli planlarda (Pro, Business, Enterprise) mevcuttur. Ücretsiz planların sınırlı WAF kuralları vardır. Ancak Managed Challenge, Ücretsiz dahil tüm planlarda mevcuttur.

WAF kuralları farklı yollar için farklı zorlukları tetikleyebilir mi?

Evet. Her WAF kuralının farklı bir eylemi olabilir ve farklı yollarla eşleşebilir. Bir site, /login için Yönetilen Mücadeleyi ve /api/ uç noktaları için JS Mücadelesini kullanabilir.

Siteler WAF kurallarını ne sıklıkla değiştirir?

Değişir. E-ticaret siteleri genellikle satış etkinlikleri sırasında kuralları ayarlar. Güvenlik bilincine sahip siteler kuralları haftalık olarak güncelleyebilir. Çoğu site, ilk kurulumdan sonra nadiren kuralları değiştirir.

Bir WAF sorununu çözmek gelecekteki istekleri etkiler mi?

Evet. Çözdükten sonra, qa_session_cookie çerezi sonraki isteklerin ~30 dakika boyunca sorgulanmadan geçmesine izin verir. Çerez IP'nize ve Kullanıcı Aracınıza bağlıdır.


Özet

Cloudflare WAF kuralları, yapılandırılabilir koşullara göre CAPTCHA zorluklarını tetikler: bot puanı, ülke, yol, başlıklar veya oran. En yaygın eylem, Cloudflare'in uyarlanabilir bir şekilde görünmez, Turnstile veya JS mücadelesi olarak sunduğu Yönetilen Mücadeledir. Bunları şununla çözünCaptchaAIneyin oluşturulduğuna bağlı olarak turnstile veya cloudflare_challenge yöntemini kullanarak. WAF kurallarındaki sabit bloklar (403) çözülemez; bunun yerine istek düzeninizi veya IP'nizi değiştirin.

İlgili Makaleler

Bu makale için yorumlar devre dışı bırakılmıştır.