SOCKS5 proxy over Yggdrasil. Allows regular applications to access the Yggdrasil network via the standard SOCKS5 protocol.
- Overview
- Initialization
- Enabling and disabling
- TCP and Unix socket
- Connection limiting
- Unix socket handling
- Errors
flowchart LR
App["application"] -->|" SOCKS5 "| Proxy["socks.Obj"]
Proxy -->|" DialContext "| Ygg["Yggdrasil"]
subgraph Proxy
Listener["TCP / Unix listener"]
Socks5["socks5.Server"]
Limit["limitedListener"]
end
Listener --> Socks5
Socks5 -->|" connect "| Ygg
The application connects to a SOCKS5 proxy (TCP or Unix socket), the proxy resolves the address via the provided
NameResolver
and establishes a connection through the Yggdrasil dialer.
s := socks.New(node) // node — proxy.ContextDialer (usually core.Obj)Creates a SOCKS5 proxy but does not start it. Call Enable to start.
err := s.Enable(socks.EnableConfigObj{
Addr: "127.0.0.1:1080", // or "/tmp/ygg.sock"
Resolver: resolver, // name resolver (.pk.ygg, DNS)
Verbose: false, // log every connection
Logger: logger,
MaxConnections: 100, // 0 — unlimited
})
s.IsEnabled() // true
s.Addr() // "127.0.0.1:1080"
s.IsUnix() // false
err := s.Disable() // stop and clean up| Method | Description |
|---|---|
Enable(cfg) |
Starts the proxy; error if already running |
Disable() |
Stops the proxy; idempotent |
Addr() |
Current listening address |
IsUnix() |
true if listening on a Unix socket |
IsEnabled() |
true if the proxy is running |
The Enable → Disable → Enable cycle is supported.
The listener type is determined by the address:
| Address | Type |
|---|---|
127.0.0.1:1080 |
TCP |
[::1]:1080 |
TCP |
/tmp/ygg.sock |
Unix socket |
./local.sock |
Unix socket |
Rule: if the address starts with / or . — Unix socket, otherwise TCP.
When MaxConnections > 0, the listener is wrapped in a limitedListener with a semaphore based on a buffered channel.
flowchart LR
Accept["Accept()"] --> Sem{"semaphore free?"}
Sem -->|" yes "| Conn["accept connection"]
Sem -->|" no "| Block["wait"]
Conn --> Close["Close()"]
Close --> Release["release semaphore"]
Acceptblocks when the limit is reachedClosereleases the slot exactly once (sync.Once)- Repeated
Closecalls are safe
On startup with a Unix socket, stale files are handled:
flowchart TB
Listen["net.Listen(unix)"] --> OK{"success?"}
OK -->|" yes "| Done["ready"]
OK -->|" EADDRINUSE "| Dial["dial socket"]
Dial --> Alive{"responds?"}
Alive -->|" yes "| Err["ErrAlreadyListening"]
Alive -->|" no "| Check["Lstat: symlink?"]
Check -->|" symlink "| Refuse["ErrSymlinkRefusal"]
Check -->|" regular file "| Remove["os.Remove → retry"]
- If the socket is held by a live process — error
- If the socket is stale — it is removed and recreated
- Symlinks are not removed (protection against attacks)
On Disable, the Unix socket file is automatically removed.
| Variable | Description |
|---|---|
ErrAlreadyEnabled |
Enable called on an already running proxy |
ErrAlreadyListening |
Unix socket is held by another process |
ErrSymlinkRefusal |
Refusal to remove a symlink (safety measure) |