From 0ed9142b1aca79ae944352c58ed5b89612da1e79 Mon Sep 17 00:00:00 2001 From: user Date: Sun, 15 Feb 2026 15:49:54 +0100 Subject: [PATCH] docs: update project docs for weighted proxy selection Add selection weight section to USAGE.md with decay formula and reference table. Mark feature complete in ROADMAP and TASKS. Update README and PROJECT descriptions. --- PROJECT.md | 1 + README.md | 9 +++++---- ROADMAP.md | 1 + TASKS.md | 1 + TODO.md | 2 +- docs/USAGE.md | 17 ++++++++++++++++- 6 files changed, 25 insertions(+), 6 deletions(-) diff --git a/PROJECT.md b/PROJECT.md index 02af7c7..8cbf2af 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -53,3 +53,4 @@ All other functionality uses Python stdlib (`asyncio`, `socket`, `struct`). - **Graceful shutdown** -- SIGTERM/SIGINT handled in the event loop for clean container stops - **Config split** -- tracked example template, gitignored live config with real addresses - **Proxy pool** -- multi-source (API + file), health-tested, persistent, auto-cleaned +- **Weighted selection** -- recently-tested proxies preferred via recency decay weight diff --git a/README.md b/README.md index fe2357c..3ed7912 100644 --- a/README.md +++ b/README.md @@ -11,7 +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 (Tor is just another SOCKS5 hop) -- Managed proxy pool: multiple sources (API + file), health-tested, auto-cleaned +- Managed proxy pool: multiple sources (API + file), health-tested, weighted selection - Connection retry with proxy rotation (configurable attempts) - Connection metrics (logged periodically and on shutdown) - Container-ready (Alpine-based, podman/docker) @@ -97,10 +97,11 @@ Options: ## How Chaining Works ``` -Client -> s5p -> [static chain] -> [random alive proxy from pool] -> Destination +Client -> s5p -> [static chain] -> [weighted alive proxy from pool] -> Destination ``` 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, a random health-tested proxy is appended to the chain per-connection. -Each hop only sees its immediate neighbors. +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. diff --git a/ROADMAP.md b/ROADMAP.md index 26a6a6b..eb4b713 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -11,6 +11,7 @@ - [x] Graceful SIGTERM/SIGINT shutdown - [x] cProfile support - [x] Dynamic proxy source API integration +- [x] Weighted proxy selection (recency-based) ## v0.2.0 diff --git a/TASKS.md b/TASKS.md index 0f4dc99..a90c57d 100644 --- a/TASKS.md +++ b/TASKS.md @@ -19,6 +19,7 @@ - [x] Connection retry with proxy rotation - [x] Connection metrics (periodic + shutdown logging) - [x] Managed proxy pool (multi-source, health-tested, persistent) +- [x] Weighted proxy selection (prefer recently-tested proxies) ## Next - [ ] Integration tests with mock proxy server diff --git a/TODO.md b/TODO.md index 8ab7013..1c0503f 100644 --- a/TODO.md +++ b/TODO.md @@ -3,7 +3,7 @@ ## Features - SOCKS5 BIND and UDP ASSOCIATE commands -- Chain randomization modes (random, round-robin) +- Chain randomization modes (round-robin, sticky-per-destination) - Per-destination chain rules (bypass chain for local addresses) - Hot config reload on SIGHUP - Systemd socket activation diff --git a/docs/USAGE.md b/docs/USAGE.md index fffaa49..dcf72a6 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -89,7 +89,8 @@ into the container. Edit locally, restart to pick up changes. ## Proxy Pool Managed proxy pool with multiple sources, health testing, and persistence. -Appends a random alive proxy after the static chain on each connection. +Appends an alive proxy after the static chain on each connection, weighted +by recency of last successful health test. ```yaml proxy_pool: @@ -133,6 +134,20 @@ After `max_fails` consecutive failures, a proxy is evicted. Mass-failure guard: if >90% of tests fail in one cycle, eviction is skipped (likely the static chain is broken, not the proxies). +### Selection weight + +Alive proxies are selected with probability proportional to their recency +weight: `1 / (1 + age / 300)`, where `age` is seconds since the last +successful health test. This favors freshly-verified proxies over stale ones: + +| Age | Weight | +|-----|--------| +| 0 s (just tested) | ~1.0 | +| 5 min | ~0.5 | +| 10 min | ~0.33 | +| 30 min | ~0.1 | +| Never tested | 0.01 | + ### Persistence Pool state is saved to `state_file` (default: `~/.cache/s5p/pool.json`) after