Skip to content

LyleMi/ja3proxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

65 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JA3Proxy

JA3Proxy is an HTTP/SOCKS5 proxy that uses uTLS to create outbound TLS connections with configurable ClientHello fingerprints. It can be used to test how applications behave behind different browser-like TLS fingerprints, while keeping familiar proxy interfaces for clients.

Features

  • HTTP, HTTPS, and SOCKS5 proxy support on the same listen address.
  • Customizable TLS ClientHello fingerprints through uTLS presets.
  • Dynamic MITM certificates for HTTPS CONNECT traffic.
  • Automatic local CA generation when no certificate/key pair is provided.
  • Optional SOCKS5 upstream proxy for both HTTP and HTTPS traffic.
  • Docker and Docker Compose examples included.

How it works

For plain HTTP requests, JA3Proxy forwards the request directly. For HTTPS CONNECT requests, it establishes a TLS connection to the upstream server using the configured uTLS fingerprint, then serves a dynamically generated certificate to the client using the local CA. SOCKS5 connections are accepted on the same listen address: TLS streams use the same MITM/uTLS path, while non-TLS streams are forwarded as plain TCP.

Because HTTPS traffic is intercepted, clients must either trust the generated CA certificate or explicitly skip certificate verification for testing.

Quick start

Build from source

Requirements:

  • Go 1.24 or newer
  • make if you want to use the provided Makefile
git clone https://github.com/lylemi/ja3proxy.git
cd ja3proxy

go build -o ja3proxy ./cmd/ja3proxy
./ja3proxy -port 8080 -client 360Browser -version 7.5

The CLI source lives in cmd/ja3proxy.

Test the proxy:

curl -v -k --proxy http://127.0.0.1:8080 https://www.example.com
curl -v -k --proxy socks5h://127.0.0.1:8080 https://www.example.com

The first run creates credentials/cert.pem and credentials/key.pem if they do not already exist.

Docker

mkdir -p credentials

docker run --rm \
  -v ./credentials:/app/credentials \
  -p 8080:8080 \
  ghcr.io/lylemi/ja3proxy:latest \
  -cert /app/credentials/cert.pem \
  -key /app/credentials/key.pem \
  -client 360Browser \
  -version 7.5

Docker Compose

docker compose up -d

See compose.yaml for the full service definition.

Configuration

Usage of ja3proxy:
  -addr string
        proxy listen host
  -port string
        proxy listen port (default "8080")
  -cert string
        proxy CA cert (default "credentials/cert.pem")
  -key string
        proxy CA key (default "credentials/key.pem")
  -client string
        utls client (default "Golang")
  -version string
        utls client version (default "0")
  -fingerprint-config string
        JSON file to hot-reload utls client/version
  -upstream string
        upstream proxy, e.g. 127.0.0.1:1080, socks5 only
  -debug
        enable debug

Example with a SOCKS5 upstream proxy:

./ja3proxy \
  -port 8080 \
  -client Chrome \
  -version 106 \
  -upstream socks5://127.0.0.1:1080

The -upstream flag also accepts host:port, for example 127.0.0.1:1080. Only SOCKS5 upstream proxies are supported.

Hot-reload TLS fingerprints

Use -fingerprint-config to load the uTLS fingerprint from a JSON file and watch it for changes:

{
  "client": "Chrome",
  "version": "106"
}

Start the proxy with the file:

./ja3proxy -port 8080 -fingerprint-config fingerprint.json

When the file changes, JA3Proxy validates and reloads it. New HTTPS CONNECT connections use the latest fingerprint; existing TLS tunnels keep the fingerprint they were opened with. If a reload fails, the previous fingerprint stays active and the error is logged.

TLS fingerprints

JA3Proxy passes the -client and -version values to uTLS. Supported presets depend on the uTLS version used by this project. See the uTLS ClientHelloID definitions for the authoritative list.

Common presets:

Client Version
Golang 0
Firefox 55, 56, 63, 99, 105
Chrome 58, 62, 70, 96, 102, 106
iOS 12.1, 13, 14
Android 11
Edge 85, 106
Safari 16.0
360Browser 7.5
QQBrowser 11.1

Updating uTLS

The uTLS library is compiled into the JA3Proxy binary, so updating it requires a rebuild. Dependabot is configured to open weekly pull requests for Go module updates, including github.com/refraction-networking/utls. Those pull requests run the Go CI workflow before they are merged.

To update manually:

go get github.com/refraction-networking/utls@latest
go mod tidy
go test ./...

Certificates

JA3Proxy needs a CA certificate and private key to generate per-host certificates for HTTPS interception.

  • If both files exist, they are loaded from -cert and -key.
  • If neither file exists, JA3Proxy generates a new CA pair.
  • If only one file exists, startup fails to avoid using a mismatched pair.

By default, generated CA files are written to credentials/cert.pem and credentials/key.pem. If the configured paths include missing directories, JA3Proxy creates them before writing the files.

For browser or application testing, import the generated CA certificate into the client trust store. For one-off command-line checks, tools such as curl -k can skip verification.

Development

Run the test suite:

go test ./...

Build release binaries with the Makefile:

make

This creates Linux and Windows AMD64 binaries in the bin/ directory.

Security notice

JA3Proxy performs TLS interception and can expose decrypted traffic to the machine running the proxy. Use it only in environments where you have permission to inspect the traffic. Protect generated CA private keys carefully and remove them from client trust stores when they are no longer needed.

Contributing

Issues and pull requests are welcome. Please include a clear description, reproduction steps when reporting bugs, and tests for behavior changes when practical.

License

This project is licensed under the MIT License.

About

Customizing TLS (JA3) Fingerprints through HTTP Proxy

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages