Menu

چگونه Cloudflare را دور بزنیم

در این مقاله یاد می‌گیرید چگونه با استفاده از NodeJS و اتوماسیون مرورگر Playwright، صفحه‌ی «در حال بررسی اینکه شما انسان هستید» از Cloudflare را دور بزنید.

بیایید ابتدا به‌طور خلاصه بفهمیم Cloudflare چگونه کار می‌کند. بدون Cloudflare، مدیران وب‌سایت‌ها صفحات خود را روی یک سرور با IP عمومی میزبانی می‌کنند. نام دامنه‌های آن‌ها به آن IP تبدیل می‌شود و مرورگر شما مستقیماً به سرور آن‌ها متصل می‌شود.

وقتی آن‌ها از Cloudflare استفاده می‌کنند، مدیریت DNS را به Cloudflare واگذار می‌کنند، که نام‌های دامنه را به IPهای اختصاصی خودش تبدیل می‌کند. روی این IPها، سرورهای پروکسی خاصی اجرا می‌شود که درخواست‌های HTTP و HTTPS ورودی را فیلتر می‌کنند.

بازدیدکنندگان جدید صفحه‌ی معروفی با متن: «Verifying you are human. This may take a few seconds.» را مشاهده می‌کنند. در طول این بررسی، ممکن است نیاز باشد یک کپچا حل کنید. قبلاً از reCAPTCHA استفاده می‌شد، اما حالا کپچای اختصاصی خودشان به نام Turnstile را استفاده می‌کنند.

پس از گذراندن موفقیت‌آمیز کپچا، مرورگر یک توکن منحصر‌به‌فرد را در کوکی‌ای با نام cf_clearance دریافت می‌کند. مرورگر شما از این توکن برای درخواست صفحات سایت از پروکسی Cloudflare استفاده می‌کند. اگر این توکن منقضی شود یا Cloudflare تشخیص دهد که این توکن مانند ربات‌ها رفتار می‌کند، آن را باطل می‌کند و شما دوباره صفحه‌ی کپچا را مشاهده خواهید کرد.

روش ما به شما کمک می‌کند تا این توکن را با استفاده از یک جلسه مرورگر خودکار به‌دست آورید. توجه داشته باشید که این روش IP واقعی وب‌سایت را فاش نمی‌کند — این اطلاعات فقط برای Cloudflare و مدیران سایت شناخته شده است. و این چیز خوبی است!

در اینجا نحوه‌ی انجام آن با NodeJS و Playwright آمده است:

// Install packages
// npx install playwright @antiadmin/anticaptchaofficial
import { chromium } from "playwright";
import ac from "@antiadmin/anticaptchaofficial";

// Specify the target website address
const websiteBehindCloudFlare = 'https://yourwebsite.com';

// Set your Anti-Captcha API key here:
ac.setAPIKey('API_KEY_HERE');
ac.setSoftId(0);

let browser = null;
let page = null;


(async () => {

    // Opening the browser
    try {
        console.log('Opening browser ..');
        browser = await chromium.launch({ headless: false });
        console.log('Creating new page ..');
        page = await browser.newPage();
    } catch (e) {
        console.log("Could not open browser: "+e.toString());
        return;
    }


    let params = null;

    try {

        // Doing several attempts to inject our code
        while (!params) {

            console.log('Navigating to the page')
            await page.goto(websiteBehindCloudFlare);

            console.log('Injecting our proxy code to replace window.turnstile');
            await page.evaluate(() => {
                window.turnstile = new Proxy(window.turnstile, {
                  get(target, prop) {
                    if (prop === "render") {
                      return function (a, b) {
                        const p = {
                          websiteURL: window.location.href,
                          websiteKey: b.sitekey,
                          action: b.action,
                          cData: b.cData,
                          chlPageData: b.chlPageData,
                          userAgent: navigator.userAgent,
                        };

                        // saving params in window.params
                        window.params = p;

                        // assigning callback to a variable
                        window.cfCallback = b.callback

                        // calling original render function
                        return target.render.apply(this, arguments);
                      };
                    }
                    return target[prop];
                  },
                });
            });

          console.log('Getting params');
          params = await page.evaluate(() => {
            return new Promise((resolve) => {
              setTimeout(() => resolve(window.params || null), 5000);
            });
          });

          if (!params) {
            console.log('Retrying..');
            await delay(3000);
          }
        }

        console.log("Extracted Turnstile Params:", params);

        console.log('Solving Turnstile captcha with Anti-Captcha')
        const token = await ac.solveTurnstileProxyless(websiteBehindCloudFlare, params.websiteKey, params.action, params.cData, params.chlPageData);

        // Running Cloudflare's callback function we previously assigned to window.cfCallback
        await page.evaluate((token) => {
            window.cfCallback(token)
        }, token);

        console.log('Waiting for redirects to finish')
        await delay(5000);

        // Get all cookies for current page
        const cookies = await page.context().cookies();
        // Find cf_clearance
        const cf_clearance = cookies.filter(c => c.name === 'cf_clearance');

        // Output cookies
        console.log('Cookies:', cookies);
        console.log('cf_clearance:', cf_clearance);



    } catch (e) {
      console.error('Could not inject proxy code:', e);
    }

    // close browser when needed
    // await browser.close();


})();

function delay(time) {
   return new Promise(function(resolve) {
       setTimeout(resolve, time)
   });
}

کاری که کد ما انجام می‌دهد:

1. باز کردن پنجره مرورگر و رفتن به صفحه بررسی Cloudflare.
2. جایگزین کردن تابع render کپچای Turnstile با تابع پراکسی ما، که در آن پارامترهای اولیه و callback اتمام کپچا را دریافت می‌کنیم.
3. ارسال پارامترهای اولیه به API آنتی‌کپچا. کارگران انسانی این کپچا را برای شما حل کرده و یک توکن ارائه می‌دهند.
4. فراخوانی تابع callback ذخیره‌شده قبلی با توکن Turnstile به‌عنوان ورودی.
5. Cloudflare این توکن را به‌صورت داخلی بررسی می‌کند، کوکی را در مرورگر ما قرار می‌دهد و صفحه را دوباره بارگذاری می‌کند.
6. با این cf_clearance مرورگر محتوای سایت را از طریق پروکسی Cloudflare دریافت می‌کند.