initial commit: standalone SoftEther VPN client in Go

Built-in DHCP (raw Ethernet frames through tunnel), automatic reconnection,
host route management, classless static routes (option 121/249), DNS config.
Single static binary, Linux only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Git Sagar 2026-06-06 16:13:51 +05:30
commit 829ca73b1b
340 changed files with 199140 additions and 0 deletions

57
docs/structure.md Normal file
View file

@ -0,0 +1,57 @@
# Project structure
```
softether-go/
├── cmd/softether-go/
│ └── main.go CLI entry point
├── pkg/
│ ├── client/
│ │ ├── client.go SoftEther handshake and session
│ │ ├── tunnel.go TCP block framing and keepalive
│ │ └── crypto.go SHA-0 and password hashing
│ ├── protocol/
│ │ ├── http.go HTTP transport layer
│ │ └── pack.go Pack binary serialization
│ ├── dhcp/
│ │ └── dhcp.go DHCP client (raw Ethernet frames)
│ └── tap/
│ └── tap.go Linux TAP device management
├── docs/ Documentation
├── vendor/ Vendored Go dependencies
├── flake.nix Nix build definition
├── go.mod
└── go.sum
```
## Package details
### `cmd/softether-go`
CLI entry point. Handles flag parsing, signal handling, and the reconnection loop. On each session:
- Connects to the server
- Runs DHCP through the tunnel
- Configures the TAP interface (IP, routes, DNS)
- Bridges Ethernet frames between the TAP device and the VPN tunnel
- Cleans up on disconnect and retries
### `pkg/client`
**`client.go`** — implements the SoftEther handshake: TLS connect, signature upload, hello/auth/welcome pack exchange. Exports `Connect(Config) (*Session, error)` and the `Config`/`Session` types.
**`tunnel.go`** — TCP block framing after the HTTP handshake. `ReadFrames()` reads batches of Ethernet frames from the server. `WriteFrames()` sends batches. `StartKeepalive()` sends periodic keepalive packets (every 3s) to prevent server timeout.
**`crypto.go`** — SHA-0 implementation (differs from SHA-1 only in the message schedule — no left-rotate). `HashPassword()` produces `SHA0(password)`. `SecurePassword()` produces `SHA0(hashed + serverRandom)`.
### `pkg/protocol`
**`http.go`** — HTTP transport layer. `DialTLS()` establishes the TLS connection. `UploadSignature()` sends the protocol signature. `SendPack()` and `RecvPack()` exchange binary Packs as HTTP POST request/response bodies.
**`pack.go`** — SoftEther Pack binary serialization. A Pack is a list of named Elements, each containing typed Values (int, string, data, ip4). Handles the BufStr wire format (`uint32(strlen+1)` then `strlen` bytes) and the `pencore` random padding element.
### `pkg/dhcp`
**`dhcp.go`** — DHCP client that constructs complete Ethernet/IP/UDP/DHCP frames. The full DHCP exchange (DISCOVER → OFFER → REQUEST → ACK) runs through the VPN tunnel's frame transport. Parses lease information including classless static routes (option 121/249, RFC 3442).
### `pkg/tap`
**`tap.go`** — Linux TAP (Layer 2) device management via `/dev/net/tun`. Opens TAP devices with `IFF_TAP | IFF_NO_PI`, reads/writes raw Ethernet frames. Provides `MAC()` to get the hardware address and `SetUp()` to bring the interface up.