purrformant advance proxy server that supports protocol detection (socks5, socks4, http, https, etc on the same port) and protocol translation (http -> socks5, socks5 -> http, etc), supports proxy chains, lists, and more advance settings. https://socks.cat
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Zoa Hickenlooper 336dfbfb18
Some checks failed
CI / fmt (push) Successful in 52s
CI / clippy (push) Failing after 5m42s
CI / coverage (push) Failing after 11s
CI / build-test (push) Failing after 3m52s
Merge pull request 'Update Rust crate rand to 0.10.0' (#19) from renovate/rand-0.x into main
Reviewed-on: #19
2026-07-28 20:42:29 +00:00
.forgejo/workflows Update actions/checkout action to v7 2026-07-27 13:45:47 +00:00
docs/superpowers 📝 plan — web-backend multiplexing (3 tasks: config, detector, reverse-proxy) 2026-07-23 00:45:17 -04:00
src 🐛 web_backend — decrement active_connections on Ok paths (was leaking the gauge); count relayed bytes; generic test host 2026-07-23 04:29:28 -04:00
tests/integration ♻️ untangled the yarn — purroute is its own cat now 2026-06-18 17:51:29 -04:00
wiki 📝 wiki + config example for tagged exits & ip auth 2026-06-23 18:16:06 -04:00
.gitignore ♻️ untangled the yarn — purroute is its own cat now 2026-06-18 17:51:29 -04:00
Cargo.lock Merge pull request 'Update Rust crate rand to 0.10.0' (#19) from renovate/rand-0.x into main 2026-07-28 20:42:29 +00:00
Cargo.toml Update Rust crate rand to 0.10.0 2026-07-27 08:15:48 +00:00
CLAUDE.md a cat needs no database — single-user mode + tidy up 2026-06-23 16:25:31 -04:00
config.toml.example config — add [router].web_backend (optional reverse-proxy target) 2026-07-23 04:14:10 -04:00
docker-compose.yml *paws at keyboard excitedly* 2025-02-22 20:48:15 -07:00
Dockerfile *paws at keyboard excitedly* 2025-02-22 20:48:15 -07:00
LICENSE ♻️ untangled the yarn — purroute is its own cat now 2026-06-18 17:51:29 -04:00
README.md 📝 wiki + config example for tagged exits & ip auth 2026-06-23 18:16:06 -04:00
renovate.json Add renovate.json 2026-07-27 02:55:12 +00:00
rustfmt.toml ✏️ drop mullvad reference from rustfmt.toml 2026-06-29 02:14:16 -04:00

purroute

An auto-detecting proxy router/gateway. It listens on a local address, detects the inbound proxy protocol (SOCKS5, SOCKS4/4a, HTTP, HTTPS-CONNECT) from the first bytes of each connection, and forwards traffic upstream through a single proxy or a multi-hop chain — translating between protocols as needed. It enforces per-user auth and bandwidth limits through a pluggable AuthBackend.

purroute is self-contained: accounts come from a pluggable AuthBackend, so it runs with no database at all (users listed in config.toml) or against PostgreSQL for many users. It only ever reads (username, secret, bandwidth_limit) and reports usage.

Features

  • Auto-detection of the inbound protocol — one endpoint serves every client type.
  • Protocol translation across all inbound→upstream combinations.
  • Multi-hop chaining (strict or random order) for every inbound protocol.
  • Tag-based exit selection — tag upstreams with country/city/isp/type and let clients pick an exit by encoding routing tokens in the proxy username (me-country-us,de-type-residential-session-ab12); comma = a set to rotate across, session pins one exit, no match fails closed.
  • Pluggable authentication (AuthBackend): inline users (no database) or PostgreSQL, by username/password or source IP (allowed_ips), with an optional per-account default_selection for credential-less connections.
  • Local-only Prometheus /metrics endpoint.

Quick start (single user, no database)

cp config.toml.example config.toml      # main() reads "config.toml" from cwd
# config.toml: a [router], one [[proxy]], and one [[user]] — no [database] needed
cargo run --release
[router]
listen = "127.0.0.1:1080"
auth = true
chain = "exit"

[[user]]
username = "me"
password = "hunter2"
# bandwidth_limit = 1073741824    # optional, bytes; omit for unlimited
# allowed_ips = ["10.0.0.0/24"]   # optional, source IPs that skip auth
# default_selection = "country-us" # optional, route for credential-less conns

[[proxy]]
label = "exit"
proxy_type = "Socks5"
address = "10.0.0.1:1080"
# country = "us"                  # optional tags for routing-token selection
# city = "nyc"
# isp = "comcast"
# type = "residential"

Point any proxy client at 127.0.0.1:1080 with me:hunter2. With tagged upstreams, select an exit by appending tokens to the username, e.g. me-country-us-type-residential.

For many users, add a [database] section (and docker-compose up --build for a local PostgreSQL) instead of [[user]] blocks. See config.toml.example for the full model; CLAUDE.md documents the internals.

Auth backend

The router depends only on the AuthBackend trait (src/auth.rs):

async fn authenticate(&self, username: &str, secret: &str) -> Result<Option<Account>, AuthError>;
async fn report_usage(&self, id: i64, bytes_in: u64, bytes_out: u64) -> Result<(), AuthError>;

It ships with StaticAuthBackend (inline users, no database) and PostgresAuthBackend. Implement the trait against an HTTP API or any other store to plug in your own account source.

License

GPL-3.0-or-later. See LICENSE.