Files
s5p/README.md
user 8a909cd79d
Some checks failed
ci / test (push) Successful in 19s
ci / build (push) Failing after 12s
fix: revert to dedicated s5p harbor project
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:32:06 +01:00

5.8 KiB

s5p

SOCKS5 proxy server with Tor and proxy-chain support. Routes connections through configurable chains of SOCKS4, SOCKS5, and HTTP CONNECT proxies.

Features

  • SOCKS5 server (RFC 1928)
  • Proxy chaining: tunnel through multiple hops in sequence
  • Supported hop protocols: SOCKS5, SOCKS4/4a, HTTP CONNECT
  • Per-hop authentication (username/password)
  • DNS leak prevention (domain names forwarded to proxies, never resolved locally)
  • Tor integration (SOCKS5 hop + control port NEWNYM for circuit rotation)
  • Multi-Tor round-robin (tor_nodes distributes traffic across Tor instances)
  • Multi-listener: different ports with different chain depths and pool assignments
  • Named proxy pools: independent sources, health testing, and state per pool
  • MITM source filter (mitm: true/false adds ?mitm=0/1 to API requests)
  • 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 per-listener latency and pool stats
  • Concurrent connection limit with backpressure (max_connections)
  • Async HTTP client for proxy source fetching (parallel, no threads)
  • First-hop TCP connection pool (pre-warmed, stale-evicted)
  • Built-in control API (runtime metrics, pool state, config reload via HTTP)
  • Container-ready (Alpine-based, podman/docker)
  • Graceful shutdown (SIGTERM/SIGINT)
  • Pure Python, asyncio-based, minimal dependencies

Quick Start

# Install locally
cd ~/git/s5p
python -m venv .venv && source .venv/bin/activate
pip install -e .

# Run with Tor
s5p -C socks5://127.0.0.1:9050

# Run with config file
cp config/example.yaml config/s5p.yaml  # edit with your proxies
s5p -c config/s5p.yaml

# Test it
curl --proxy socks5h://127.0.0.1:1080 https://check.torproject.org/api/ip

Container

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

Production images bake source into the image. Config and data are mounted at runtime. Pool state and profile output persist in ~/.cache/s5p/ (/data inside container). The compose.yaml volume mount overrides source for local dev.

CI (Gitea Actions) runs lint + tests on push to main, then builds and pushes harbor.mymx.me/s5p/s5p:latest.

Configuration

Copy the example and edit with your proxy chain:

cp config/example.yaml config/s5p.yaml
timeout: 10
retries: 3
max_connections: 256                  # concurrent connection limit
pool_size: 8                          # pre-warmed connections to first hop
api_listen: 127.0.0.1:1081           # control API (disabled by default)

# Named proxy pools (each with independent sources and health testing)
proxy_pools:
  clean:
    sources:
      - url: http://10.200.1.250:8081/proxies/all
        mitm: false                   # filter: ?mitm=0
    refresh: 300
    test_interval: 120
    max_fails: 3
  mitm:
    sources:
      - url: http://10.200.1.250:8081/proxies/all
        mitm: true                    # filter: ?mitm=1
    refresh: 300
    test_interval: 120
    max_fails: 3

# Multi-listener: each port gets a chain depth and pool assignment
# Use "pool" for listener default, "pool:name" for explicit pool per hop,
# or [pool:a, pool:b] for random choice from candidates per connection
listeners:
  - listen: 0.0.0.0:1080
    pool: clean
    chain:
      - socks5://127.0.0.1:9050
      - pool                           # Tor + 2 clean proxies
      - pool
  - listen: 0.0.0.0:1081
    chain:
      - socks5://127.0.0.1:9050
      - [pool:clean, pool:mitm]        # random choice per connection
      - [pool:clean, pool:mitm]        # independent random choice
  - listen: 0.0.0.0:1082
    chain:
      - socks5://127.0.0.1:9050       # Tor only

# Singular proxy_pool: still works (becomes pool "default")

tor:
  control_port: 9051                  # Tor control port (NEWNYM)
  password: ""                        # or cookie_file for auth
  newnym_interval: 0                  # periodic circuit rotation (0 = manual)

config/s5p.yaml is gitignored; config/example.yaml is the tracked template.

CLI Reference

s5p [-c FILE] [-l [HOST:]PORT] [-C URL[,URL,...]] [-S URL] [-t SEC] [-r N] [-m N] [--api [HOST:]PORT] [-v|-q]

Options:
  -c, --config FILE        YAML config file
  -l, --listen [HOST:]PORT Listen address (default: 127.0.0.1:1080)
  -C, --chain URL[,URL]    Comma-separated proxy chain
  -S, --proxy-source URL   Proxy source API URL
  -t, --timeout SEC        Per-hop timeout (default: 10)
  -r, --retries N          Max attempts per connection (default: 3, proxy_source only)
  -m, --max-connections N  Max concurrent connections (default: 256)
  --api [HOST:]PORT        Enable control API (e.g. 127.0.0.1:1081)
  -v, --verbose            Debug logging
  -q, --quiet              Errors only
  --cprofile [FILE]        Enable cProfile, dump to FILE (default: s5p.prof)
  --tracemalloc [N]        Enable tracemalloc, show top N allocators on exit (default: 10)
  -V, --version            Show version

How Chaining Works

:1080  Client -> s5p -> Tor -> [clean] -> [clean]       -> Dest  (2 clean hops)
:1081  Client -> s5p -> Tor -> [clean|mitm] -> [clean|mitm] -> Dest  (random)
:1082  Client -> s5p -> Tor -> Dest                              (Tor only)

s5p connects to Hop1 via TCP, negotiates the hop protocol (SOCKS5/4/HTTP), then over that tunnel negotiates with Hop2, and so on. Each listener draws from its assigned named pool -- alive proxies are appended per-connection (one per pool entry), weighted toward those with the most recent successful health test. Each hop only sees its immediate neighbors.