Files
s5p/docs/USAGE.md
user fc1dea70f4 docs: update project docs for warm start and chain health check
Add warm start and chain pre-flight sections to USAGE. Mark both
features complete in ROADMAP and TASKS. Remove implemented items
from TODO. Update README, PROJECT, and CHEATSHEET.
2026-02-15 16:00:23 +01:00

7.2 KiB

s5p -- Usage

Basic Usage

# Direct proxy (no chain, just a SOCKS5 server)
s5p

# Through Tor
s5p -C socks5://127.0.0.1:9050

# Through Tor + another proxy
s5p -C socks5://127.0.0.1:9050,socks5://proxy:1080

# Custom listen address
s5p -l 0.0.0.0:9999 -C socks5://127.0.0.1:9050

# From config file
s5p -c config/s5p.yaml

# With proxy source API (rotate exit proxy per-connection)
s5p -C socks5://127.0.0.1:9050 -S http://10.200.1.250:8081/proxies

# Debug mode
s5p -v -C socks5://127.0.0.1:9050

Configuration

Copy the tracked example to create your live config:

cp config/example.yaml config/s5p.yaml
File Tracked Purpose
config/example.yaml yes Template with placeholder addresses
config/s5p.yaml no (gitignored) Live config with real proxy addresses
listen: 127.0.0.1:1080
timeout: 10
retries: 3
log_level: info

chain:
  - socks5://127.0.0.1:9050

proxy_pool:
  sources:
    - url: http://10.200.1.250:8081/proxies
      proto: socks5
      limit: 1000
    - file: /etc/s5p/proxies.txt
  refresh: 300
  test_interval: 120
  test_url: http://httpbin.org/ip
  test_timeout: 15
  test_concurrency: 5
  max_fails: 3
  state_file: ""      # empty = ~/.cache/s5p/pool.json

Proxy URL Format

protocol://[username:password@]host[:port]
Protocol Default Port Auth Support
socks5 1080 username/password
socks4 1080 none
http 8080 Basic

Container

make build   # build image
make up      # start container (detached)
make logs    # follow logs
make down    # stop and remove container

Source (./src) and config (./config/s5p.yaml) are mounted read-only into the container. Edit locally, restart to pick up changes.

Proxy Pool

Managed proxy pool with multiple sources, health testing, and persistence. Appends an alive proxy after the static chain on each connection, weighted by recency of last successful health test.

proxy_pool:
  sources:
    - url: http://10.200.1.250:8081/proxies
      proto: socks5         # optional: filter by protocol
      country: US           # optional: filter by country
      limit: 1000           # max proxies to fetch from API
    - file: /etc/s5p/proxies.txt  # text file, one proxy URL per line
  refresh: 300              # re-fetch sources every 300 seconds
  test_interval: 120        # health test cycle every 120 seconds
  test_url: http://httpbin.org/ip  # URL for health checks
  test_timeout: 15          # per-test timeout (seconds)
  test_concurrency: 5       # parallel health tests
  max_fails: 3              # evict after N consecutive failures
  state_file: ""            # empty = ~/.cache/s5p/pool.json

Sources

Type Config key Description
HTTP API url JSON: {"proxies": [{"proto": "socks5", "proxy": "host:port"}, ...]}
Text file file One proxy URL per line, # comments, blank lines ignored

Proxy file format

# Exit proxies
socks5://1.2.3.4:1080
socks5://user:pass@5.6.7.8:1080
http://proxy.example.com:8080

Health testing

Each cycle tests all proxies through the full chain (static chain + proxy) by sending an HTTP GET to test_url. Proxies are marked alive on 200 response. After max_fails consecutive failures, a proxy is evicted.

Before each health test cycle, the static chain is tested without any pool proxy. If the chain itself is unreachable (e.g., Tor is down), proxy tests are skipped entirely and a warning is logged. This prevents false mass-failure and unnecessary evictions.

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

Failure backoff

When a proxy fails during an actual connection attempt (not just a health test), its weight is penalized for 60 seconds. The penalty ramps linearly from floor (0.01) back to normal over that window. This prevents retries from repeatedly selecting a proxy that just failed.

Stale proxy expiry

Proxies not returned by any source for 3 consecutive refresh cycles and not currently alive are automatically evicted. This cleans up proxies removed upstream faster than waiting for max_fails health test failures.

Persistence

Pool state is saved to state_file (default: ~/.cache/s5p/pool.json) after each refresh/health cycle and on shutdown. On startup, previously-alive proxies are loaded for fast warm starts.

Warm start

When restarting with an existing state file, only the previously-alive proxies are tested before the server starts accepting connections. A full health test 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.

CLI shorthand

s5p -C socks5://127.0.0.1:9050 -S http://10.200.1.250:8081/proxies

The -S flag creates a pool with a single API source (uses defaults for all other pool settings).

Legacy config

The old proxy_source key is still supported and auto-converts to proxy_pool with a single API source. proxy_pool takes precedence if both are present.

Connection Retry

When a proxy pool is active, s5p retries failed connections with a different random proxy. Controlled by the retries setting (default: 3). Static-only chains do not retry (retrying the same chain is pointless).

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

Metrics

s5p tracks connection metrics and logs a summary every 60 seconds and on shutdown:

metrics: conn=142 ok=98 fail=44 retries=88 active=3 in=1.2M out=4.5M up=0h05m12s pool=42/65
Counter Meaning
conn Total incoming connections
ok Successfully connected + relayed
fail All retries exhausted
retries Total retry attempts
active Currently relaying
in Bytes client -> remote
out Bytes remote -> client
up Server uptime
pool Alive/total proxies (only when pool is active)

Profiling

# Run with cProfile enabled
s5p --cprofile -c config/s5p.yaml

# Custom output file
s5p --cprofile output.prof -c config/s5p.yaml

# Analyze after stopping
python -m pstats s5p.prof

Testing the Proxy

# Check exit IP via Tor
curl --proxy socks5h://127.0.0.1:1080 https://check.torproject.org/api/ip

# Fetch a page
curl --proxy socks5h://127.0.0.1:1080 https://example.com

# Use with Firefox: set SOCKS5 proxy to 127.0.0.1:1080, enable remote DNS

Note: use socks5h:// (not socks5://) with curl to send DNS through the proxy.

Chain Order

Hops are traversed left-to-right:

-C hop1,hop2,hop3

Client -> s5p -> hop1 -> hop2 -> hop3 -> Destination

Each hop only sees its immediate neighbors.