Documentation
¶
Overview ¶
Package fingerprint builds the stealth Chrome argument vector and resolves proxy geo/exit-IP metadata. Its output is pinned by the golden snapshot in testdata and regression-tested, because a silent drift is a silent stealth loss.
Index ¶
- Constants
- Variables
- func BuildArgs(in BuildArgsInput) []string
- func DefaultExitIP(proxyURL string) (string, error)
- func EnsureBinary() (string, error)
- func EnsureProxyScheme(proxyURL string) string
- func ForkParityArgs(locale, proxy string) []string
- func MatchesSeedGrammar(name string) bool
- func NormalizeSocksStringURL(rawurl string) string
- func ResolveWebRTCArgs(args []string, proxy string, resolveExitIP func(proxyURL string) string) []string
- func SplitProxyAuth(proxy string) (string, string, string)
- func ValidSeed(name string) bool
- type BuildArgsInput
- type ExitIPFunc
- type GeoResolver
Constants ¶
const BinaryPathEnv = "CUTTLE_BROWSER_BINARY"
BinaryPathEnv selects the stealth Chromium fork binary.
const ReservedSeed = "__default__"
ReservedSeed is the sentinel seed that maps to the shared default Chrome instance; it is not a valid user-supplied seed.
Variables ¶
var CountryLocaleMap = map[string]string{}/* 132 elements not displayed */
CountryLocaleMap maps an ISO 3166-1 alpha-2 country code to a BCP 47 locale. Pinned by the golden snapshot; a change must be a reviewed golden diff.
Functions ¶
func BuildArgs ¶
func BuildArgs(in BuildArgsInput) []string
BuildArgs combines stealth defaults, user args, and locale/timezone flags, deduplicating by flag key (everything before '='). Priority: stealth defaults < user args < dedicated params. Insertion order is preserved, and updating an existing key keeps its original position.
func DefaultExitIP ¶
DefaultExitIP discovers the egress IP by querying the echo services through the proxy (or directly when proxyURL is empty).
func EnsureBinary ¶
EnsureBinary resolves the stealth Chromium binary from CUTTLE_BROWSER_BINARY, erroring clearly when the variable is unset or points at a missing file.
func EnsureProxyScheme ¶
EnsureProxyScheme prepends http:// to a schemeless proxy URL so parsers can extract the hostname.
func ForkParityArgs ¶
ForkParityArgs replicates clark/clearcote's own launcher flag set, which the vendored build_args (tuned for the Pro binary) omits but the fork binaries require: an explicit --user-agent matching navigator.userAgent, the ungoogled canvas/client-rects noise switches, UA-CH brand/platform coherence, a Windows font dir, the Accept-Language header, and a residential network profile. Returns nil unless a fork binary is selected via CUTTLE_BROWSER_BINARY.
The persona is Windows: the container spoofs a Direct3D11 GPU pair, so a forced Windows UA + Windows font dir + platform=windows are all coherent.
func MatchesSeedGrammar ¶ added in v0.7.0
MatchesSeedGrammar reports whether name fits the seed character grammar, INCLUDING the reserved default sentinel (which is a legal snapshot filename stem even though it is not a user-supplied seed). The serve daemon's snapshot store uses it as a path-safety guard so a store key can never contain a path separator; it is the single source for that grammar.
func NormalizeSocksStringURL ¶
NormalizeSocksStringURL re-encodes credentials in a proxy URL so Chromium's parser does not truncate them at special characters. It is idempotent on already-encoded input and passes unparseable input through unchanged.
func ResolveWebRTCArgs ¶
func ResolveWebRTCArgs(args []string, proxy string, resolveExitIP func(proxyURL string) string) []string
ResolveWebRTCArgs replaces --fingerprint-webrtc-ip=auto with the resolved proxy exit IP. With no proxy or an unresolvable exit IP, the flag is dropped. resolveExitIP is injected so callers can stub network access in tests.
func SplitProxyAuth ¶
SplitProxyAuth strips inline credentials from an http(s) proxy URL. Stock Chromium and the free forks reject credentials on --proxy-server, so the cred-less URL is used there and the username/password are answered over CDP (Fetch.continueWithAuth). SOCKS and cred-less proxies pass through unchanged with empty credentials.
It byte-matches CPython's urlsplit + SplitResult.username/password (raw, percent-encoding preserved) / hostname (lowercased) / port (re-rendered) + urlunsplit, so both the argv and the credentials answered to the proxy are identical to what CPython's urllib.parse produces.
Types ¶
type BuildArgsInput ¶
type BuildArgsInput struct {
StealthArgs bool
ExtraArgs []string
Timezone string
Locale string
Headless bool
ExtensionPaths []string
StartMaximized bool
}
BuildArgsInput holds the parameters of the vendored build_args function.
type ExitIPFunc ¶
ExitIPFunc resolves the egress IP for a proxy URL ("" = the machine's own public IP). Injected so callers can stub network access in tests.
type GeoResolver ¶
type GeoResolver struct {
ExitIP ExitIPFunc
DBPath func() string
// ResolveHost DNS-resolves the proxy's own hostname to an IP. It is the
// fallback egress IP when every echo service is unreachable but the proxy
// host still resolves (common for datacenter proxies that block outbound to
// the echo endpoints).
ResolveHost func(proxyURL string) string
}
GeoResolver resolves timezone/locale/exit-IP from a proxy. All fields are injectable for hermetic testing; the zero value is not usable - construct via NewGeoResolver.
func NewGeoResolver ¶
func NewGeoResolver() GeoResolver
NewGeoResolver returns a resolver wired to the real echo services, the cached mmdb (downloaded on first use), and DNS-based proxy-host fallback.
func (GeoResolver) ResolveProxyGeoWithIP ¶
func (r GeoResolver) ResolveProxyGeoWithIP(proxyURL string) (string, string, string)
ResolveProxyGeoWithIP returns (timezone, locale, exitIP). When the echo services fail, it falls back to DNS-resolving the proxy hostname (gateway geo) rather than dropping the IP, so WebRTC never leaks the real address behind a proxy. A missing or failed mmdb still returns the exit IP; any lookup failure degrades gracefully rather than erroring.