Skip to content

Proxy Rotation

Fresh

Source: BIBLE.md (Phase 11 Cookie Refresh + Proxy Pool Fallback), bible/glossary.md (proxy marriage)

Ghost Engine uses two distinct proxy patterns: per-account "marriages" and a session pool for fallback.

Proxy marriage

Permanent 1:1 binding of a proxy IP to a persona. Never changes. Stored in proxy-marriages.json.

Why permanent: an account's IP is part of its identity. If someone@gmail.com always connects from 1.2.3.4, that's a coherent signal. If the IP changes weekly, every login looks like an attack to the platform.

Proxy pool fallback

When an account's married proxy gets rejected (Google says "signin/rejected", "blocked", or "unusual activity"), Ghost Engine pulls fresh session proxies from a pool.

data/proxy-pool.json contains 100 pg.proxi.es session proxies (F2K9t1gNVvNAxEVf-co-USA). Each new connection gets a different IP. Pool loaded at plugin startup via ProxyPool from core/proxy-rotate.mjs.

Recovery flow

flowchart TD
  S[Account login attempt] --> M[Married proxy]
  M -- ok --> D[Done: refresh cookies]
  M -- rejected --> P1[Pool proxy #1, fresh session id]
  P1 -- ok --> D
  P1 -- rejected --> P2[Pool proxy #2, fresh session id]
  P2 -- ok --> D
  P2 -- rejected --> P3[Pool proxy #3, fresh session id]
  P3 -- ok --> D
  P3 -- rejected --> Q[Quarantine account]

Each retry appends a random session ID (-sid-XXXXX) to the username for fresh IP.

Where it kicks in

The cookie-refresh plugin uses this flow:

  1. Launch browser with saved cookies, check if still logged in
  2. If logged in: re-capture fresh cookies, done
  3. If expired: call loginPersona(persona) or joinPlatform(persona, platform) (randomized 65% OAuth, 35% direct)
  4. If proxy rejected: pull fresh proxy from pool
  5. Up to 3 retries from pool
  6. If all fail: quarantine

Proxy manager plugin

plugins/proxy-manager/ wraps core/proxy-rotate.mjs ProxyPool. 7 routes:

MethodRouteWhat
GET/proxiesList proxies
POST/proxiesAdd proxy
DELETE/proxies/:idRemove
POST/proxies/:id/health-checkTest connection
GET/proxies/healthPool health stats
POST/proxies/rotateForce rotate
POST/proxies/assignAssign to account

Pool health route

bash
curl http://localhost:4700/cookies/proxy-pool

Returns { alive, dead, total }.

Health-aware rotation

The ProxyPool tracks per-proxy health:

  • 200 OK on test fetch: +1
  • timeout/refused/4xx/5xx: -1
  • Score below threshold: removed from active pool

When pulling a proxy from the pool, the manager picks the highest-health unused one first.

Per-account fingerprint + proxy + timezone consistency

The full identity stack ensures consistency:

flowchart LR
  E[Account email] --> M[Proxy marriage 1.2.3.4]
  M --> G[Geo: Dallas, TX]
  G --> TZ[Timezone: America/Chicago]
  G --> LA[Language: en-US]
  G --> UULE[UULE: Dallas, TX]
  E --> FP[Fingerprint deterministic from email hash]

Sleeve network-identity.mjs enforces this:

  • Proxy marriage permanent
  • Timezone from geo
  • Language from country
  • WebRTC and DNS leak protection