Skip to content

covertchannelblog/alterego

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

alterego

alterego is an HTTP/HTTPS MITM proxy that clones TLS fingerprints to help automated clients evade anti-bot systems. It captures the ClientHello from a real browser and replays it for scripted traffic, while maintaining a shared cookie jar so authentication state flows transparently between human-operated browsers and automation tools.

Read the blog post: Cloning Real Browser TLS Identities

alterego terminal screenshot

Features

  • TLS Fingerprint Cloning: Automatically learns the ClientHello from downstream connections and replays it upstream using uTLS, or accepts a base64-encoded ClientHello for precise control.
  • Preset Fingerprint Library: ~50 built-in browser profiles (Chrome, Firefox, Safari, Edge, iOS, Android) with -list-fingerprints to enumerate all options.
  • Shared Cookie Jar: All proxy clients (browser + automation) share the same cookie store. Cookies set by the server during browser challenges automatically appear in subsequent automated requests.
  • User-Agent Inheritance: The proxy captures the User-Agent from the first downstream request and applies it to all upstream traffic, ensuring consistent client identification.
  • Automatic CA Management: Omit -ca-cert/-ca-key to auto-generate a persistent MITM root CA (alterego-ca.crt / alterego-ca.key) that survives restarts.
  • JSON Configuration: Persist settings in config.json (or use -config path); CLI flags override config values for quick experimentation.
  • WebSocket Support: Proxies WebSocket connections over HTTP/1.1 or HTTP/2 extended CONNECT (RFC 8441), with automatic fallback when the origin doesn't support HTTP/2 settings.
  • SOCKS5 Upstream Proxy: Route upstream connections through Tor or another SOCKS5 proxy with -upstream-socks and optional authentication.
  • Interactive TUI: Real-time dashboard (enabled by default) displays captured identity (fingerprint, User-Agent) and live request logs. Pass -no-tui to revert to plain stdout logging.
  • Upstream TLS Verification: Uses system root CAs by default; disable with -insecure-skip-upstream-cert-verify for testing only.

Requirements

  • Go 1.24.0+ to build from source (specified in go.mod)
  • MITM CA trust: Clients must trust the generated alterego-ca.crt for HTTPS interception (see Trust the MITM CA)

No additional system dependencies. All Go dependencies (including uTLS v1.8.1) are fetched automatically via go mod.

Quick Start

# Auto-generate a CA and start the proxy on 127.0.0.1:8888
go run ./cmd/alterego

# Use an existing CA and specify listen address
go run ./cmd/alterego -ca-cert /path/to/root.crt -ca-key /path/to/root.key -listen 0.0.0.0:8080

# Pin a specific upstream fingerprint
go run ./cmd/alterego -upstream-fingerprint HelloChrome_120 -debug

# Route upstream through Tor
go run ./cmd/alterego -upstream-socks 127.0.0.1:9050

# List all available fingerprint profiles
go run ./cmd/alterego -list-fingerprints

Trust the MITM CA

For HTTPS interception to work, clients must trust alterego-ca.crt:

# macOS
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain alterego-ca.crt

# Linux (Debian/Ubuntu)
sudo cp alterego-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

# Firefox: Preferences → Privacy & Security → View Certificates → Import

For testing with curl, use -k to skip verification:

curl -k -x http://127.0.0.1:8888 https://example.com

Configuration

CLI Flags

Flag Default Description
-listen 127.0.0.1:8888 Full listen address (overrides -listen-ip/-listen-port)
-listen-ip 127.0.0.1 Listen IP (used when -listen is unset)
-listen-port 8888 Listen port (used when -listen is unset)
-ca-cert (auto-generated) Path to PEM root CA certificate
-ca-key (auto-generated) Path to PEM private key for root CA
-upstream-fingerprint (learned) uTLS profile name (see -list-fingerprints)
-upstream-fingerprint-base64 Base64-encoded ClientHello (overrides -upstream-fingerprint)
-fallback-fingerprint HelloRandomizedALPN Fallback profile if primary handshake fails
-fingerprint-allow-blunt-mimicry false Allow unknown extensions when parsing captured ClientHello
-fingerprint-add-padding false Force padding extension in captured ClientHello
-fingerprint-real-psk false Treat PSK extensions as real (default: fake PSK)
-upstream-socks SOCKS5 proxy for upstream connections (host:port)
-upstream-socks-user SOCKS5 username (optional)
-upstream-socks-pass SOCKS5 password (optional)
-har Write proxied HTTP/HTTPS traffic to a HAR file
-insecure-skip-upstream-cert-verify false Disable upstream TLS verification (testing only)
-debug false Enable verbose logging for troubleshooting
-no-tui false Disable interactive TUI and log to stdout
-config config.json (if exists) Path to JSON config file
-list-fingerprints Print all available fingerprint profiles and exit

