mirror of
https://github.com/lukaszraczylo/mcp-captcharesolver.git
synced 2026-10-12 00:45:28 +00:00
84 lines
3.3 KiB
Go
84 lines
3.3 KiB
Go
// Package stealth generates browser anti-bot artifacts (fingerprint profiles,
|
|
// evasion init scripts, humanized interaction plans, header sets) that the
|
|
// caller injects/applies. It never drives a browser.
|
|
package stealth
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand/v2"
|
|
)
|
|
|
|
// FingerprintParams selects an identity. Seed makes generation deterministic.
|
|
type FingerprintParams struct {
|
|
OS string // windows | macos | linux
|
|
Browser string // chrome | firefox
|
|
Locale string // e.g. en-US
|
|
Seed uint64
|
|
}
|
|
|
|
// Fingerprint is a coherent, internally-consistent browser identity.
|
|
type Fingerprint struct {
|
|
UserAgent string `json:"user_agent"`
|
|
SecCHUA string `json:"sec_ch_ua"`
|
|
SecCHUAPlatform string `json:"sec_ch_ua_platform"`
|
|
Platform string `json:"platform"`
|
|
Locale string `json:"locale"`
|
|
Timezone string `json:"timezone"`
|
|
Viewport string `json:"viewport"`
|
|
WebGLVendor string `json:"webgl_vendor"`
|
|
WebGLRenderer string `json:"webgl_renderer"`
|
|
HardwareConcurrency int `json:"hardware_concurrency"`
|
|
DeviceMemory int `json:"device_memory"`
|
|
}
|
|
|
|
func pick[T any](r *rand.Rand, xs []T) T { return xs[r.IntN(len(xs))] }
|
|
|
|
// GenerateFingerprint returns a coherent identity. Same Seed → same output.
|
|
func GenerateFingerprint(p FingerprintParams) Fingerprint {
|
|
if p.OS == "" {
|
|
p.OS = "windows"
|
|
}
|
|
if p.Browser == "" {
|
|
p.Browser = "chrome"
|
|
}
|
|
if p.Locale == "" {
|
|
p.Locale = "en-US"
|
|
}
|
|
r := rand.New(rand.NewPCG(p.Seed, p.Seed^0x9e3779b97f4a7c15)) //nolint:gosec // math/rand intentional: fingerprint generation is not a security primitive
|
|
|
|
chromeMajor := pick(r, []string{"131", "132", "133"})
|
|
var ua, platform, chPlatform, webglVendor, webglRenderer, tz string
|
|
switch p.OS {
|
|
case "macos":
|
|
platform, chPlatform = "MacIntel", `"macOS"`
|
|
ua = fmt.Sprintf("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s.0.0.0 Safari/537.36", chromeMajor)
|
|
webglVendor, webglRenderer = "Google Inc. (Apple)", "ANGLE (Apple, Apple M2, OpenGL 4.1)"
|
|
tz = "America/Los_Angeles"
|
|
case "linux":
|
|
platform, chPlatform = "Linux x86_64", `"Linux"`
|
|
ua = fmt.Sprintf("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s.0.0.0 Safari/537.36", chromeMajor)
|
|
webglVendor, webglRenderer = "Google Inc. (Mesa)", "ANGLE (Mesa, llvmpipe, OpenGL 4.5)"
|
|
tz = "Europe/London"
|
|
default: // windows
|
|
platform, chPlatform = "Win32", `"Windows"`
|
|
ua = fmt.Sprintf("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s.0.0.0 Safari/537.36", chromeMajor)
|
|
webglVendor, webglRenderer = "Google Inc. (NVIDIA)", "ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 Direct3D11, D3D11)"
|
|
tz = "America/New_York"
|
|
}
|
|
secCHUA := fmt.Sprintf(`"Chromium";v="%s", "Google Chrome";v="%s", "Not?A_Brand";v="24"`, chromeMajor, chromeMajor)
|
|
viewport := pick(r, []string{"1920x1080", "1536x864", "1440x900", "1366x768"})
|
|
return Fingerprint{
|
|
UserAgent: ua,
|
|
SecCHUA: secCHUA,
|
|
SecCHUAPlatform: chPlatform,
|
|
Platform: platform,
|
|
Locale: p.Locale,
|
|
Timezone: tz,
|
|
Viewport: viewport,
|
|
WebGLVendor: webglVendor,
|
|
WebGLRenderer: webglRenderer,
|
|
HardwareConcurrency: pick(r, []int{4, 8, 12, 16}),
|
|
DeviceMemory: pick(r, []int{4, 8, 16}),
|
|
}
|
|
}
|