Update USAGE, CHEATSHEET, README, PROJECT, and TASKS for the three performance improvements: max_connections semaphore, async HTTP source fetching, and first-hop TCP connection pool.
356 lines
9.8 KiB
Markdown
356 lines
9.8 KiB
Markdown
# s5p -- Usage
|
|
|
|
## Basic Usage
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
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 |
|
|
|
|
```yaml
|
|
listen: 127.0.0.1:1080
|
|
timeout: 10
|
|
retries: 3
|
|
log_level: info
|
|
max_connections: 256 # concurrent connection limit (backpressure)
|
|
pool_size: 0 # pre-warmed TCP connections to first hop (0 = disabled)
|
|
pool_max_idle: 30 # max idle time for pooled connections (seconds)
|
|
|
|
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
|
|
|
|
```bash
|
|
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. `~/.cache/s5p` is mounted as `/data` for pool state
|
|
and profile output. 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.
|
|
|
|
```yaml
|
|
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
|
|
report_url: "" # POST dead proxies here (optional)
|
|
```
|
|
|
|
### 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.
|
|
|
|
### 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
|
|
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).
|
|
|
|
```yaml
|
|
retries: 5 # try up to 5 different proxies per connection
|
|
```
|
|
|
|
```bash
|
|
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 |
|
|
| `max_connections` | Concurrent connection limit |
|
|
| `proxy_pool.*` | Sources, intervals, thresholds |
|
|
|
|
Settings that require a restart: `listen`, `chain`, `pool_size`, `pool_max_idle`.
|
|
|
|
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
|
|
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
|
|
|
|
```bash
|
|
# Run with cProfile enabled
|
|
s5p --cprofile -c config/s5p.yaml
|
|
|
|
# Custom output file
|
|
s5p --cprofile output.prof -c config/s5p.yaml
|
|
|
|
# Container: uncomment the command line in compose.yaml
|
|
# command: ["-c", "/app/config/s5p.yaml", "--cprofile", "/data/s5p.prof"]
|
|
# Profile output persists at ~/.cache/s5p/s5p.prof on the host.
|
|
|
|
# Analyze after stopping
|
|
python -m pstats s5p.prof
|
|
```
|
|
|
|
## Testing the Proxy
|
|
|
|
```bash
|
|
# 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.
|
|
|
|
## Connection Limit
|
|
|
|
s5p caps concurrent connections with an `asyncio.Semaphore`. When all
|
|
slots are taken, new clients backpressure at TCP accept (the connection
|
|
is accepted but the handler waits for a slot).
|
|
|
|
```yaml
|
|
max_connections: 256 # default
|
|
```
|
|
|
|
```bash
|
|
s5p -m 512 # override via CLI
|
|
```
|
|
|
|
The `max_connections` value is reloaded on SIGHUP. Connections already
|
|
in flight are not affected -- new limits take effect as active connections
|
|
close.
|
|
|
|
## First-Hop Connection Pool
|
|
|
|
Pre-warms TCP connections to the first hop in the chain, avoiding the
|
|
TCP handshake latency on each client request. Only the raw TCP
|
|
connection is pooled -- once SOCKS/HTTP CONNECT negotiation begins,
|
|
the connection is consumed.
|
|
|
|
```yaml
|
|
pool_size: 8 # 0 = disabled (default)
|
|
pool_max_idle: 30 # seconds before a pooled connection is evicted
|
|
```
|
|
|
|
Connections idle longer than `pool_max_idle` are discarded and replaced.
|
|
A background task tops up the pool at half the idle interval. Requires
|
|
at least one hop in `chain` -- ignored if chain is empty.
|
|
|
|
## 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.
|