Files
s5p/PROJECT.md
user 40560ef6dd docs: document connection limit, async fetch, and connection pool
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.
2026-02-15 17:56:08 +01:00

3.1 KiB

s5p -- Project

Purpose

A lightweight SOCKS5 proxy server that chains connections through Tor and/or arbitrary proxy hops (SOCKS4, SOCKS5, HTTP CONNECT).

Motivation

Existing solutions (proxychains-ng) rely on LD_PRELOAD hacks, only work on Linux, and intercept at the library level. s5p is a proper SOCKS5 server that any application can use natively -- no injection required.

Architecture

                  TCP          tunnel        tunnel
Client -------> s5p -------> Hop 1 -------> Hop 2 -------> Target
        SOCKS5       proto1         proto2         protoN
  • server.py -- asyncio SOCKS5 server, bidirectional relay, signal handling
  • proto.py -- protocol handshakes (SOCKS5, SOCKS4/4a, HTTP CONNECT), chain builder
  • config.py -- YAML config loading, proxy URL parsing, pool config
  • pool.py -- managed proxy pool (multi-source, health-tested, persistent)
  • source.py -- legacy proxy source (single HTTP API, kept for backward compat)
  • http.py -- minimal async HTTP/1.1 client (GET/POST JSON, no external deps)
  • connpool.py -- pre-warmed TCP connection pool to first chain hop
  • cli.py -- argparse CLI, logging setup, cProfile support

Deployment

Method Command
Local venv pip install -e . then s5p -c config/s5p.yaml
Container make build && make up (Alpine, ~59MB)

Container mounts ./src and ./config/s5p.yaml read-only, plus ~/.cache/s5p as /data for pool state and profile output. No application code is baked into the image.

Dependencies

Package Purpose
pyyaml Config file parsing

All other functionality uses Python stdlib (asyncio, socket, struct).

Design Decisions

  • No LD_PRELOAD -- clean SOCKS5 server, works with any client
  • asyncio -- single-threaded event loop, efficient for I/O-bound proxying
  • Domain passthrough -- never resolve DNS locally to prevent leaks
  • Tor as a hop -- no special Tor handling; it's just socks5://127.0.0.1:9050
  • Graceful shutdown -- SIGTERM/SIGINT handled in the event loop for clean container stops
  • Config split -- tracked example template, gitignored live config with real addresses
  • Proxy pool -- multi-source (API + file), health-tested, persistent, auto-cleaned
  • Weighted selection -- recently-tested proxies preferred via recency decay weight
  • Failure backoff -- connection failures penalize proxy weight for 60s, avoids retry waste
  • Stale expiry -- proxies dropped from sources evicted after 3 refresh cycles if not alive
  • Chain pre-flight -- static chain tested before pool health tests; skip on failure
  • Warm start -- quick-test alive subset on restart, defer full test to background
  • SIGHUP reload -- re-read config, update pool settings, re-fetch sources
  • Dead reporting -- POST evicted proxies to upstream API for list quality feedback
  • Connection semaphore -- cap concurrent connections to prevent fd exhaustion
  • Async HTTP -- native asyncio HTTP client replaces blocking urllib, parallel fetches
  • First-hop pool -- pre-warmed TCP connections to chain[0], stale-evicted, auto-refilled