返回博客

如何在使用代理时绕过Cloudflare检测

Cloudflare通过代理阻止您的请求?我们分析绕过检测的技术方法:从正确配置TLS到使用无头浏览器的真实示例。

📅2025年12月17日
```html

7种经过验证的方法,通过代理绕过Cloudflare检测

Cloudflare处理超过20%的网络流量,并使用多层次的机器人保护系统。通过代理服务器工作时,收到验证码或被阻止的可能性大大增加。在本指南中,我们将讨论检测的技术方面和在2024年有效的绕过方法。

Cloudflare如何识别代理和机器人

Cloudflare使用综合分析系统,检查每个请求的数十个参数。理解检测机制是成功绕过保护的第一步。

主要检测方法

TLS指纹识别: Cloudflare分析SSL/TLS握手的参数(密码套件、扩展、顺序)。每个HTTP客户端都有独特的“指纹”。例如,Python requests使用OpenSSL,具有易于与Chrome或Firefox区分的特定密码集。

在分析请求时,Cloudflare将TLS指纹与声明的用户代理进行匹配。如果您指定Chrome 120,但TLS参数与Python requests相符——这将立即检测到机器人。

检查参数 分析内容 检测风险
TLS指纹 密码套件、扩展、TLS版本
HTTP/2指纹 头部顺序、SETTINGS帧
IP声誉 IP历史、数据中心归属
JavaScript挑战 执行JS、canvas指纹、WebGL
行为分析 请求模式、时序、鼠标移动

自2023年以来,Cloudflare积极使用机器学习分析行为模式。系统不仅跟踪技术参数,还跟踪请求之间的时间间隔、用户的操作顺序、鼠标移动和页面滚动。

伪装TLS指纹

TLS指纹识别是检测机器人的最有效方法。标准的HTTP客户端(requests、curl、axios)生成的指纹与真实浏览器无法混淆。解决方案是使用模拟浏览器TLS行为的专用库。

使用curl-impersonate

curl-impersonate库是curl的修改版本,准确复制流行浏览器的TLS和HTTP/2指纹。支持Chrome、Firefox、Safari和Edge。

# 安装curl-impersonate
git clone https://github.com/lwthiker/curl-impersonate
cd curl-impersonate
make chrome-build

# 使用模拟Chrome 120
curl_chrome120 -x http://username:password@proxy.example.com:8080 \
  -H "Accept-Language: en-US,en;q=0.9" \
  https://example.com

Python:tls-client库

对于Python,有一个名为tls-client的包装,它在底层使用curl-impersonate,并提供类似requests的接口。

import tls_client

# 创建具有Chrome 120指纹的会话
session = tls_client.Session(
    client_identifier="chrome_120",
    random_tls_extension_order=True
)

# 配置代理
proxies = {
    'http': 'http://username:password@proxy.example.com:8080',
    'https': 'http://username:password@proxy.example.com:8080'
}

# 执行请求
response = session.get(
    'https://example.com',
    proxies=proxies,
    headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'en-US,en;q=0.9',
        'Accept-Encoding': 'gzip, deflate, br',
        'DNT': '1',
        'Connection': 'keep-alive',
        'Upgrade-Insecure-Requests': '1'
    }
)

print(response.status_code)

重要: 使用tls-client时,确保头部中的User-Agent与所选的client_identifier相匹配。否则将导致立即检测。

检查TLS指纹

在开始解析之前,建议检查您的TLS指纹。使用服务tls.peet.wsja3er.com进行分析。

# 检查指纹
response = session.get('https://tls.peet.ws/api/all')
print(response.json()['tls']['ja3'])

# 与真实Chrome的指纹进行比较:
# https://kawayiyi.com/tls-fingerprint-database/

正确配置HTTP头

即使TLS指纹正确,错误的HTTP头也会暴露机器人。Cloudflare不仅分析头部的存在,还分析它们的顺序、值的格式和逻辑一致性。

Chrome的必需头部

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.9',
    'Accept-Encoding': 'gzip, deflate, br',
    'DNT': '1',
    'Connection': 'keep-alive',
    'Upgrade-Insecure-Requests': '1',
    'Sec-Fetch-Dest': 'document',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-Site': 'none',
    'Sec-Fetch-User': '?1',
    'Sec-Ch-Ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
    'Sec-Ch-Ua-Mobile': '?0',
    'Sec-Ch-Ua-Platform': '"Windows"',
    'Cache-Control': 'max-age=0'
}

头部Sec-Ch-Ua-*在Chrome 89中引入,是Client Hints API的一部分。在使用现代用户代理时缺少它们是机器人的明显标志。

头部顺序很重要

在HTTP/2中,头部的顺序对于每个浏览器都是固定的。Python requests和其他标准客户端按字母顺序发送头部,这与浏览器的行为不同。使用支持自定义头部顺序的库。

建议: 使用浏览器的DevTools(网络选项卡→右键单击请求→复制→复制为cURL)获取真实浏览器头部的精确副本。然后根据您的代码进行调整。

动态生成User-Agent

对于所有请求使用相同的User-Agent会增加检测风险。创建一个最新的User-Agent池并进行轮换。

import random

# 最新User-Agent池(2024年12月)
USER_AGENTS = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
]

def get_random_headers():
    ua = random.choice(USER_AGENTS)
    
    # 根据所选UA调整其他头部
    if 'Chrome' in ua:
        return {
            'User-Agent': ua,
            'Sec-Ch-Ua': '"Not_A Brand";v="8", "Chromium";v="120"',
            # ... 其他Chrome头部
        }
    elif 'Firefox' in ua:
        return {
            'User-Agent': ua,
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            # ... Firefox头部
        }
    # ... 处理其他浏览器

使用无头浏览器

当Cloudflare使用JavaScript挑战或高级检测时,唯一可靠的绕过方法是使用真实浏览器。无头浏览器自动处理JavaScript、cookies,并生成完全真实的指纹。

使用Playwright和反检测补丁

Playwright是Selenium的现代替代品,性能更好。然而,标准的Playwright容易通过navigator.webdriver和其他标记被检测到。使用playwright-stealth进行伪装。

from playwright.sync_api import sync_playwright
from playwright_stealth import stealth_sync

def bypass_cloudflare(url, proxy):
    with sync_playwright() as p:
        browser = p.chromium.launch(
            headless=True,
            proxy={
                "server": f"http://{proxy['host']}:{proxy['port']}",
                "username": proxy['username'],
                "password": proxy['password']
            },
            args=[
                '--disable-blink-features=AutomationControlled',
                '--disable-dev-shm-usage',
                '--no-sandbox'
            ]
        )
        
        context = browser.new_context(
            viewport={'width': 1920, 'height': 1080},
            user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            locale='en-US',
            timezone_id='America/New_York'
        )
        
        page = context.new_page()
        stealth_sync(page)  # 应用反检测补丁
        
        # 转到页面
        page.goto(url, wait_until='networkidle', timeout=30000)
        
        # 等待通过Cloudflare挑战(通常5-10秒)
        page.wait_for_timeout(8000)
        
        # 检查是否成功绕过
        if 'Just a moment' in page.content():
            print('Cloudflare挑战未通过')
            return None
        
        # 提取cookies以供后续使用
        cookies = context.cookies()
        html = page.content()
        
        browser.close()
        return {'html': html, 'cookies': cookies}

# 使用
proxy_config = {
    'host': 'proxy.example.com',
    'port': 8080,
    'username': 'user',
    'password': 'pass'
}

result = bypass_cloudflare('https://example.com', proxy_config)

使用Puppeteer Extra和插件

对于Node.js生态系统,最佳解决方案是使用带有puppeteer-extra-plugin-stealth插件的puppeteer-extra。该插件应用超过30种不同的自动化伪装技术。

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

puppeteer.use(StealthPlugin());

async function bypassCloudflare(url, proxyUrl) {
    const browser = await puppeteer.launch({
        headless: 'new',
        args: [
            `--proxy-server=${proxyUrl}`,
            '--disable-blink-features=AutomationControlled',
            '--window-size=1920,1080'
        ]
    });
    
    const page = await browser.newPage();
    
    // 设置视口和用户代理
    await page.setViewport({ width: 1920, height: 1080 });
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
    
    // 重写navigator.webdriver
    await page.evaluateOnNewDocument(() => {
        delete Object.getPrototypeOf(navigator).webdriver;
    });
    
    // 转到页面
    await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
    
    // 等待通过挑战
    await page.waitForTimeout(8000);
    
    // 获取内容和cookies
    const content = await page.content();
    const cookies = await page.cookies();
    
    await browser.close();
    
    return { content, cookies };
}

// 示例使用
bypassCloudflare('https://example.com', 'http://user:pass@proxy.example.com:8080')
    .then(result => console.log('成功'))
    .catch(err => console.error(err));

性能: 无头浏览器消耗的资源显著更多(每个实例200-500 MB RAM)。对于高负载任务,仅在获取cookies时使用它们,然后切换到带有这些cookies的HTTP客户端。

选择绕过Cloudflare的代理类型

代理类型对绕过的成功率至关重要。Cloudflare维护数据中心IP地址的数据库,并对其应用更严格的检查规则。

代理类型 绕过概率 速度 成本 推荐
数据中心 30-40% 仅与无头浏览器一起使用
住宅 85-95% 中等 最佳选择
移动 90-98% 中等 非常高 用于关键任务
ISP(静态住宅) 80-90% 中等 价格与质量的平衡

为什么住宅代理更有效

住宅代理使用真实设备的IP地址(家庭路由器、智能手机)。Cloudflare无法大规模阻止这些IP,因为这会阻止普通用户。统计数据显示,住宅IP收到验证码的频率比数据中心低15-20倍。

使用住宅代理时,地理位置至关重要。如果目标网站面向美国,使用来自亚洲的代理将增加可疑性。选择具有广泛地理覆盖和城市定向能力的提供商。

移动代理以确保最大可靠性

移动代理使用移动运营商的IP地址(4G/5G)。移动网络的特点是通过飞行模式动态更换IP,这提供了几乎无限数量的干净IP地址。移动IP被阻止的概率接近于零。

# 通过API轮换移动IP的示例
import requests
import time

def rotate_mobile_ip(proxy_api_url):
    """更换移动代理的IP"""
    response = requests.get(f"{proxy_api_url}/rotate")
    if response.status_code == 200:
        print("IP成功更换")
        time.sleep(5)  # 等待更改生效
        return True
    return False

# 使用移动代理
mobile_proxy = "http://user:pass@mobile.proxy.com:8080"

for i in range(10):
    # 执行请求
    response = requests.get(
        'https://example.com',
        proxies={'http': mobile_proxy, 'https': mobile_proxy}
    )
    
    # 每次请求后轮换IP
    rotate_mobile_ip('https://api.proxy.com/mobile')

管理cookies和会话

成功通过Cloudflare挑战后,服务器会设置cookies(cf_clearance、__cfduid等),以确认客户端的合法性。正确管理这些cookies可以避免重复检查。

提取和重用cf_clearance

cf_clearance cookie通常有效期为30-60分钟。在通过无头浏览器获取后,可以在常规HTTP请求中使用。

import requests
import pickle
from datetime import datetime, timedelta

class CloudflareCookieManager:
    def __init__(self, cookie_file='cf_cookies.pkl'):
        self.cookie_file = cookie_file
        self.cookies = self.load_cookies()
    
    def load_cookies(self):
        """加载保存的cookies"""
        try:
            with open(self.cookie_file, 'rb') as f:
                data = pickle.load(f)
                # 检查过期时间
                if data['expires'] > datetime.now():
                    return data['cookies']
        except FileNotFoundError:
            pass
        return None
    
    def save_cookies(self, cookies, ttl_minutes=30):
        """保存带TTL的cookies"""
        data = {
            'cookies': cookies,
            'expires': datetime.now() + timedelta(minutes=ttl_minutes)
        }
        with open(self.cookie_file, 'wb') as f:
            pickle.dump(data, f)
    
    def get_cf_clearance(self, url, proxy):
        """通过浏览器获取cf_clearance"""
        if self.cookies:
            return self.cookies
        
        # 这里是启动浏览器的代码(来自前面的部分)
        # ...
        browser_cookies = bypass_cloudflare(url, proxy)['cookies']
        
        # 转换为requests格式
        cookies_dict = {c['name']: c['value'] for c in browser_cookies}
        self.save_cookies(cookies_dict)
        self.cookies = cookies_dict
        
        return cookies_dict
    
    def make_request(self, url, proxy):
        """自动管理cookies的请求"""
        cookies = self.get_cf_clearance(url, proxy)
        
        response = requests.get(
            url,
            cookies=cookies,
            proxies={'http': proxy, 'https': proxy},
            headers=get_random_headers()
        )
        
        # 如果再次收到挑战——更新cookies
        if response.status_code == 403 or 'cf-browser-verification' in response.text:
            print("Cookies过期,正在获取新的...")
            self.cookies = None
            return self.make_request(url, proxy)
        
        return response

# 使用
manager = CloudflareCookieManager()
response = manager.make_request(
    'https://example.com/api/data',
    'http://user:pass@proxy.example.com:8080'
)

将cookies绑定到IP地址

Cloudflare将cf_clearance绑定到通过挑战的IP地址。在其他IP上使用此cookie将导致阻止。在使用轮换代理时,必须为每个IP存储单独的cookies集。

import hashlib

class IPBoundCookieManager:
    def __init__(self):
        self.cookies_by_ip = {}
    
    def get_ip_hash(self, proxy_url):
        """为代理创建哈希以进行识别"""
        return hashlib.md5(proxy_url.encode()).hexdigest()
    
    def get_cookies_for_proxy(self, proxy_url, target_url):
        """获取特定代理的cookies"""
        ip_hash = self.get_ip_hash(proxy_url)
        
        if ip_hash in self.cookies_by_ip:
            cookies_data = self.cookies_by_ip[ip_hash]
            if cookies_data['expires'] > datetime.now():
                return cookies_data['cookies']
        
        # 通过浏览器获取新的cookies
        new_cookies = self.fetch_cookies_with_browser(target_url, proxy_url)
        
        self.cookies_by_ip[ip_hash] = {
            'cookies': new_cookies,
            'expires': datetime.now() + timedelta(minutes=30)
        }
        
        return new_cookies

代理轮换和请求频率控制

即使技术栈正确,从一个IP发出的请求频率过高也会触发速率限制。Cloudflare分析流量模式并识别异常活动。

代理轮换策略

轮换有三种主要方法:轮流(顺序)、随机和粘性会话(会话绑定)。对于绕过Cloudflare,最佳策略是粘性会话,并限制每个IP的请求。

import time
import random
from collections import defaultdict
from datetime import datetime, timedelta

class SmartProxyRotator:
    def __init__(self, proxy_list, max_requests_per_ip=20, cooldown_minutes=10):
        self.proxy_list = proxy_list
        self.max_requests_per_ip = max_requests_per_ip
        self.cooldown_minutes = cooldown_minutes
        
        # 使用计数器
        self.usage_count = defaultdict(int)
        self.last_used = {}
        self.cooldown_until = {}
    
    def get_proxy(self):
        """获取下一个可用的代理"""
        available_proxies = []
        
        for proxy in self.proxy_list:
            # 检查冷却时间
            if proxy in self.cooldown_until:
                if datetime.now() < self.cooldown_until[proxy]:
                    continue
                else:
                    # 冷却时间结束后重置计数器
                    self.usage_count[proxy] = 0
                    del self.cooldown_until[proxy]
            
            # 检查请求限制
            if self.usage_count[proxy] < self.max_requests_per_ip:
                available_proxies.append(proxy)
        
        if not available_proxies:
            # 如果所有代理都在冷却中——等待
            wait_time = min(
                (self.cooldown_until[p] - datetime.now()).total_seconds()
                for p in self.cooldown_until
            )
            print(f"所有代理都在冷却中。等待{wait_time:.0f}秒...")
            time.sleep(wait_time + 1)
            return self.get_proxy()
        
        # 选择使用最少的代理
        proxy = min(available_proxies, key=lambda p: self.usage_count[p])
        
        self.usage_count[proxy] += 1
        self.last_used[proxy] = datetime.now()
        
        # 达到限制时设置冷却时间
        if self.usage_count[proxy] >= self.max_requests_per_ip:
            self.cooldown_until[proxy] = datetime.now() + timedelta(
                minutes=self.cooldown_minutes
            )
            print(f"代理{proxy}达到限制。冷却{self.cooldown_minutes}分钟。")
        
        return proxy
    
    def add_delay(self):
        """在请求之间添加随机延迟(模拟人类行为)"""
        delay = random.uniform(2, 5)  # 2-5秒
        time.sleep(delay)

# 使用
proxy_pool = [
    'http://user:pass@proxy1.example.com:8080',
    'http://user:pass@proxy2.example.com:8080',
    'http://user:pass@proxy3.example.com:8080',
    # ... 50-100个代理以确保稳定运行
]

rotator = SmartProxyRotator(
    proxy_pool,
    max_requests_per_ip=15,  # 保守值
    cooldown_minutes=15
)

# 执行请求
for i in range(1000):
    proxy = rotator.get_proxy()
    
    response = requests.get(
        'https://example.com/page',
        proxies={'http': proxy, 'https': proxy},
        headers=get_random_headers()
    )
    
    print(f"请求 {i+1}: {response.status_code}")
    rotator.add_delay()

自适应速率限制

更先进的方法是根据服务器的响应动态调整请求频率。如果开始出现429错误或验证码,则自动降低速度。

class AdaptiveRateLimiter:
    def __init__(self, initial_delay=3.0):
        self.delay = initial_delay
        self.min_delay = 1.0
        self.max_delay = 30.0
        self.success_streak = 0
        self.failure_streak = 0
    
    def on_success(self):
        """成功请求——可以加速"""
        self.success_streak += 1
        self.failure_streak = 0
        
        if self.success_streak >= 10:
            # 将延迟减少10%
            self.delay = max(self.min_delay, self.delay * 0.9)
            self.success_streak = 0
    
    def on_failure(self, status_code):
        """错误——减速"""
        self.failure_streak += 1
        self.success_streak = 0
        
        if status_code == 429:  # 速率限制
            # 激进减速
            self.delay = min(self.max_delay, self.delay * 2.0)
        elif status_code == 403:  # 可能被阻止
            self.delay = min(self.max_delay, self.delay * 1.5)
        
        print(f"延迟增加到 {self.delay:.2f}s")
    
    def wait(self):
        """在下一个请求之前等待"""
        # 添加±20%的随机性
        actual_delay = self.delay * random.uniform(0.8, 1.2)
        time.sleep(actual_delay)

绕过的现成工具和库

从零开始开发自己的解决方案需要时间和专业知识。现有的工具可以自动化绕过Cloudflare的过程。

cloudscraper(Python)

cloudscraper库是requests的一个扩展,能够自动解决JavaScript挑战。它适用于基本保护,但可能无法处理高级检查。

import cloudscraper

# 创建支持代理的scraper
scraper = cloudscraper.create_scraper(
    browser={
        'browser': 'chrome',
        'platform': 'windows',
        'desktop': True
    }
)

# 配置代理
proxies = {
    'http': 'http://user:pass@proxy.example.com:8080',
    'https': 'http://user:pass@proxy.example.com:8080'
}

# 执行请求
response = scraper.get('https://example.com', proxies=proxies)

if response.status_code == 200:
    print("成功绕过")
    print(response.text)
else:
    print(f"错误:{response.status_code}")

FlareSolverr(通用)

FlareSolverr是一个代理服务器,它启动无头浏览器来解决Cloudflare挑战。通过HTTP API工作,支持任何编程语言。

# 通过Docker启动FlareSolverr
docker run -d \
  --name=flaresolverr \
  -p 8191:8191 \
  -e LOG_LEVEL=info \
  ghcr.io/flaresolverr/flaresolverr:latest

# 从Python使用
import requests

def solve_cloudflare(url, proxy=None):
    flaresolverr_url = "http://localhost:8191/v1"
    
    payload = {
        "cmd": "request.get",
        "url": url,
        "maxTimeout": 60000
    }
    
    if proxy:
        payload["proxy"] = {
            "url": proxy
        }
    
    response = requests.post(flaresolverr_url, json=payload)
    result = response.json()
    
    if result['status'] == 'ok':
        return {
            'html': result['solution']['response'],
            'cookies': result['solution']['cookies'],
            'user_agent': result['solution']['userAgent']
        }
    else:
        raise Exception(f"FlareSolverr错误:{result['message']}")

# 示例使用
result = solve_cloudflare(
    'https://example.com',
    proxy='http://user:pass@proxy.example.com:8080'
)

print(result['html'])

undetected-chromedriver

修改版的Selenium ChromeDriver,自动应用多种反检测技术。使用起来比Playwright简单,但灵活性较差。

import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def bypass_with_uc(url, proxy):
    options = uc.ChromeOptions()
    options.add_argument(f'--proxy-server={proxy}')
    options.add_argument('--disable-blink-features=AutomationControlled')
    
    driver = uc.Chrome(options=options, version_main=120)
    
    try:
        driver.get(url)
        
        # 等待Cloudflare挑战消失
        WebDriverWait(driver, 20).until_not(
            EC.presence_of_element_located((By.ID, "cf-spinner-please-wait"))
        )
        
        # 为了可靠性额外等待
        time.sleep(3)
        
        # 获取结果
        html = driver.page_source
        cookies = driver.get_cookies()
        
        return {'html': html, 'cookies': cookies}
    
    finally:
        driver.quit()

# 使用
result = bypass_with_uc(
    'https://example.com',
    'http://user:pass@proxy.example.com:8080'
)

组合方法: 最佳策略是仅在初始获取cookies时使用无头浏览器,然后切换到带有这些cookies的HTTP客户端(tls-client、cloudscraper)。这在可靠性和性能之间提供了平衡。

结论

通过代理绕过Cloudflare需要综合方法:正确的TLS指纹、真实的HTTP头、高质量的代理和合理的会话管理。关键建议:

  • 使用住宅移动代理而不是数据中心
  • 使用具有正确TLS指纹的库(tls-client、curl-impersonate)
  • 对于复杂情况,使用带有反检测补丁的无头浏览器
  • 保存和重用cf_clearance cookies
  • 根据速率限制轮换代理(每个IP不超过15-20个请求)
  • 在请求之间添加随机延迟(2-5秒)

Cloudflare的保护机制不断演变,因此定期更新工具和调整策略非常重要。监控指纹技术的变化,并在最新版本的保护上测试解决方案。

为了稳定运行,建议使用具有广泛IP池和自动轮换的专业代理服务。

```