diff --git a/PROJECT.md b/PROJECT.md index f0e49be..24b4d94 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -58,3 +58,5 @@ All other functionality uses Python stdlib (`asyncio`, `socket`, `struct`). - **Stale expiry** -- proxies dropped from sources evicted after 3 refresh cycles if not alive - **Chain pre-flight** -- static chain tested before pool health tests; skip on failure - **Warm start** -- quick-test alive subset on restart, defer full test to background +- **SIGHUP reload** -- re-read config, update pool settings, re-fetch sources +- **Dead reporting** -- POST evicted proxies to upstream API for list quality feedback diff --git a/README.md b/README.md index 1fd9d9e..013cd72 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ through configurable chains of SOCKS4, SOCKS5, and HTTP CONNECT proxies. - Per-proxy failure backoff (60s cooldown), stale proxy expiry, chain pre-flight - Fast warm start (seconds on restart vs minutes on cold start) - Connection retry with proxy rotation (configurable attempts) +- Dead proxy reporting to upstream API (optional `report_url`) +- SIGHUP hot reload (timeout, retries, log_level, pool config) - Connection metrics with pool stats (logged periodically and on shutdown) - Container-ready (Alpine-based, podman/docker) - Graceful shutdown (SIGTERM/SIGINT) diff --git a/ROADMAP.md b/ROADMAP.md index f28810c..8208f8c 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -17,6 +17,8 @@ - [x] Pool stats in periodic metrics log - [x] Fast warm start (deferred full health test) - [x] Static chain health check (pre-flight before pool tests) +- [x] SIGHUP hot config reload +- [x] Dead proxy reporting to source API ## v0.2.0 @@ -29,7 +31,6 @@ - [ ] UDP ASSOCIATE support (SOCKS5 UDP relay) - [ ] BIND support - [ ] Chain randomization (random order, random subset) -- [ ] Hot-reload config on SIGHUP ## v1.0.0 diff --git a/TASKS.md b/TASKS.md index 79340a2..f09d6e1 100644 --- a/TASKS.md +++ b/TASKS.md @@ -25,6 +25,8 @@ - [x] Pool stats in periodic metrics log (`pool=alive/total`) - [x] Fast warm start (quick-test alive subset, defer full test) - [x] Static chain health check (skip pool tests if chain unreachable) +- [x] SIGHUP hot config reload (timeout, retries, log_level, pool config) +- [x] Dead proxy reporting (`report_url` POST evicted proxies to API) ## Next - [ ] Integration tests with mock proxy server diff --git a/TODO.md b/TODO.md index 47aee0d..c22bbf1 100644 --- a/TODO.md +++ b/TODO.md @@ -5,9 +5,7 @@ - SOCKS5 BIND and UDP ASSOCIATE commands - 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 -- Report dead proxies back to source API ## Performance diff --git a/config/example.yaml b/config/example.yaml index cfc876b..7b9333e 100644 --- a/config/example.yaml +++ b/config/example.yaml @@ -32,6 +32,7 @@ chain: # test_concurrency: 5 # parallel health tests # max_fails: 3 # consecutive fails before eviction # state_file: "" # empty = ~/.cache/s5p/pool.json +# report_url: "" # POST dead proxies here (optional) # Legacy proxy source (still supported, auto-converts to proxy_pool): # proxy_source: diff --git a/docs/CHEATSHEET.md b/docs/CHEATSHEET.md index cacd994..8bd1109 100644 --- a/docs/CHEATSHEET.md +++ b/docs/CHEATSHEET.md @@ -44,6 +44,14 @@ proxy_pool: refresh: 300 # re-fetch interval test_interval: 120 # health test cycle max_fails: 3 # evict after N fails + report_url: "" # POST dead proxies (optional) +``` + +## Hot Reload + +```bash +kill -HUP $(pidof s5p) # reload config +podman kill --signal HUP s5p # container reload ``` ## Proxy File Format diff --git a/docs/USAGE.md b/docs/USAGE.md index b94e40f..e564b7b 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -107,6 +107,7 @@ proxy_pool: test_concurrency: 5 # parallel health tests max_fails: 3 # evict after N consecutive failures state_file: "" # empty = ~/.cache/s5p/pool.json + report_url: "" # POST dead proxies here (optional) ``` ### Sources @@ -180,6 +181,24 @@ of all proxies runs in the background. This reduces startup blocking from minutes to seconds on warm restarts. Cold starts (no state file) test all proxies before serving. +### Dead proxy reporting + +When `report_url` is set, evicted proxies are POSTed to the upstream API +after each health test cycle. This helps the source maintain list quality. + +```yaml +proxy_pool: + report_url: http://10.200.1.250:8081/proxies/report +``` + +Payload format: + +```json +{"dead": [{"proto": "socks5", "proxy": "1.2.3.4:1080"}, ...]} +``` + +Reporting is fire-and-forget; failures are logged at debug level only. + ### CLI shorthand ```bash @@ -208,6 +227,30 @@ retries: 5 # try up to 5 different proxies per connection s5p -r 5 -C socks5://127.0.0.1:9050 -S http://api:8081/proxies ``` +## Hot Reload + +Send `SIGHUP` to reload the config file without restarting: + +```bash +kill -HUP $(pidof s5p) +# or in a container: +podman kill --signal HUP s5p +``` + +Settings reloaded on SIGHUP: + +| Setting | Effect | +|---------|--------| +| `timeout` | Per-connection timeout | +| `retries` | Max retry attempts | +| `log_level` | Logging verbosity | +| `proxy_pool.*` | Sources, intervals, thresholds | + +Settings that require a restart: `listen`, `chain`. + +Requires `-c` / `--config` to know which file to re-read. Without a +config file, SIGHUP is ignored with a warning. + ## Metrics s5p tracks connection metrics and logs a summary every 60 seconds and on