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.
204 lines
5.7 KiB
Markdown
204 lines
5.7 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
cp config/example.yaml config/s5p.yaml # create live config (gitignored)
|
|
```
|
|
|
|
## Multi-Listener (config)
|
|
|
|
```yaml
|
|
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)
|
|
|
|
```yaml
|
|
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)
|
|
|
|
```yaml
|
|
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)
|
|
|
|
```yaml
|
|
tor:
|
|
control_port: 9051
|
|
password: "" # or cookie_file: /path/to/cookie
|
|
newnym_interval: 60 # auto-rotate every 60s (0 = manual)
|
|
```
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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`)
|
|
|
|
```bash
|
|
curl -s http://127.0.0.1:1081/metrics | jq .
|
|
```
|
|
|
|
```json
|
|
{
|
|
"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 |
|