JSON Configuration File

Create config.json in the working directory (or use -config path) to persist settings:

{
  "listen": "127.0.0.1:8080",
  "ca_cert": "/path/to/alterego-ca.crt",
  "ca_key": "/path/to/alterego-ca.key",
  "upstream_fingerprint": "HelloChrome_120",
  "fallback_fingerprint": "HelloRandomizedALPN",
  "upstream_socks": "127.0.0.1:9050",
  "har_path": "captures/traffic.har",
  "debug": false,
  "disable_tui": false
}

CLI flags always override config file values. See config.example.json for a commented template.

How It Works

TLS Fingerprint Mechanics

When a client connects over HTTPS, the initial ClientHello advertises its "personality": cipher suites, supported groups, extensions, ALPN protocols, and their ordering. Modern anti-bot systems use this shape as a classification signal.

alterego solves this in three ways using uTLS:

  1. Automatic Learning (default): Captures the first downstream ClientHello and replays it for all upstream connections. The browser teaches the proxy what "normal" looks like.
  2. Preset Profiles: Pin a specific uTLS profile (HelloChrome_120, HelloFirefox_Auto, etc.) via -upstream-fingerprint.
  3. Raw ClientHello Cloning: Provide a base64-encoded ClientHello (captured from Wireshark or browser devtools) via -upstream-fingerprint-base64 for exact duplication.

Cookie Jar and User-Agent Sharing

All clients connected to the proxy share a single cookie jar. When a browser clears a Cloudflare challenge and receives a cf_clearance cookie, the next automated request automatically includes it. Similarly, the proxy captures the User-Agent from the first downstream request and injects it into all upstream traffic.

This dual-identity model (one TLS fingerprint + one User-Agent + one cookie jar) alters requests from other tools to be consistent with the real browser that cleared the challenge.

Fingerprint Fallback

If the primary fingerprint fails during the TLS handshake (e.g., invalid server key share, handshake failure), the proxy automatically retries with the fallback profile(s). This is useful when a captured ClientHello targets a specific TLS 1.3 key exchange that the origin doesn't support.

Disable fallback by omitting -fallback-fingerprint entirely.

WebSocket Proxying

WebSocket requests are detected after the downstream TLS handshake. The proxy attempts HTTP/2 extended CONNECT (RFC 8441) first and falls back to HTTP/1.1 if the origin declines SETTINGS_ENABLE_CONNECT_PROTOCOL. Once the upgrade succeeds, frames are relayed verbatim with no post-handshake meddling.

Usage Examples

Example 1: Browser + Automation

# Terminal 1: Start the proxy
go run ./cmd/alterego -debug

# Terminal 2: Configure browser to use proxy 127.0.0.1:8888 and visit a Cloudflare-protected site
# The browser clears the challenge; cookies are stored in the proxy's jar

# Terminal 3: Automated client inherits the session
curl -x http://127.0.0.1:8888 https://protected-site.example.com/api/data

Example 2: Pinned Fingerprint via SOCKS5

# Route through Tor with a specific Chrome fingerprint
go run ./cmd/alterego \
  -upstream-fingerprint HelloChrome_131 \
  -fallback-fingerprint HelloChrome_120 \
  -upstream-socks 127.0.0.1:9050 \
  -debug

Architecture

The codebase is organized into modules:

  • cmd/alterego/main.go: CLI flag parsing, configuration loading, server wiring.
  • internal/config/: JSON config file parsing.
  • internal/proxy/: Core HTTP/HTTPS/CONNECT handling, cookie jar, upstream dialing.
  • internal/tls/: MITM CA management, leaf certificate generation and caching (512-entry LRU cache, 24h TTL).
  • internal/fingerprint/: uTLS ClientHello spec parsing, ALPN override, fingerprint cloning.
  • internal/websocketproxy/: WebSocket detection, HTTP/2 extended CONNECT, bidirectional tunneling.
  • cmd/alterego/tui.go: Interactive TUI powered by tview.

Building and Testing

# Format code
gofmt -w .

# Run tests
go test ./...

# Build a static binary
go build -o alterego ./cmd/alterego

# Cross-compile
GOOS=linux GOARCH=amd64 go build -o alterego-linux ./cmd/alterego

Updating uTLS Fingerprints

When bumping github.com/refraction-networking/utls, review u_common.go in that module for new Hello* constants and update the clientHelloProfiles table in cmd/alterego/main.go. The list is currently hand-maintained; a code generator is planned for future versions.