SOCKS5 server with async Python addon hooks.
Docs · Architecture · Addon recipes · Addon model · Public API · 简体中文
pip install asyncio-socks-serverDocker images are versioned:
docker run --rm -p 1080:1080 amaindex/asyncio-socks-server:1.3.2asyncio_socks_server
asyncio_socks_server --host 127.0.0.1 --port 9050
asyncio_socks_server --auth user:passCLI flags:
| Flag | Default | Meaning |
|---|---|---|
--host |
:: |
Bind address |
--port |
1080 |
Bind port |
--auth |
None | username:password |
--log-level |
INFO |
DEBUG, INFO, WARNING, ERROR |
--log-format |
text |
text or json |
from asyncio_socks_server import Server
Server(host="::", port=1080).run()Addons are optional. Add only the behavior you need:
| Goal | Addons |
|---|---|
| Runtime counters and active flows | FlowStats + StatsAPI |
| Closed-flow usage audit | FlowAudit + StatsAPI |
| TCP chain proxying | ChainRouter |
| UDP chain proxying | UdpOverTcpEntry + UdpOverTcpExitServer |
| Auth, source policy, logs | FileAuth, IPFilter, Logger |
Runtime counters and audit API:
from asyncio_socks_server import FlowAudit, FlowStats, Server, StatsAPI
audit = FlowAudit()
stats = FlowStats()
server = Server(
addons=[
audit,
stats,
StatsAPI(stats=stats, audit=audit, host="127.0.0.1", port=9900),
],
)
server.run()Addon order is execution order. Built-in addons are opt-in; adding StatsAPI
is what starts an HTTP listener.
FlowStats has no network side effects. Use its snapshot() and flows()
methods directly, or pair it with StatsAPI for a small local HTTP API.
FlowAudit records closed-flow usage in memory and can be exposed through
StatsAPI for Kafra-like usage audit summaries.
Default logs are compact key-value events, for example
event=flow_closed flow_id=7 proto=tcp src=127.0.0.1:50000 dst=example.com:443 bytes_up=128 bytes_down=1024.
Use --log-format json when a log collector prefers JSON lines.
For task-oriented examples, see Addon recipes.
The core handles SOCKS5 parsing, relay, and hook dispatch. Addons handle policy.
Hook dispatch has three models:
| Model | Hooks | Contract |
|---|---|---|
| Competitive | on_auth, on_connect, on_udp_associate |
First non-None result wins |
| Pipeline | on_data |
Output from one addon becomes input to the next |
| Observational | on_start, on_stop, on_flow_close, on_error |
All applicable addons run |
Built-ins:
ChainRouterfor TCP chain proxyingUdpOverTcpEntryandUdpOverTcpExitServerfor UDP chain proxyingFlowStatsfor in-memory flow statisticsFlowAuditfor closed-flow usage audit summariesStatsAPIas an opt-in HTTP API aroundFlowStatsStatsServeras a backward-compatible name forStatsAPITrafficCounter,FileAuth,IPFilter,Logger
Client ── SOCKS5 ──▶ Server ──▶ Target
│
├─ auth / route hooks
├─ data pipeline hooks
└─ flow close hooks
ChainRouter:
Client ──▶ A ──▶ B ──▶ C ──▶ Target
Each node only knows its next hop:
# A ─▶ B ─▶ C ─▶ target
Server(addons=[ChainRouter("B:1080")]) # A
Server(addons=[ChainRouter("C:1080")]) # B
Server() # CUDP chain proxying uses TCP between proxy nodes:
from asyncio_socks_server import Server, UdpOverTcpEntry, UdpOverTcpExitServer
entry = Server(addons=[UdpOverTcpEntry("exit-host:9020")])
exit_server = UdpOverTcpExitServer(host="::", port=9020)from asyncio_socks_server import Address, connect
conn = await connect(
proxy_addr=Address("127.0.0.1", 1080),
target_addr=Address("93.184.216.34", 443),
)
conn.writer.write(b"hello")
await conn.writer.drain()
data = await conn.reader.read(4096)Stable imports live at the package root:
from asyncio_socks_server import (
Addon,
Address,
ChainRouter,
Flow,
FlowAudit,
FlowStats,
Server,
StatsAPI,
StatsServer,
UdpOverTcpEntry,
UdpOverTcpExitServer,
connect,
)Root exports are the 1.x compatibility contract. Submodules remain importable.
| Document | Scope |
|---|---|
| Architecture | Core flow, relay design, UDP-over-TCP, Flow context |
| Addon recipes | Goal-oriented addon combinations |
| Addon model | Hook contracts, dispatch semantics, built-in addons |
| Public API | 1.x compatibility surface |
git clone https://github.com/Amaindex/asyncio-socks-server.git
cd asyncio-socks-server
uv sync
uv run ruff check .
uv run ruff format --check .
uv run pyright
uv run pytest
uv buildGitHub Actions tests Python 3.12 and 3.13, builds the Python package, and builds Docker images.
Create a GitHub Release from a tag such as v1.3.2. The release workflow publishes the Python package. The Docker workflow publishes semver image tags.
MIT