Files
s5p/docs/CHEATSHEET.md
user d4e3638143 feat: per-listener latency tracking
Each listener now tracks chain setup latency independently via a
dict[str, LatencyTracker] on Metrics. The global aggregate stays for
summary output. /status embeds per-listener latency on each listener
entry; /metrics includes a listener_latency map keyed by host:port.
2026-02-18 08:14:09 +01:00

5.7 KiB

s5p -- Cheatsheet

CLI

s5p                                         # direct, listen :1080
s5p -C socks5://127.0.0.1:9050             # through Tor
s5p -C socks5://tor:9050,http://px:8080    # Tor + HTTP proxy
s5p -c config/s5p.yaml                      # from config file
s5p -l 0.0.0.0:9999                         # custom listen address
s5p -t 30                                   # 30s per-hop timeout
s5p -v                                      # debug logging
s5p -q                                      # errors only
s5p -S http://api:8081/proxies              # proxy source API
s5p -r 5                                   # retry up to 5 proxies
s5p -m 512                                 # max concurrent connections
s5p --api 127.0.0.1:1081                   # enable control API
s5p --cprofile                              # profile to s5p.prof
s5p --cprofile out.prof                     # profile to custom file
s5p --tracemalloc                           # memory profile (top 10)
s5p --tracemalloc 20                        # memory profile (top 20)

Container

make build   # podman-compose build
make up      # podman-compose up -d
make logs    # podman-compose logs -f
make down    # podman-compose down

Volumes: ./src (ro), ./config/s5p.yaml (ro), ~/.cache/s5p/data (pool state + profiles)

Config

cp config/example.yaml config/s5p.yaml     # create live config (gitignored)

Multi-Listener (config)

listeners:
  - listen: 0.0.0.0:1080
    chain:
      - socks5://127.0.0.1:9050
      - pool                                 # Tor + 2 pool hops
      - pool
  - listen: 0.0.0.0:1081
    chain:
      - socks5://127.0.0.1:9050
      - pool                                 # Tor + 1 pool hop
  - listen: 0.0.0.0:1082
    chain:
      - socks5://127.0.0.1:9050             # Tor only

Performance Tuning (config)

max_connections: 256   # concurrent connection cap
pool_size: 8           # pre-warmed TCP conns to first hop (0 = off)
pool_max_idle: 30      # evict idle pooled conns (seconds)

Proxy Pool (config)

proxy_pool:
  sources:
    - url: http://10.200.1.250:8081/proxies
      proto: socks5
      limit: 1000
    - file: /etc/s5p/proxies.txt
  refresh: 300       # re-fetch interval
  test_interval: 120 # health test cycle
  test_targets:      # TLS handshake targets (round-robin)
    - www.google.com
    - www.cloudflare.com
    - www.amazon.com
  max_fails: 3       # evict after N fails
  report_url: ""     # POST dead proxies (optional)

Tor Control Port (config)

tor:
  control_port: 9051
  password: ""               # or cookie_file: /path/to/cookie
  newnym_interval: 60        # auto-rotate every 60s (0 = manual)
curl -s http://127.0.0.1:1081/tor | jq .                  # status
curl -s -X POST http://127.0.0.1:1081/tor/newnym | jq .   # new circuit

Hot Reload

kill -HUP $(pidof s5p)                    # reload config
podman kill --signal HUP s5p              # container reload

Proxy File Format

# one proxy URL per line
socks5://1.2.3.4:1080
socks5://user:pass@5.6.7.8:1080
http://proxy.example.com:8080

Proxy URLs

socks5://host:port
socks5://user:pass@host:port
socks4://host:port
http://host:port
http://user:pass@host:port

Control API

s5p --api 127.0.0.1:1081 -c config/s5p.yaml    # enable API

curl -s http://127.0.0.1:1081/status | jq .     # runtime status
curl -s http://127.0.0.1:1081/metrics | jq .    # full metrics
curl -s http://127.0.0.1:1081/pool | jq .       # all proxies
curl -s http://127.0.0.1:1081/pool/alive | jq . # alive only
curl -s http://127.0.0.1:1081/config | jq .     # current config
curl -s -X POST http://127.0.0.1:1081/reload    # reload config
curl -s -X POST http://127.0.0.1:1081/pool/test # health test now

Testing

# Check exit IP
curl -x socks5h://127.0.0.1:1080 https://httpbin.org/ip

# Tor check
curl -x socks5h://127.0.0.1:1080 https://check.torproject.org/api/ip

# Verbose curl
curl -v -x socks5h://127.0.0.1:1080 https://example.com

# With timeout
curl --max-time 30 -x socks5h://127.0.0.1:1080 https://example.com

Profiling

# Enable in compose.yaml: uncomment the command line
python -m pstats s5p.prof                   # interactive stats viewer
python -m pstats ~/.cache/s5p/s5p.prof      # container profile output

Metrics Log

metrics: conn=1842 ok=1790 fail=52 retries=67 active=3 in=50.0M out=1.0G rate=4.72/s p50=198.3ms p95=890.1ms up=1h01m01s pool=42/65

Metrics JSON (/metrics)

curl -s http://127.0.0.1:1081/metrics | jq .
{
  "connections": 1842,
  "success": 1790,
  "rate": 4.72,
  "latency": {"count": 1000, "min": 45.2, "max": 2841.7, "avg": 312.4, "p50": 198.3, "p95": 890.1, "p99": 1523.6},
  "listener_latency": {
    "0.0.0.0:1080": {"count": 500, "p50": 1800.2, "p95": 8200.1, "...": "..."},
    "0.0.0.0:1081": {"count": 300, "p50": 1000.1, "p95": 3500.2, "...": "..."},
    "0.0.0.0:1082": {"count": 200, "p50": 400.1, "p95": 1200.5, "...": "..."}
  }
}

Per-listener latency also appears in /status under each listener entry.

Troubleshooting

Symptom Check
Connection refused Is Tor running? ss -tlnp | grep 9050
Timeout Increase -t, check proxy reachability
DNS leak Use socks5h:// (not socks5://) in client
Auth failed Verify credentials in proxy URL
Port in use fuser -k 1080/tcp to free the port
Proxy keeps failing Backoff penalizes for 60s; check pool= in metrics
"static chain unreachable" Tor/upstream hop is down; pool tests skipped
Slow startup Normal on cold start; warm restarts serve instantly from state