- Per-listener `retries` overrides global default (0 = inherit)
- Pool-level `allowed_protos` filters proxies during merge
- Connection pooling documented in CHEATSHEET.md
- Both features exposed in /config and /status API responses
- 12 new tests (config parsing, API exposure, merge filtering)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Per-listener username/password auth via `auth:` config key. When set,
clients must negotiate method 0x02 and pass RFC 1929 subnegotiation;
no-auth (0x00) is rejected to prevent downgrade. Listeners without
`auth` keep current no-auth behavior.
Includes auth_failures metric, API integration (/status auth flag,
/config auth_users count without exposing passwords), config parsing
with YAML int coercion, integration tests (success, failure, method
rejection, no-auth unchanged), and documentation updates.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Per-listener bypass rules skip the chain for local/private destinations
(CIDR, exact IP/hostname, domain suffix). Weighted multi-candidate pool
selection biases toward pools with more alive proxies. End-to-end
integration tests validate the full client->s5p->hop->target path using
mock SOCKS5 proxies.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow listeners to mix named pools in a single chain using pool:name
syntax. Bare "pool" continues to use the listener's default pool.
Replaces pool_hops field with pool_seq list; pool_hops is now a
backward-compatible property. Each hop draws from its own pool and
failure reporting targets the correct source pool.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add proxy_pools: top-level config (dict of name -> pool config) so
listeners can draw from different proxy sources. Each pool has
independent sources, health testing, state persistence, and refresh
cycles.
- PoolSourceConfig gains mitm: bool|None for API ?mitm=0/1 filtering
- ListenerConfig gains pool_name for named pool assignment
- ProxyPool gains name param with prefixed log messages and
per-name state file derivation (pool-{name}.json)
- server.py replaces single proxy_pool with proxy_pools dict,
validates listener pool references at startup, per-listener closure
- API /pool merges all pools (with pool field on multi-pool entries),
/status and /config expose per-pool summaries
- Backward compat: singular proxy_pool: registers as "default"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New top-level tor_nodes list distributes traffic across multiple Tor
SOCKS proxies. First hop is replaced at connection time by round-robin
selection; health tests also rotate across all nodes. FirstHopPools
are created for each node when pool_size > 0.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Auto-scale test concurrency to ~10% of proxy count, capped by
test_concurrency config ceiling (default raised from 5 to 25).
Prevents saturating upstream Tor when pool size varies.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.
Replace _http_check (HTTP GET to httpbin.org) with _tls_check that
performs a TLS handshake through the proxy chain. Multiple targets
(google, cloudflare, amazon) rotated round-robin eliminate the single
point of failure. Lighter, faster, harder to block than HTTP.
- Add test_targets config field (replaces test_url)
- Backward compat: legacy test_url extracts hostname automatically
- Add ssl.create_default_context() and round-robin index to ProxyPool
- Update docs (example.yaml, USAGE.md, CHEATSHEET.md)
Start/stop TorController in serve() lifecycle when tor: config
is present. Adds GET /tor (status) and POST /tor/newnym (signal)
endpoints to the control API. Logs control address at startup.
Adds tor: section and api_listen to example config.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add max_connections config (default 256) with -m/--max-connections CLI
flag. Server wraps on_client in asyncio.Semaphore to prevent fd
exhaustion under load. Value reloads on SIGHUP; active connections
drain normally. Also adds pool_size/pool_max_idle config fields and
first_hop_pool wiring in server.py (used by next commits), and fixes
asyncio.TimeoutError -> TimeoutError lint warnings.
Add hot reload section to USAGE with reloadable settings table.
Add dead proxy reporting section with report_url config and payload
format. Update example.yaml, ROADMAP, TASKS, TODO, CHEATSHEET.
Update all docs for managed proxy pool: README, USAGE, CHEATSHEET,
PROJECT, TASKS, and example config. Document multi-source config,
proxy file format, health testing, persistence, and legacy compat.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Retry failed proxy connections with a fresh random proxy on each
attempt (configurable via retries setting, proxy_source only).
Track connection metrics and log summary every 60s and on shutdown.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fetches proxies from an HTTP API, caches them in memory, and appends
a random proxy to the chain on each connection. Supports proto/country
filters and configurable refresh interval.
Config: proxy_source.url, proto, country, limit, refresh
CLI: -S/--proxy-source URL
Asyncio-based SOCKS5 server that tunnels connections through
configurable chains of SOCKS5, SOCKS4/4a, and HTTP CONNECT proxies.
Tor integration via standard SOCKS5 hop.