- Rust 99.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .forgejo/workflows | ||
| docs/superpowers | ||
| src | ||
| tests/integration | ||
| wiki | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CLAUDE.md | ||
| config.toml.example | ||
| docker-compose.yml | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
| renovate.json | ||
| rustfmt.toml | ||
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/typeand 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,sessionpins 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-accountdefault_selectionfor credential-less connections. - Local-only Prometheus
/metricsendpoint.
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.