Phân Tích Kỹ Thuật

Cách xử lý Cloudflare ở chế độ tấn công

Trang trả về lỗi 503 kèm dòng "Checking your browser before accessing..." dù server đích vẫn hoạt động bình thường? Đó gần như chắc chắn là Cloudflare "I'm Under Attack Mode" (IUAM) — lớp phòng thủ DDoS mạnh nhất của Cloudflare, bắt mọi khách truy cập (kể cả request gọi thẳng vào API) chạy xong một thử thách JavaScript ~5 giây trước khi nhận nội dung thật. Site operator có thể bật thủ công khi đang bị tấn công hoặc để mặc định vĩnh viễn. Với client HTTP thuần (requests, axios, cURL…) không có engine JavaScript, thử thách này không thể vượt qua bằng retry hay đổi header — cần một bộ giải chuyên dụng.


Cơ chế hoạt động của IUAM

Khi site operator bật "I'm Under Attack Mode", luồng xử lý mỗi request trở thành:

Every request → Cloudflare edge
    ↓
JavaScript challenge page served (HTTP 503)
    ↓
Browser executes JavaScript challenge (~5 seconds)
    ↓
Challenge answer submitted automatically
    ↓
qa_session_cookie cookie set
    ↓
Original page loaded with qa_session_cookie cookie

Trang thử thách trả về HTTP 503 kèm các tham số sau:

Yếu tố Vai trò
jschl_vc Mã xác minh thử thách
pass Token thời gian — ép client phải chờ đủ ~5 giây
jschl_answer Kết quả tính toán bằng JavaScript
cf_chl_opt Tham số cấu hình thử thách
ray Cloudflare Ray ID gắn với request
"Checking your browser before accessing..." Thông báo hiển thị cho người dùng thật

Ba đặc điểm nhận ra IUAM ngay: mã trạng thái luôn là HTTP 503 (403 là bị chặn hẳn), có chờ bắt buộc ~5 giây trước khi submit, và bắt buộc thực thi JavaScript vì client HTTP đơn thuần không tính được jschl_answer. Cookie xác thực có hiệu lực toàn miền ~30 phút, áp dụng cho mọi trang, kể cả route API không render HTML.

Đừng nhầm mọi lỗi 503 của Cloudflare là IUAM. Managed Challenge, Turnstile và WAF block trả về tín hiệu khác nhau — nhầm lẫn giữa chúng là lý do phổ biến khiến script "giải xong vẫn không vào được trang".


Nhận diện đúng lớp bảo vệ và vì sao HTTP client thường thất bại

Phân biệt IUAM với Managed Challenge, Turnstile, WAF block

Đoạn code dưới đây soi từng tín hiệu HTTP để phân loại chính xác trước khi chọn phương pháp giải:

import requests

def identify_cloudflare_protection(url):
    """Distinguish IUAM from other Cloudflare protections."""
    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, allow_redirects=False)
    html = response.text
    status = response.status_code

    if status == 503 and "jschl" in html:
        return "IUAM (I'm Under Attack Mode)"

    if status == 503 and "challenge-platform" in html:
        return "Managed Challenge"

    if status == 403 and "cf-ray" in str(response.headers):
        return "Blocked by WAF/Bot Management"

    if "cf-turnstile" in html:
        return "Turnstile widget"

    if "challenges.cloudflare.com" in html:
        return "Cloudflare challenge (generic)"

    if status == 200:
        return "No challenge (passed)"

    return f"Unknown (status: {status})"
Tín hiệu IUAM Managed Challenge Turnstile WAF Block
HTTP status 503 503 200 403
jschl xuất hiện trong body
Chờ 5 giây Đôi khi
Set cookie qa_session_cookie Sau khi giải Sau khi giải
Kiểu trang thử thách Toàn trang Toàn trang Chỉ widget Trang lỗi
Cần JavaScript

Trang trả về widget Turnstile thay vì thử thách toàn trang? Đó là Managed Challenge, không phải IUAM — dùng phương pháp giải Turnstile thay vì cloudflare_challenge.

Vì sao HTTP client thường (không phải trình duyệt) luôn thất bại

Thử thách JavaScript của IUAM chứng minh khách truy cập có một trình duyệt thật: Cloudflare trả về trang thử thách với JavaScript bị obfuscate, JavaScript tính toán trên chuỗi lấy từ trang và đo DOM trong tối thiểu 4–5 giây, kết quả jschl_answer được form tự submit lên Cloudflare kèm jschl_vcpass, Cloudflare xác thực cả kết quả lẫn thời gian, rồi trả về cookie qa_session_cookie nếu hợp lệ.

requests, axios, cURL hay bất kỳ HTTP client nào không có engine JavaScript đều dừng lại ngay từ bước đầu — chúng nhận trang thử thách nhưng không có cách nào chạy JavaScript để tính ra jschl_answer:

# This will ALWAYS get the challenge page:
import requests
response = requests.get("https://iuam-protected-site.com")
# response.status_code == 503
# response.text contains "Checking your browser..."

# Plain HTTP clients cannot:
# - Execute JavaScript
# - Compute the challenge answer
# - Meet the timing requirement
# - Generate the required cookies

