-
Notifications
You must be signed in to change notification settings - Fork 698
Description
Summary
Hi @ginuerzh @fernvenue ,
Proposal to add per-application transparent proxying via a new gost run subcommand. This routes traffic from specific applications through gost's proxy chain while leaving other system traffic unaffected.
gost run -F socks5://proxy:1080 -- firefoxI have already implemented this as a standalone Go wrapper with working Linux and Windows versions. If you're interested, I'd be happy to port it to gost v3 as a PR.
Why gost run Subcommand?
The existing -- separator in gost is used for multi-process spawning (cmd/gost/main.go:44-67):
# Existing: spawns two gost processes
gost -L socks5://:1111 -- -L rtcp://:3333/:1111 -F sshd://server:2222A dedicated run subcommand avoids this conflict and provides cleaner semantics for per-app isolation.
Motivation
gost already has excellent TUN support for system-wide proxying. However, users often need to proxy only specific applications:
| Use Case | Current Solution | Limitation |
|---|---|---|
| Proxy only browser | proxychains | Fails with static binaries (Linux) |
| Dev/test isolation | Docker + gost | Heavy, slow startup |
| Nested proxy chains | Not possible | TUN captures all traffic |
Platform Support
| Platform | Status | Implementation |
|---|---|---|
| Linux | ✅ Implemented | User namespaces + TUN + gVisor netstack |
| Windows | ✅ Implemented | WinDivert packet interception + gVisor netstack |
| macOS | ❌ Not feasible | Network Extension API barriers |
Why Not macOS?
| Requirement | Issue |
|---|---|
| Apple Developer Account | $99/year recurring cost (required even for local builds) |
| App notarization | Must be signed by Apple |
| Language | Swift/Obj-C required; no pure Go |
Proposed Usage
Basic
# Linux (no root required)
gost run -F socks5://proxy:1080 -- firefox
# Windows (administrator required)
gost run -F socks5://proxy:1080 -- firefox.exeWith Different Protocols
# Relay protocol
gost run -F relay://server:8080 -- curl https://example.com
# Tunnel protocol
gost run -F tunnel://server:8080?tunnel.id=my-id -- wget https://example.comProxy Chain
gost run --chain -F socks5://proxy1:1080 -F relay://proxy2:8421 -- curl https://example.comUnix Socket
# Works on both Linux and Windows (Windows 10 1803+ supports AF_UNIX)
gost run -F socks5+unix:///path/to/socks5.sock -- curl https://example.comConfig File
gost run -C run-config.yamlrun-config.yaml:
forwards:
- socks5://proxy1:1080
- socks5://proxy2:1080
command: ["firefox", "--private-window"]
uid: 1000 # Linux only
gid: 1000 # Linux only
net: 192.168.123.1/24
mtu: 1350Implementation
Linux: User Namespaces
┌─────────────────────────────────────────────────────────────────────┐
│ gost run -F socks5://proxy:1080 -- firefox │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Parse command after "--" │
│ │
│ 2. Create child process with new namespaces: │
│ └── unshare(CLONE_NEWUSER | CLONE_NEWNET) │
│ │
│ 3. Child creates TUN device inside namespace │
│ └── Has root capabilities inside user namespace │
│ │
│ 4. Pass TUN fd to parent via Unix socket pair │
│ │
│ 5. Parent attaches TUN to gVisor netstack │
│ └── Forward TCP/UDP through chain │
│ │
│ 6. Child sets TUN as default route, execs application │
│ │
└─────────────────────────────────────────────────────────────────────┘
No root required — user namespaces are unprivileged.
Windows: WinDivert
┌─────────────────────────────────────────────────────────────────────┐
│ gost run -F socks5://proxy:1080 -- firefox.exe │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Parse command after "--", launch application │
│ │
│ 2. Track launched PID and child process tree │
│ │
│ 3. WinDivert intercepts outbound packets by PID │
│ └── If packet's PID matches → forward through chain │
│ └── Else → re-inject directly │
│ │
└─────────────────────────────────────────────────────────────────────┘
Requires administrator privileges. WinDivert is an external DLL loaded at runtime (no CGO), same pattern as gost's existing Wintun dependency. Just ship WinDivert.dll + WinDivert64.sys alongside the binary. Both are pre-signed.
Integration with gost
Reuse Existing Components
| Component | Reuse |
|---|---|
| gVisor netstack | Already used by TUN handler (Linux) |
| Chain forwarding | All connectors (socks5, relay, tunnel, http, etc.) |
| Config parsing | YAML/JSON support |
Dependencies
| Component | License | Platform | Notes |
|---|---|---|---|
| gVisor netstack | Apache 2.0 | Both | Already in gost |
| WinDivert | LGPL | Windows | External DLL, same pattern as Wintun |
| divert-go | MIT | Windows | Go bindings, no CGO required for cross-compile |
Nested Proxy Chains
gost run -F socks5://proxy1:1080 \
-- gost run -F socks5://proxy2:1080 \
-- firefoxTraffic: firefox → proxy2 → proxy1 → internet
How it works:
- Linux: Each nested gost runs in its own network namespace
- Windows: WinDivert priority system — inner gost uses higher priority, catches packets first, injects to outer gost
Unix Socket for Nested Mode (Linux)
TCP doesn't work across namespaces. Unix sockets can be bind-mounted:
gost run -F relay+unix:///tmp/gost.sock \
-L relay+unix:///tmp/gost.sock \
-- gost run -F relay+unix:///tmp/gost.sock \
-- firefoxUse Cases
- Selective routing — Proxy only specific applications
- Development & testing — Route apps through different network paths
- Nested chains — Hierarchical routing
Questions
-
Interest level? Would you be interested in per-app isolation via
gost run? -
Implementation scope?
- Linux first, Windows follow-up
- Both together
Looking forward to your feedback! Happy to submit a PR.