feat: multi-listener with configurable proxy chaining

Each listener binds to its own port with an independent chain.
The "pool" keyword in a chain appends a random alive proxy from
the shared pool; multiple pool entries = multiple hops.

  :1080 -> Tor only (0 pool hops)
  :1081 -> Tor + 1 pool proxy
  :1082 -> Tor + 2 pool proxies

Shared resources (ProxyPool, Tor, metrics, semaphore, API) are
reused across listeners. FirstHopPool is shared per unique first
hop. Backward compatible: old listen/chain format still works.
This commit is contained in:
user
2026-02-17 22:03:37 +01:00
parent ba60d087c0
commit 7dc3926f48
11 changed files with 495 additions and 62 deletions

View File

@@ -11,6 +11,7 @@ through configurable chains of SOCKS4, SOCKS5, and HTTP CONNECT proxies.
- Per-hop authentication (username/password)
- DNS leak prevention (domain names forwarded to proxies, never resolved locally)
- Tor integration (SOCKS5 hop + control port NEWNYM for circuit rotation)
- Multi-listener: different ports with different chain depths (Tor-only, Tor+1, Tor+2)
- Managed proxy pool: multiple sources (API + file), health-tested, weighted selection
- Per-proxy failure backoff (60s cooldown), stale proxy expiry, chain pre-flight
- Fast warm start (seconds on restart vs minutes on cold start)
@@ -66,15 +67,31 @@ cp config/example.yaml config/s5p.yaml
```
```yaml
listen: 127.0.0.1:1080
timeout: 10
retries: 3
max_connections: 256 # concurrent connection limit
pool_size: 8 # pre-warmed connections to first hop
api_listen: 127.0.0.1:1081 # control API (disabled by default)
chain:
- socks5://127.0.0.1:9050 # Tor
# Multi-listener: each port gets a different chain depth
listeners:
- listen: 0.0.0.0:1080
chain:
- socks5://127.0.0.1:9050 # Tor only
- listen: 0.0.0.0:1081
chain:
- socks5://127.0.0.1:9050
- pool # Tor + 1 pool proxy
- listen: 0.0.0.0:1082
chain:
- socks5://127.0.0.1:9050
- pool # Tor + 2 pool proxies
- pool
# Old single-listener format still works:
# listen: 127.0.0.1:1080
# chain:
# - socks5://127.0.0.1:9050
tor:
control_port: 9051 # Tor control port (NEWNYM)
@@ -117,11 +134,13 @@ Options:
## How Chaining Works
```
Client -> s5p -> [static chain] -> [weighted alive proxy from pool] -> Destination
:1080 Client -> s5p -> Tor -> Destination (0 pool hops)
:1081 Client -> s5p -> Tor -> [pool proxy] -> Destination (1 pool hop)
:1082 Client -> s5p -> Tor -> [pool proxy] -> [pool proxy] -> Dest (2 pool hops)
```
s5p connects to Hop1 via TCP, negotiates the hop protocol (SOCKS5/4/HTTP),
then over that tunnel negotiates with Hop2, and so on. If a proxy pool is
configured, an alive proxy is appended per-connection, weighted toward those
with the most recent successful health test. Each hop only sees its immediate
neighbors.
configured, alive proxies are appended per-connection (one per `pool` entry),
weighted toward those with the most recent successful health test. Each hop
only sees its immediate neighbors.