From 20c7597ef948cdc32b44e2290fbaf86bf84e9b28 Mon Sep 17 00:00:00 2001 From: user Date: Sun, 15 Feb 2026 03:51:16 +0100 Subject: [PATCH] docs: update all docs for container, cprofile, and config split --- PROJECT.md | 14 +++++++++++++- README.md | 34 +++++++++++++++++++++++++++------- ROADMAP.md | 3 +++ TASKS.md | 7 ++++++- docs/CHEATSHEET.md | 30 +++++++++++++++++++++++++++++- docs/INSTALL.md | 27 ++++++++++++++++++++------- docs/USAGE.md | 40 ++++++++++++++++++++++++++++++++++++++-- 7 files changed, 136 insertions(+), 19 deletions(-) diff --git a/PROJECT.md b/PROJECT.md index 0e92f1d..441fef2 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -22,7 +22,17 @@ Client -------> s5p -------> Hop 1 -------> Hop 2 -------> Target - **server.py** -- asyncio SOCKS5 server, chain builder, bidirectional relay - **proto.py** -- protocol handshake implementations (SOCKS5, SOCKS4/4a, HTTP CONNECT) - **config.py** -- YAML config loading, proxy URL parsing -- **cli.py** -- argparse CLI, logging setup +- **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 at runtime. +No application code is baked into the image. ## Dependencies @@ -38,3 +48,5 @@ All other functionality uses Python stdlib (`asyncio`, `socket`, `struct`). - **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 diff --git a/README.md b/README.md index b2f08ec..1d8ada2 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,14 @@ through configurable chains of SOCKS4, SOCKS5, and HTTP CONNECT proxies. - Per-hop authentication (username/password) - DNS leak prevention (domain names forwarded to proxies, never resolved locally) - Tor integration (Tor is just another SOCKS5 hop) +- Container-ready (Alpine-based, podman/docker) +- Graceful shutdown (SIGTERM/SIGINT) - Pure Python, asyncio-based, minimal dependencies ## Quick Start ```bash -# Install +# Install locally cd ~/git/s5p python -m venv .venv && source .venv/bin/activate pip install -e . @@ -24,32 +26,49 @@ pip install -e . # Run with Tor s5p -C socks5://127.0.0.1:9050 -# Run with a chain: Tor -> external proxy -s5p -C socks5://127.0.0.1:9050,socks5://proxy:1080 - # Run with config file -s5p -c config/example.yaml +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 + +```bash +make build # podman-compose build +make up # podman-compose up -d +make logs # podman-compose logs -f +make down # podman-compose down +``` + +Source and config are bind-mounted, not baked into the image. + ## Configuration +Copy the example and edit with your proxy chain: + +```bash +cp config/example.yaml config/s5p.yaml +``` + ```yaml listen: 127.0.0.1:1080 timeout: 10 chain: - socks5://127.0.0.1:9050 # Tor - - socks5://user:pass@proxy:1080 # exit-side proxy + - socks5://user:pass@proxy:1080 # post-Tor proxy - http://proxy2:8080 # HTTP CONNECT proxy ``` +`config/s5p.yaml` is gitignored; `config/example.yaml` is the tracked template. + ## CLI Reference ``` -s5p [-c FILE] [-l [HOST:]PORT] [-C URL[,URL,...]] [-t SEC] [-v|-q] +s5p [-c FILE] [-l [HOST:]PORT] [-C URL[,URL,...]] [-t SEC] [-v|-q] [--cprofile [FILE]] Options: -c, --config FILE YAML config file @@ -58,6 +77,7 @@ Options: -t, --timeout SEC Per-hop timeout (default: 10) -v, --verbose Debug logging -q, --quiet Errors only + --cprofile [FILE] Enable cProfile, dump to FILE (default: s5p.prof) -V, --version Show version ``` diff --git a/ROADMAP.md b/ROADMAP.md index 64623f4..590a9d4 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -7,6 +7,9 @@ - [x] Per-hop authentication - [x] YAML config + CLI flags - [x] DNS leak prevention +- [x] Container deployment (Alpine + podman-compose) +- [x] Graceful SIGTERM/SIGINT shutdown +- [x] cProfile support ## v0.2.0 diff --git a/TASKS.md b/TASKS.md index a152752..320fe80 100644 --- a/TASKS.md +++ b/TASKS.md @@ -9,10 +9,15 @@ - [x] CLI and config loading - [x] Unit tests (config, proto) - [x] Documentation -- [ ] Smoke test with Tor +- [x] Smoke test with Tor +- [x] Containerfile + compose.yaml (Alpine) +- [x] Graceful SIGTERM shutdown +- [x] cProfile support (`--cprofile`) +- [x] Config split (example.yaml tracked, s5p.yaml gitignored) ## Next +- [ ] Gather working public proxy list for post-Tor chaining - [ ] Integration tests with mock proxy server - [ ] SOCKS5 server-side authentication - [ ] Tor control port integration diff --git a/docs/CHEATSHEET.md b/docs/CHEATSHEET.md index 2a47759..f39b6eb 100644 --- a/docs/CHEATSHEET.md +++ b/docs/CHEATSHEET.md @@ -6,11 +6,28 @@ 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/example.yaml # from config file +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 --cprofile # profile to s5p.prof +s5p --cprofile out.prof # profile to custom file +``` + +## Container + +``` +make build # podman-compose build +make up # podman-compose up -d +make logs # podman-compose logs -f +make down # podman-compose down +``` + +## Config + +```bash +cp config/example.yaml config/s5p.yaml # create live config (gitignored) ``` ## Proxy URLs @@ -29,6 +46,9 @@ http://user:pass@host:port # 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 @@ -36,6 +56,12 @@ curl -v -x socks5h://127.0.0.1:1080 https://example.com curl --max-time 30 -x socks5h://127.0.0.1:1080 https://example.com ``` +## Profiling + +```bash +python -m pstats s5p.prof # interactive stats viewer +``` + ## Troubleshooting | Symptom | Check | @@ -44,3 +70,5 @@ curl --max-time 30 -x socks5h://127.0.0.1:1080 https://example.com | 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 | +| Container slow stop | Rebuild image after SIGTERM fix | diff --git a/docs/INSTALL.md b/docs/INSTALL.md index b044f63..5dbf39d 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -5,8 +5,9 @@ - Python >= 3.11 - pip - Tor (optional, for Tor-based chains) +- podman + podman-compose (optional, for container deployment) -## Install +## Local Install ```bash cd ~/git/s5p @@ -22,6 +23,24 @@ s5p --version which s5p ``` +## Symlink (alternative) + +```bash +ln -sf ~/git/s5p/.venv/bin/s5p ~/.local/bin/s5p +``` + +## Container Install + +```bash +cd ~/git/s5p +cp config/example.yaml config/s5p.yaml # edit with your proxies +make build # podman-compose build +make up # podman-compose up -d +``` + +The Alpine-based image (~59MB) contains only Python and PyYAML. +Application source and config are bind-mounted at runtime. + ## Install Tor (optional) ```bash @@ -31,9 +50,3 @@ sudo systemctl enable --now tor # Verify Tor SOCKS5 port ss -tlnp | grep 9050 ``` - -## Symlink (alternative) - -```bash -ln -sf ~/git/s5p/.venv/bin/s5p ~/.local/bin/s5p -``` diff --git a/docs/USAGE.md b/docs/USAGE.md index 53fca9a..e189e94 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -16,13 +16,24 @@ s5p -C socks5://127.0.0.1:9050,socks5://proxy:1080 s5p -l 0.0.0.0:9999 -C socks5://127.0.0.1:9050 # From config file -s5p -c config/example.yaml +s5p -c config/s5p.yaml # Debug mode s5p -v -C socks5://127.0.0.1:9050 ``` -## Config File +## 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 @@ -46,6 +57,31 @@ protocol://[username:password@]host[:port] | 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. Edit locally, restart to pick up changes. + +## Profiling + +```bash +# Run with cProfile enabled +s5p --cprofile -c config/s5p.yaml + +# Custom output file +s5p --cprofile output.prof -c config/s5p.yaml + +# Analyze after stopping +python -m pstats s5p.prof +``` + ## Testing the Proxy ```bash