feat(browser): fixed Windows identity and per-site egress in umt-cookies plugin (BR-4)
- browser:launching hook generates a Windows fingerprint once (camoufox-js, os=windows), persists it to /root/.camofox/umt-identity.json and reuses it on every launch; Firefox/Camoufox upgrades only bump UA/version fields - Windows fontconfig with absolute font dir (upstream path was broken) - GET /umt/identity (public UA/OS/version) and PUT /umt/sessions/:id/proxy (per-context proxy; Firefox no longer uses container HTTP_PROXY env) - adapter identity()/setEgress(), splitBrowserOnlyCookies for cf_clearance/__cf_bm Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
6663afce7e
commit
ebd07c9230
8 files changed
+746
-5
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import type { BrowserCookie } from "@umt/contracts";
|
||||
import { BROWSER_ONLY_COOKIES, type BrowserCookie } from "@umt/contracts";
|
||||
|
||||
// BR-2 凭据统一:站点账号里存的是 HTTP `Cookie:` 请求头串("a=1; b=2"),浏览器 profile 里是带域名/路径/期限的 Cookie 对象。
|
||||
// 这里只做两者互转与比较;值是凭据,不打印、不进错误信息。
|
||||
@@ -34,6 +34,28 @@ export function mergeCookieHeaders(...headers: (string | null | undefined)[]): s
|
||||
return jar.size ? formatCookieHeader(jar) : null;
|
||||
}
|
||||
|
||||
/** 仅浏览器用的 Cookie(Cloudflare 人机验证):名字精确匹配,或 cf_chl_ 前缀(挑战过程中的临时 Cookie) */
|
||||
export function isBrowserOnlyCookie(name: string): boolean {
|
||||
return (BROWSER_ONLY_COOKIES as readonly string[]).includes(name) || name.startsWith("cf_chl_");
|
||||
}
|
||||
|
||||
/**
|
||||
* 浏览器 → HTTP 方向:剔除仅浏览器用的 Cookie(BR-4)。返回剩下的头串(没有剩余为 null)与被剔除的名字(不含值)。
|
||||
*/
|
||||
export function splitBrowserOnlyCookies(header: string | null | undefined): {
|
||||
header: string | null;
|
||||
browserOnly: string[];
|
||||
} {
|
||||
const jar = parseCookieHeader(header);
|
||||
const browserOnly: string[] = [];
|
||||
for (const name of [...jar.keys()])
|
||||
if (isBrowserOnlyCookie(name)) {
|
||||
jar.delete(name);
|
||||
browserOnly.push(name);
|
||||
}
|
||||
return { header: jar.size ? formatCookieHeader(jar) : null, browserOnly: browserOnly.sort() };
|
||||
}
|
||||
|
||||
/** 两个 Cookie 头串是否等价(忽略顺序与空白) */
|
||||
export function sameCookieHeader(a: string | null | undefined, b: string | null | undefined): boolean {
|
||||
const x = parseCookieHeader(a);
|
||||
|
||||
Reference in new issue
Block a user