autoreg-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok60915d52e8425
2026-10-20 02:16:32 +03:00
commit f58eafeb48
565 changed files with 60064 additions and 0 deletions

View File

@@ -0,0 +1,333 @@
---
name: anti-detection-browser
description: Browser automation with Cloudflare Turnstile & CDP-detection bypass. DrissionPage + Turnstile patch extension + proxy auth forwarder. Use when headless browsers are blocked by Cloudflare or anti-bot detection.
category: automation
---
# Anti-Detection Browser Automation
Обход Cloudflare Turnstile и CDP-детекции при автоматизации браузера.
## Когда использовать
- Cloudflare блокирует headless-браузеры (Playwright, Puppeteer, Selenium)
- Страница показывает "Attention Required! | Cloudflare" или "Sorry, you have been blocked"
- `MouseEvent.screenX/screenY = 0` детектится как CDP-браузер
- Нужна регистрация/логин на сайтах с Turnstile (x.ai, Clerk, TokenHarbor)
## Почему Playwright не работает
Playwright использует CDP (Chrome DevTools Protocol). Cloudflare Turnstile детектит CDP-браузеры через:
- `MouseEvent.screenX/screenY = 0` (в headless-режиме координаты мыши не эмулируются)
- `navigator.webdriver = true`
- Отсутствие реальных движений мыши перед кликом
## Решение: DrissionPage + Turnstile Patch
**DrissionPage** — библиотека управления Chromium, которая не использует WebDriver и не выставляет `navigator.webdriver`.
**Turnstile patch** — Chrome extension (Manifest V3), который инжектит скрипт в `MAIN` world на `document_start`, переопределяя `MouseEvent.prototype.screenX/Y` случайными реалистичными значениями.
### Структура расширения
```
turnstilePatch/
├── manifest.json
└── script.js
```
**manifest.json**:
```json
{
"manifest_version": 3,
"name": "Turnstile Patch",
"version": "1.0",
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["script.js"],
"run_at": "document_start",
"world": "MAIN"
}]
}
```
**script.js**:
```javascript
Object.defineProperty(MouseEvent.prototype, 'screenX', {
get: function() { return Math.floor(Math.random() * 400) + 800; }
});
Object.defineProperty(MouseEvent.prototype, 'screenY', {
get: function() { return Math.floor(Math.random() * 200) + 400; }
});
```
### Настройка DrissionPage
```python
from DrissionPage import Chromium, ChromiumOptions
co = ChromiumOptions()
co.auto_port()
co.set_argument("--no-sandbox")
co.set_argument("--disable-gpu")
co.set_argument("--disable-dev-shm-usage")
co.set_argument("--disable-software-rasterizer")
# Загрузка Turnstile patch
EXTENSION_PATH = os.path.abspath("turnstilePatch")
co.add_extension(EXTENSION_PATH)
# Прокси (если без аутентификации)
co.set_proxy("http://proxy:port")
browser = Chromium(co)
```
### Ожидание Turnstile
После навигации нужно ждать 15-30 секунд, пока Turnstile пройдёт в non-interactive режиме:
```python
page.get("https://target.com/sign-up")
run_logger.info("Waiting for Cloudflare Turnstile...")
deadline = time.time() + 30
while time.time() < deadline:
has_challenge = page.run_js(
"return document.title.includes('Attention Required') || "
"document.querySelector('#challenge-running') !== null || "
"document.body.innerText.includes('verifying you are human')"
)
if not has_challenge:
break
time.sleep(2)
```
### Поиск кнопок с fallback
На странице может быть разный язык. Использовать JS-поиск по тексту:
```javascript
const candidates = Array.from(document.querySelectorAll('button, a, [role="button"]'));
const target = candidates.find(node => {
const text = (node.innerText || node.textContent || '').replace(/\s+/g, '').toLowerCase();
return text.includes('signupwithemail') ||
text.includes('continue with email') ||
text.includes('sign up with email') ||
text.includes('use email') ||
text.includes('email');
});
if (target) target.click();
```
## Proxy Auth Forwarder
DrissionPage и nodriver НЕ поддерживают прокси с аутентификацией. Ошибка: "你似乎在设置使用账号密码的代理,暂时不支持这种代理".
Решение: локальный forward proxy, который добавляет `Proxy-Authorization` header.
### ⚠️ HTTP-based forwarder НЕ работает с Chrome
`http.server.HTTPServer` + `BaseHTTPRequestHandler` ломает CONNECT-туннели для Chrome — браузер получает `chrome-error://chromewebdata/`. Curl работает, Chrome — нет.
**Использовать RAW TCP forwarder** (см. `scripts/tcp_forwarder.py`):
```python
import socket, threading, select, base64
UPSTREAM_HOST = 'residential-x.bpproxy.at'
UPSTREAM_PORT = 1000
AUTH = base64.b64encode(b'user:pass').decode()
LOCAL_PORT = 9129
def handle_client(client_sock):
data = b''
while b'\r\n\r\n' not in data:
chunk = client_sock.recv(4096)
if not chunk: return
data += chunk
request = data.decode('latin-1', errors='replace')
first_line = request.split('\r\n')[0]
method, target, _ = first_line.split(' ', 2)
if method == 'CONNECT':
host, port_str = target.rsplit(':', 1)
port = int(port_str)
remote = socket.create_connection((UPSTREAM_HOST, UPSTREAM_PORT), timeout=10)
connect_req = f'CONNECT {host}:{port} HTTP/1.1\r\nHost: {host}:{port}\r\nProxy-Authorization: Basic {AUTH}\r\n\r\n'
remote.send(connect_req.encode())
resp = b''
while b'\r\n\r\n' not in resp:
resp += remote.recv(4096)
if b'200' not in resp.split(b'\r\n')[0]:
client_sock.send(b'HTTP/1.1 502 Bad Gateway\r\n\r\n')
remote.close()
return
client_sock.send(b'HTTP/1.1 200 Connection Established\r\n\r\n')
client_sock.settimeout(30)
remote.settimeout(30)
socks = [client_sock, remote]
while True:
r, _, _ = select.select(socks, [], [], 30)
if not r: break
for s in r:
d = s.recv(8192)
if not d: return
dst = remote if s is client_sock else client_sock
dst.sendall(d)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('127.0.0.1', LOCAL_PORT))
server.listen(50)
while True:
client, addr = server.accept()
threading.Thread(target=handle_client, args=(client,), daemon=True).start()
```
Запуск:
```bash
python tcp_forwarder.py &
# Затем использовать http://127.0.0.1:9129 как browser_proxy
```
## Geo-Blocking
Сервисы типа x.ai гео-блокируют по стране выхода прокси. Проверять перед использованием:
```bash
curl -x "http://user:pass@proxy:port" -s http://ip-api.com/json
# Проверить поле "country" — x.ai доступен из US, CA, UK, EU, но НЕ из IQ, RU, CN
```
## Nodriver: Fallback When DrissionPage Fails
DrissionPage может быть детектирован Cloudflare даже с Turnstile patch. Симптом: `PageDisconnectedError: 与页面的连接已断开` — Cloudflare активно рвёт CDP-соединение.
**Nodriver** (`pip install nodriver`) — альтернатива с встроенной антидетект-защитой. Не требует отдельного Turnstile patch.
### Настройка nodriver
```python
import nodriver as uc
browser = await uc.start(
headless=False,
browser_args=[
"--window-size=1280,900",
"--no-first-run",
"--no-default-browser-check",
"--disable-blink-features=AutomationControlled",
"--proxy-server=http://127.0.0.1:9129", # через proxy forwarder
"--ignore-certificate-errors",
],
)
tab = await browser.get("https://accounts.x.ai/sign-up?redirect=grok-com")
```
### API ключевые отличия от DrissionPage
- **Async**: все методы `await`
- `tab.find(text)` — поиск элемента по тексту (аналог `page.run_js(...find text...)`)
- `tab.select(selector)` — CSS-селектор
- `tab.evaluate(js)` — выполнить JS
- `el.click()`, `el.send_keys(text)` — взаимодействие
- Обернуть в `asyncio.wait_for()` для таймаутов
### Google OAuth Bypass для accounts.x.ai
**Проблема**: `accounts.x.ai` блокирует ВСЕ bpproxy residential IP (403) напрямую, но Google OAuth (`accounts.google.com`) принимает те же прокси (302).
**Решение**: использовать Google OAuth flow вместо прямой email-регистрации:
1. Зайти на `accounts.x.ai/sign-up?redirect=grok-com`
2. Нажать «Continue with Google» (не «Use email»)
3. Google OAuth-страница загружается через прокси (Google принимает bpproxy)
4. Ввести Gmail + пароль + TOTP (если 2FA)
5. Пройти consent screen
6. Редирект обратно на Grok
**Требования**: Gmail аккаунты с 2FA-секретами (формат как в `tusk_gmail_accounts.json`).
```python
# Пример: поиск кнопки Google
clicked = await click_text(tab, [
"Continue with Google", "Sign in with Google",
"Sign up with Google", "Google",
], timeout=10)
```
### Port Conflicts: Multiple Proxy Forwarders
Никогда не запускать несколько экземпляров proxy forwarder на одном порту — они конфликтуют и порт становится недоступным. При смене upstream-прокси:
1. Убить старый forwarder: `taskkill /F /PID <pid>`
2. Проверить что порт свободен: `netstat -ano | grep <port>`
3. Запустить новый forwarder на **уникальном** порту
**Рекомендация**: использовать разные порты для разных upstream-прокси (9128, 9129, 9130...).
### Nodriver `browser.stop()` не awaitable
`browser.stop()` в nodriver возвращает `None` — не использовать `await`:
```python
# ❌ ОШИБКА: TypeError: object NoneType can't be used in 'await' expression
await browser.stop()
# ✅ ПРАВИЛЬНО
browser.stop()
```
### TCP Forwarder: всегда вместо HTTP-based
HTTP-based forwarder (`http.server.HTTPServer`) не работает с Chrome — CONNECT-туннели ломаются. Всегда использовать RAW TCP forwarder (`scripts/tcp_forwarder.py`).
## Pitfalls
### Playwright Headless Blocked by Cloudflare (General)
Playwright's headless Chromium is detected by Cloudflare on many sites, not just those with Turnstile. Symptoms: `page.goto()` times out, empty page content, or Cloudflare challenge page. Use `headless=False` with a persistent Chrome user profile (`launch_persistent_context`), or connect via CDP to an existing Chrome instance (`connect_over_cdp`).
### Playwright CDP Works, Headless Doesn't
`connect_over_cdp("http://127.0.0.1:9222")` to an existing Chrome with remote debugging works reliably because it uses the real Chrome profile. Headless Playwright (`launch()`) is detected. For automation that needs Cloudflare bypass, always prefer CDP connection over headless launch.
### Nodriver Windows Asyncio Crashes (2026-08-21)
Nodriver (`uc.start()`) crashes on Windows with `ValueError: I/O operation on closed pipe` in `asyncio.proactor_events`. This is a Windows-specific asyncio issue. Fall back to Playwright with `headless=False` or CDP connection.
### MCP Browser as Reliable Fallback
When Playwright and nodriver both fail, the Chrome DevTools MCP (`mcp__chrome_devtools__*` tools) works reliably. It uses the existing Chrome instance with the user's profile, avoiding Cloudflare detection entirely. Use `evaluate_script` with nativeInputSetter for fastest form interactions.
### Standalone Chrome + CDP: самопроходящий Turnstile (2026-09-10)
Когда все MCP/headless-пути висят на SPA-бандле (белая страница, бандл pending, хотя curl качает 200), а firecrawl_interact рвёт сессии — поднять отдельный Chrome с `--remote-debugging-port=9333 --user-data-dir=<fresh>` (background=true), подключиться Playwright `connect_over_cdp`, заполнить форму и **поллить скрытое поле `cf-turnstile-response` до length>10** — в реальном Chrome non-interactive Turnstile решается сам за 10-20 сек. Полный разбор (RainProxy): `references/rainproxy-cdp-turnstile.md` — там же pitfalls: `has-text("Login")` ловит "Login with Google", Gmail-алиасы с `+` отклоняются, UTF-7 имена папок Gmail при русской локали.
### accounts.x.ai blocks ALL bpproxy residential IPs (2026-08-14)
Все 25 bpproxy residential прокси возвращают `403` при прямом обращении к `accounts.x.ai`. Google (`accounts.google.com`) принимает те же прокси. Использовать Google OAuth flow вместо прямого email signup.
### DrissionPage CDP disconnection
Cloudflare может детектировать и разрывать CDP-соединение DrissionPage (`PageDisconnectedError`). Переключиться на nodriver.
### DrissionPage proxy auth
DrissionPage не поддерживает `user:pass@host:port` в URL прокси. Использовать proxy forwarder.
### Turnstile timing
Non-interactive Turnstile требует 5-30 секунд. Недостаточное ожидание → кнопки не найдены (страница ещё не загрузилась после challenge).
### Geo-blocking bpproxy
bpproxy residential выходят из разных стран (Ирак, Канада, etc.). Всегда проверять `ip-api.com/json` перед использованием с гео-зависимыми сервисами.
### bpproxy hardsession истекает
Hardsession-прокси могут умереть через несколько часов. Периодически перегенерировать пул через `bpproxy` skill.
## Связанные скиллы
- `bpproxy` — генерация и управление прокси
- `bulk-account-registration` — пайплайн массовой регистрации
## Связанные файлы
- `references/grok-registration-pipeline.md` — конкретный пайплайн регистрации Grok (x.ai) с DrissionPage
- `scripts/proxy_forwarder.py` — HTTP forward proxy (DEPRECATED — не работает с Chrome, используй tcp_forwarder.py)
- `scripts/tcp_forwarder.py` — RAW TCP forward proxy (работает с Chrome, nodriver, DrissionPage)
- `templates/turnstile-patch/` — шаблон Chrome extension для обхода CDP-детекции (manifest.json + script.js)