Đây cũng là lý do thêm header giả hay đổi User-Agent không giải quyết được gì — vấn đề nằm ở việc thiếu runtime JavaScript, không phải ở request.


Giải IUAM bằng CaptchaAI

Tình huống thường gặp: đội QA outsourcing tại TP.HCM chạy script theo dõi giá đối thủ trên các sàn thương mại điện tử. Trang đích bật IUAM đúng đợt khuyến mãi, request bắt đầu trả về 503 — client HTTP thuần không tự vượt qua được, cần bộ giải xử lý thay phần JavaScript.

Cách 1: Bộ giải Cloudflare Challenge (khuyến nghị)

Phương thức cloudflare_challenge của CaptchaAI giải trực tiếp IUAM, không cần dựng trình duyệt:

import requests
import time

API_KEY = "YOUR_API_KEY"
TARGET_URL = "https://iuam-protected-site.com/data"

# Step 1: Submit challenge to CaptchaAI
submit = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "cloudflare_challenge",
    "sitekey": "managed",
    "pageurl": TARGET_URL,
    "json": 1,
})

task_id = submit.json()["request"]
print(f"Task submitted: {task_id}")

# Step 2: Poll for result
for attempt 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:
        token = result["request"]
        print(f"Challenge solved! Token: {token[:50]}...")
        break
    elif result.get("request") == "ERROR_CAPTCHA_UNSOLVABLE":
        print("Challenge could not be solved")
        break
else:
    print("Timed out waiting for solution")

# Step 3: Use qa_session_cookie cookie or token
# The response contains the clearance data needed to access the site

Chỉ ba bước:

  1. Gửi task tới in.php với method=cloudflare_challenge.
  2. Polling res.php mỗi 5 giây tới khi status bằng 1.
  3. Dùng dữ liệu clearance trả về để tiếp tục request — không cần Selenium, không cần trình duyệt.

Cách 2: Kết hợp trình duyệt headless với CaptchaAI

Cho phiên cần duy trì lâu hơn một request, kết hợp trình duyệt headless với CaptchaAI để vừa giữ session vừa xử lý thử thách khi cần:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import requests
import time

API_KEY = "YOUR_API_KEY"

# Launch browser
options = webdriver.ChromeOptions()
options.add_argument("")
driver = webdriver.Chrome(options=options)

# Navigate to IUAM page
driver.get("https://iuam-protected-site.com")

# Wait for challenge page to load
time.sleep(3)

# Check if IUAM challenge is present
if "Checking your browser" in driver.page_source or driver.title == "Just a moment...":
    print("IUAM challenge detected")

    # Option A: Wait for browser to solve natively (if not headless)
    try:
        WebDriverWait(driver, 15).until(
            lambda d: "Checking your browser" not in d.page_source
        )
        print("Challenge passed natively")
    except:
        print("Native solve failed — using CaptchaAI")
        # Submit to CaptchaAI for solving
        # Token submission via JavaScript injection

# After challenge is passed, extract cookies for API use
cookies = driver.get_cookies()
qa_session_cookie = next(
    (c["value"] for c in cookies if c["name"] == "qa_session_cookie"), None
)

if qa_session_cookie:
    print(f"qa_session_cookie obtained: {qa_session_cookie[:30]}...")

    # Use cookie with requests library
    session = requests.Session()
    for cookie in cookies:
        session.cookies.set(cookie["name"], cookie["value"])
    session.headers.update({
        "User-Agent": driver.execute_script("return navigator.userAgent"),
    })

    # Now make requests with the clearance cookie
    response = session.get("https://iuam-protected-site.com/api/data")
    print(f"Status: {response.status_code}")

driver.quit()

Trình duyệt tự vượt qua thử thách khi chạy headed; nếu chạy headless và không tự pass, phần fallback gọi CaptchaAI giải thay. Sau khi có cookie clearance, các request tiếp theo dùng requests.Session() bình thường, không cần chạy lại trình duyệt.

Node.js

const axios = require("axios");

const API_KEY = "YOUR_API_KEY";
const TARGET_URL = "https://iuam-protected-site.com/data";

async function solveIUAM() {
  // Submit challenge
  const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
    params: {
      key: API_KEY,
      method: "cloudflare_challenge",
      sitekey: "managed",
      pageurl: TARGET_URL,
      json: 1,
    },
  });

  const taskId = submit.data.request;
  console.log(`Task submitted: ${taskId}`);

  // Poll for result
  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) {
      console.log("IUAM challenge solved!");
      return result.data.request;
    }
  }

  throw new Error("Timed out");
}

solveIUAM().then((token) => console.log("Token:", token.substring(0, 50)));

Cùng logic gửi/polling như bản Python, chỉ khác cú pháp async/await — cả hai gọi chung một cặp endpoint in.php/res.php.


Cookie cf_clearance (qa_session_cookie trong code ở trên) là kết quả chính của việc giải IUAM — có nó, request tiếp theo trong ~30 phút không cần giải lại:

