From cf6c0d2b4d8419daa2837ab2ab3194b1254790f4 Mon Sep 17 00:00:00 2001 From: Chaos Date: Sun, 12 Jul 2026 00:37:27 +0800 Subject: [PATCH] Prefer Chromium for turnstilePatch on headless servers Google Chrome blocks --load-extension, so CF tokens stay empty under Xvfb. Auto-select Chromium when the extension is present, install/ detect chromium in start.sh, and document browser_prefer overrides. --- README.md | 5 ++- auto_register.py | 5 ++- config.example.json | 6 ++- cpa_xai/browser_confirm.py | 4 +- grok_register_ttk.py | 73 ++++++++++++++++++++++++++++++------ register_cli.py | 16 +++++--- start.sh | 77 ++++++++++++++++++++++++++++---------- 7 files changed, 141 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 3ae624e..dfadd81 100644 --- a/README.md +++ b/README.md @@ -543,8 +543,9 @@ curl -sS http://127.0.0.1:8317/v1/chat/completions \ | 协议 `sso invalid` | SSO 过期/无效;会回退浏览器;检查账本第三段 | | 协议 verify/approve 失败 | 会话态变化 / 风控;看日志后自动回退浏览器 | | 一直 `authorization_pending` | 浏览器路径未完成 consent;需到「设备已授权」且 token 200 | -| Cloudflare / Turnstile | 优先 `xvfb-run` 有头;纯 headless 易拦;Chromium+turnstilePatch、检查代理 | -| 浏览器 connection fails / no interface | 无 DISPLAY:已自动 headless;仍失败则装 Chrome 并用 `xvfb-run -a ...` | +| Cloudflare / Turnstile | 必须用 **Chromium + turnstilePatch**(Chrome 无法 `--load-extension`,token 常为 0);配合 `./start.sh` 自动 Xvfb | +| Turnstile token 长度=0 | 日志若 `skip turnstilePatch on Google Chrome`:`sudo apt install -y chromium` 后重跑;或 `browser_path` 指向 chromium | +| 浏览器 connection fails / no interface | 无 DISPLAY:`./start.sh` 自动 Xvfb / Python headless | | Hotmail 收不到码 | 检查四段凭证、ClientID/Token、IMAP 主机与 alias 计数 | | 有 token 但无 grok-4.5 | `cpa_base_url` 是否为 `cli-chat-proxy` | | 注册成功但无 `cpa_auths` | `cpa_export_enabled`?看 `cpa_auths/cpa_auth_failed.txt` | diff --git a/auto_register.py b/auto_register.py index 20b3e63..7567299 100755 --- a/auto_register.py +++ b/auto_register.py @@ -184,12 +184,13 @@ def save_account(email: str, password: str, sso: str = ""): def resolve_browser_path() -> str | None: # Prefer Chromium: Google Chrome blocks --load-extension (turnstilePatch). + # Chrome-first order often leaves Turnstile token=0 on Xvfb servers. for cand in ( - "/snap/bin/chromium", "/usr/bin/chromium", "/usr/bin/chromium-browser", - "/usr/bin/google-chrome", + "/snap/bin/chromium", "/usr/bin/google-chrome-stable", + "/usr/bin/google-chrome", ): if os.path.isfile(cand) or os.path.islink(cand): return cand diff --git a/config.example.json b/config.example.json index 43beb0e..420717f 100644 --- a/config.example.json +++ b/config.example.json @@ -56,9 +56,11 @@ "// ===== 网络 / 浏览器 =====": "", "// proxy": "注册机主代理:Chromium + 邮箱 HTTP。可带账号 http://user:pass@host:port。优先于系统 https_proxy。", "proxy": "http://127.0.0.1:7890", - "// browser_headless": "注册 Chromium:true=强制无头,false=强制有头,auto/省略=无 DISPLAY 时自动 headless。也可用 env BROWSER_HEADLESS / CLI --headless|--headed。无头服务器建议 xvfb-run。", + "// browser_headless": "注册浏览器:true=强制无头,false=强制有头,auto/省略=无 DISPLAY 时自动 headless。也可用 env BROWSER_HEADLESS / CLI --headless|--headed。无头服务器建议 start.sh 自动 Xvfb。", "browser_headless": "auto", - "// browser_path": "可选,强制 Chromium/Chrome 可执行文件路径;默认自动探测 google-chrome-stable / chromium。", + "// browser_prefer": "auto=有 turnstilePatch 时优先 Chromium(可 --load-extension);chromium|chrome 强制偏好。Google Chrome 无法加载扩展,服务器上 Turnstile 常 token=0。", + "browser_prefer": "auto", + "// browser_path": "可选,强制浏览器可执行文件路径;默认按 browser_prefer 自动探测。", "browser_path": "", "// user_agent": "Chromium UA;一般保持默认 Chrome 桌面串即可。", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36", diff --git a/cpa_xai/browser_confirm.py b/cpa_xai/browser_confirm.py index 75370f9..b5f5714 100644 --- a/cpa_xai/browser_confirm.py +++ b/cpa_xai/browser_confirm.py @@ -233,11 +233,11 @@ def create_standalone_page( # Prefer Chromium: Google Chrome blocks --load-extension (turnstilePatch). for cand in ( - "/snap/bin/chromium", "/usr/bin/chromium", "/usr/bin/chromium-browser", - "/usr/bin/google-chrome", + "/snap/bin/chromium", "/usr/bin/google-chrome-stable", + "/usr/bin/google-chrome", ): if os.path.isfile(cand) or os.path.islink(cand): try: diff --git a/grok_register_ttk.py b/grok_register_ttk.py index e155e4e..a5cce3b 100644 --- a/grok_register_ttk.py +++ b/grok_register_ttk.py @@ -58,6 +58,7 @@ DEFAULT_CONFIG = { "cloudmail_password": "", "cpa_gui_close_mint_browser": True, "browser_headless": "auto", + "browser_prefer": "auto", "browser_path": "", "hotmail_accounts_file": "mail_credentials.txt", "hotmail_alias_mode": "random", @@ -772,16 +773,22 @@ def apply_headless_to_options(options, headless: bool = True) -> None: except Exception: pass -# Prefer Google Chrome for registration reliability (email delivery path). -# Chromium is fallback; turnstilePatch extension only loads on Chromium. -# On Chrome we inject the same patch via CDP add_init_js (see apply_stealth_patches). -BROWSER_CANDIDATES = ( - "/usr/bin/google-chrome-stable", - "/usr/bin/google-chrome", - "/snap/bin/chromium", +# Browser discovery order is decided by resolve_browser_path(): +# - default (auto): prefer Chromium so turnstilePatch can load (--load-extension) +# - Google Chrome blocks unpacked extensions; CDP stealth alone often fails CF on servers +# - config browser_prefer: auto | chromium | chrome +# - config browser_path: absolute override +CHROMIUM_CANDIDATES = ( "/usr/bin/chromium", "/usr/bin/chromium-browser", + "/snap/bin/chromium", ) +CHROME_CANDIDATES = ( + "/usr/bin/google-chrome-stable", + "/usr/bin/google-chrome", +) +# Legacy flat list (tests / external callers) +BROWSER_CANDIDATES = CHROMIUM_CANDIDATES + CHROME_CANDIDATES # Minimal CDP stealth only. Aggressive patches (chrome.runtime delete, permissions # monkeypatch, fake plugins/languages, postMessage spam) caused xAI UI to show @@ -816,15 +823,54 @@ def _is_google_chrome_path(path: str | None) -> bool: return "chrome" in base and "chromium" not in path +def _first_existing_browser(candidates) -> str | None: + for cand in candidates: + if cand and (os.path.isfile(cand) or os.path.islink(cand)): + return cand + return None + + def resolve_browser_path(): + """Pick Chromium/Chrome for registration. + + Priority: + 1. config browser_path (absolute) + 2. env BROWSER_PATH / CHROME_PATH + 3. browser_prefer=chromium|chrome|auto + auto → Chromium first when turnstilePatch exists (needed for CF) + 4. any remaining candidate + """ # Optional override from config.json "browser_path" override = str((config.get("browser_path") if isinstance(config, dict) else "") or "").strip() if override and (os.path.isfile(override) or os.path.islink(override)): return override - for cand in BROWSER_CANDIDATES: - if os.path.isfile(cand) or os.path.islink(cand): - return cand - return None + for env_key in ("BROWSER_PATH", "CHROME_PATH", "CHROMIUM_PATH"): + env_path = (os.environ.get(env_key) or "").strip() + if env_path and (os.path.isfile(env_path) or os.path.islink(env_path)): + return env_path + + prefer = str((config.get("browser_prefer") if isinstance(config, dict) else "") or "auto").strip().lower() + if prefer in ("", "default", "detect"): + prefer = "auto" + # env override + env_pref = (os.environ.get("BROWSER_PREFER") or "").strip().lower() + if env_pref: + prefer = env_pref + + has_ext = os.path.isdir(EXTENSION_PATH) + if prefer in ("chrome", "google-chrome", "google"): + order = list(CHROME_CANDIDATES) + list(CHROMIUM_CANDIDATES) + elif prefer in ("chromium", "chromeium"): # typo tolerant + order = list(CHROMIUM_CANDIDATES) + list(CHROME_CANDIDATES) + else: + # auto: extension needs Chromium; without extension Chrome is fine + if has_ext: + order = list(CHROMIUM_CANDIDATES) + list(CHROME_CANDIDATES) + else: + order = list(CHROME_CANDIDATES) + list(CHROMIUM_CANDIDATES) + + path = _first_existing_browser(order) + return path def apply_stealth_patches(page=None, log_callback=None) -> bool: @@ -902,11 +948,14 @@ def create_browser_options(headless=None): # Google Chrome blocks CLI unpacked extension loading; Chromium still allows it. if _is_google_chrome_path(browser_path): print( - " [ext] Chrome: minimal CDP stealth only (extension blocked)", + " [ext] Chrome: minimal CDP stealth only (extension blocked)\n" + " 建议安装 Chromium 或 config browser_prefer=chromium / browser_path=/usr/bin/chromium\n" + " 否则 Turnstile token 常为 0(无头/Xvfb 服务器上尤其明显)", flush=True, ) else: options.add_extension(EXTENSION_PATH) + print(f" [ext] turnstilePatch loaded: {EXTENSION_PATH}", flush=True) # Apply config.json "proxy" to Chromium. Without this, only HTTP helpers # used get_proxies(); the browser itself fell through to system/env proxy. proxy = (config.get("proxy") or "").strip() diff --git a/register_cli.py b/register_cli.py index f2d8fc7..778f9e7 100644 --- a/register_cli.py +++ b/register_cli.py @@ -59,7 +59,8 @@ def _patched_create_browser_options(): except Exception: pass - # Prefer Google Chrome for registration reliability; Chromium fallback for extension. + # Prefer register resolve_browser_path (Chromium first when turnstilePatch exists). + # Do NOT force Google Chrome here — Chrome blocks --load-extension and CF often fails. browser_path = None resolve = getattr(reg, "resolve_browser_path", None) if callable(resolve): @@ -69,11 +70,11 @@ def _patched_create_browser_options(): browser_path = None if not browser_path: for cand in ( - "/usr/bin/google-chrome-stable", - "/usr/bin/google-chrome", - "/snap/bin/chromium", "/usr/bin/chromium", "/usr/bin/chromium-browser", + "/snap/bin/chromium", + "/usr/bin/google-chrome-stable", + "/usr/bin/google-chrome", ): if os.path.isfile(cand) or os.path.islink(cand): browser_path = cand @@ -103,10 +104,15 @@ def _patched_create_browser_options(): and "chromium" not in browser_path ) if is_chrome: - print("[ext] skip turnstilePatch on Google Chrome (--load-extension blocked)", flush=True) + print( + "[ext] skip turnstilePatch on Google Chrome (--load-extension blocked); " + "install chromium or set browser_prefer=chromium", + flush=True, + ) else: try: opts.add_extension(ext_path) + print(f"[ext] turnstilePatch loaded: {ext_path}", flush=True) except Exception: pass diff --git a/start.sh b/start.sh index 21460a5..6676bd0 100755 --- a/start.sh +++ b/start.sh @@ -339,33 +339,58 @@ step3_sync_deps() { step4_check_browser() { echo -e "${CYAN}[4/6] 检测/安装浏览器...${NC}" + # Prefer Chromium for turnstilePatch (--load-extension works). + # Google Chrome alone often leaves CF token=0 on Xvfb servers. local candidate + local found_chromium="" + local found_chrome="" for candidate in \ - google-chrome-stable google-chrome chromium chromium-browser \ + chromium chromium-browser \ + /usr/bin/chromium /usr/bin/chromium-browser /snap/bin/chromium; do + if have_cmd "$candidate" || [ -x "$candidate" ] 2>/dev/null; then + found_chromium="$(command -v "$candidate" 2>/dev/null || echo "$candidate")" + break + fi + done + for candidate in \ + google-chrome-stable google-chrome \ /usr/bin/google-chrome-stable /usr/bin/google-chrome \ - /snap/bin/chromium /usr/bin/chromium /usr/bin/chromium-browser \ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"; do if have_cmd "$candidate" || [ -x "$candidate" ] 2>/dev/null; then - echo -e " ${GREEN}✓${NC} 浏览器: $(command -v "$candidate" 2>/dev/null || echo "$candidate")" - return 0 + found_chrome="$(command -v "$candidate" 2>/dev/null || echo "$candidate")" + break fi done - echo -e " ${YELLOW}⚠${NC} 未检测到 Chrome/Chromium,尝试自动安装..." + if [ -n "$found_chromium" ]; then + echo -e " ${GREEN}✓${NC} Chromium: $found_chromium (可加载 turnstilePatch)" + if [ -n "$found_chrome" ]; then + echo -e " ${CYAN}·${NC} 另检测到 Chrome: $found_chrome(注册默认优先 Chromium)" + fi + return 0 + fi + + if [ -n "$found_chrome" ]; then + echo -e " ${YELLOW}⚠${NC} 仅有 Google Chrome: $found_chrome" + echo " Chrome 无法加载 turnstilePatch,Turnstile 容易 token=0。" + echo " 将尝试安装 Chromium..." + else + echo -e " ${YELLOW}⚠${NC} 未检测到 Chrome/Chromium,尝试自动安装 Chromium..." + fi local installed=false - # Debian/Ubuntu + # Debian/Ubuntu — prefer chromium (extension support) if have_cmd apt-get; then if have_cmd sudo; then if sudo -n true 2>/dev/null; then echo " → 使用 apt 安装 chromium(免密 sudo)..." - if sudo apt-get update -qq && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq chromium-browser chromium 2>/dev/null; then + if sudo apt-get update -qq && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq chromium chromium-browser 2>/dev/null; then installed=true fi else echo -e " ${YELLOW}⚠${NC} 检测到 apt,但需要交互 sudo,跳过自动安装浏览器" - echo " 可手动: sudo apt install -y chromium-browser" + echo " 可手动: sudo apt install -y chromium" fi fi # Arch @@ -388,23 +413,35 @@ step4_check_browser() { else echo " 可手动: sudo dnf install -y chromium" fi - # macOS Homebrew + # macOS Homebrew — chromium cask if available, else chrome elif have_cmd brew; then - echo " → 使用 Homebrew 安装 Google Chrome..." - if brew install --cask google-chrome 2>/dev/null; then + echo " → 使用 Homebrew 安装 chromium / chrome..." + if brew install --cask chromium 2>/dev/null || brew install --cask google-chrome 2>/dev/null; then installed=true fi fi - # 再检测一次 + # 再检测一次(Chromium 优先) for candidate in \ - google-chrome-stable google-chrome chromium chromium-browser \ + chromium chromium-browser \ + /usr/bin/chromium /usr/bin/chromium-browser /snap/bin/chromium \ + google-chrome-stable google-chrome \ /usr/bin/google-chrome-stable /usr/bin/google-chrome \ - /snap/bin/chromium /usr/bin/chromium /usr/bin/chromium-browser \ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"; do if have_cmd "$candidate" || [ -x "$candidate" ] 2>/dev/null; then - echo -e " ${GREEN}✓${NC} 浏览器已就绪: $(command -v "$candidate" 2>/dev/null || echo "$candidate")" - return 0 + local resolved + resolved="$(command -v "$candidate" 2>/dev/null || echo "$candidate")" + case "$resolved" in + *chromium*) + echo -e " ${GREEN}✓${NC} 浏览器已就绪 (Chromium): $resolved" + return 0 + ;; + *) + echo -e " ${YELLOW}⚠${NC} 仅有 Chrome: $resolved" + echo " 注册机将用 CDP stealth;过 CF 仍建议: sudo apt install -y chromium" + return 0 + ;; + esac fi done @@ -412,12 +449,12 @@ step4_check_browser() { echo -e " ${YELLOW}⚠${NC} 安装命令已执行,但仍未在 PATH 中找到浏览器,请重启终端后重试" else echo -e " ${YELLOW}⚠${NC} 未能自动安装浏览器" - echo " DrissionPage 需要 Chrome/Chromium;协议 mint 不强制浏览器,回退流程需要。" + echo " 注册需要 Chromium(推荐,可加载 turnstilePatch)或 Chrome。" echo " 手动安装示例:" - echo " Ubuntu/Debian: sudo apt install -y chromium-browser" + echo " Ubuntu/Debian: sudo apt install -y chromium" echo " Arch: sudo pacman -S chromium" - echo " macOS: brew install --cask google-chrome" - echo " ${YELLOW}脚本将继续,注册可能因缺少浏览器而失败。${NC}" + echo " macOS: brew install --cask chromium" + echo " ${YELLOW}脚本将继续,注册可能因缺少浏览器 / Turnstile 失败。${NC}" fi }