Thuộc tính Giá trị
Tên cookie cf_clearance
Thời hạn ~30 phút (site operator có thể cấu hình khác)
Phạm vi Toàn miền (domain-wide)
Gắn với Địa chỉ IP + User-Agent dùng lúc giải
Tái sử dụng Được, trong suốt thời hạn
Chuyển sang máy/IP khác Không — chỉ hợp lệ với đúng IP + User-Agent ban đầu

Với workload chạy liên tục, nên tự quản lý thời điểm hết hạn thay vì đợi 503 quay lại:

import requests
import time

class IUAMSessionManager:
    """Manage qa_session_cookie cookies for IUAM-protected sites."""

    def __init__(self, api_key, target_url, user_agent=None):
        self.api_key = api_key
        self.target_url = target_url
        self.user_agent = user_agent or (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 Chrome/120.0.0.0"
        )
        self.session = requests.Session()
        self.session.headers["User-Agent"] = self.user_agent
        self.clearance_time = 0
        self.clearance_lifetime = 1800  # 30 minutes default

    def needs_refresh(self):
        """Check if clearance cookie needs refreshing."""
        return time.time() - self.clearance_time > self.clearance_lifetime - 60

    def solve_challenge(self):
        """Solve IUAM challenge and update session cookies."""
        submit = requests.post("https://ocr.captchaai.com/in.php", data={
            "key": self.api_key,
            "method": "cloudflare_challenge",
            "sitekey": "managed",
            "pageurl": self.target_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": self.api_key,
                "action": "get",
                "id": task_id,
                "json": 1,
            }).json()

            if result.get("status") == 1:
                # Apply clearance to session
                self.clearance_time = time.time()
                return result["request"]

        raise TimeoutError("IUAM solve timed out")

    def get(self, url, **kwargs):
        """Make a GET request, solving IUAM if needed."""
        if self.needs_refresh():
            self.solve_challenge()
        return self.session.get(url, **kwargs)

needs_refresh() chủ động giải lại trước khi cookie hết hạn 60 giây, thay vì đợi request thất bại rồi mới retry.


Xử lý sự cố thường gặp

Triệu chứng Nguyên nhân Cách xử lý
Vòng lặp thử thách vô tận IP thay đổi sau khi đã có cookie clearance Dùng cùng một IP xuyên suốt cả bước giải lẫn bước request
Cookie cf_clearance bị từ chối User-Agent lúc request khác User-Agent lúc giải Dùng đúng một User-Agent cho cả hai bước
Vẫn 503 dù đã giải Cookie hết hạn (>30 phút) Làm mới cookie trước khi hết hạn, không đợi lỗi mới giải lại
Trang thử thách trông khác dự kiến Trang dùng Managed Challenge, không phải IUAM Chuyển sang phương pháp giải Turnstile
Gặp liên tiếp hai trang thử thách Thử thách đầu là IUAM, thử thách sau là Turnstile Giải tuần tự cả hai, đừng bỏ qua trang thứ hai

Câu hỏi thường gặp

IUAM khác gì với Managed Challenge của Cloudflare?

IUAM thách thức mọi khách truy cập vô điều kiện, luôn trả về 503 kèm thử thách JavaScript toàn trang. Managed Challenge chỉ thách thức lưu lượng đáng ngờ và có thể trả về widget Turnstile thay vì trang JS đầy đủ. Cách phân biệt nhanh nhất: có jschl trong HTML hay không.

Làm sao biết trang có đang bật IUAM mà không cần thử request thật?

Không có API công khai để hỏi Cloudflare trước. Cách thực tế là gửi một request thử: nếu nhận HTTP 503 kèm jschl trong body, đó là IUAM (dùng hàm identify_cloudflare_protection() ở phần trên để tự động hóa việc này trong pipeline scraping/QA).

Giải IUAM bằng CaptchaAI tốn bao nhiêu?

CaptchaAI tính phí theo thread song song, không theo số lần giải — BASIC ($15/tháng, 5 thread) đủ cho khối lượng nhỏ, số lần giải mỗi thread không giới hạn. Khối lượng lớn hơn thì cần nhiều thread hơn để giải song song nhiều IUAM cùng lúc.

Ba lý do thường gặp: IP request khác IP lúc giải, User-Agent không khớp, hoặc cookie đã quá 30 phút. Kiểm tra theo thứ tự này trước khi nghi ngờ bộ giải bị lỗi.

IUAM có ảnh hưởng tới các endpoint API gọi trực tiếp, không qua trình duyệt không?

Có. IUAM áp dụng cho toàn domain, kể cả route API không render HTML — đây là lý do request gọi thẳng API từ script vẫn nhận 503 dù chưa từng mở trình duyệt.


Tóm tắt

IUAM buộc mọi khách truy cập vượt qua thử thách JavaScript bắt buộc, trả về HTTP 503 kèm tính toán ~5 giây. Nhận diện đúng IUAM (phân biệt Managed Challenge, Turnstile, WAF block), giải bằng Cloudflare Challenge solver của CaptchaAI, rồi dùng cookie cf_clearance cho request tiếp theo trong cửa sổ 30 phút — luôn khớp IP và User-Agent giữa bước giải và bước dùng.

Bài viết liên quan

Os comentários estão desativados para este artigo.