# Project structure ``` softether-go/ ├── cmd/softether-go/ │ ├── main.go Flag parsing, TAP setup, reconnect loop │ └── session.go Session lifecycle, DHCP orchestration ├── pkg/ │ ├── client/ │ │ ├── client.go SoftEther handshake and session │ │ ├── tunnel.go TCP block framing, keepalive, frame bridging │ │ └── crypto.go SHA-0 and password hashing │ ├── protocol/ │ │ ├── http.go TLS connection, HTTP transport layer │ │ └── pack.go Pack binary serialization │ ├── dhcp/ │ │ └── dhcp.go DHCP client (raw Ethernet frames) │ ├── netcfg/ │ │ └── netcfg.go TAP configuration, routing, DNS management │ └── 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, split into two files: **`main.go`** — flag parsing, TAP device creation, MAC configuration, signal handling, and the reconnect loop. Calls `runSession` for each connection attempt. **`session.go`** — one VPN session lifecycle: connect to server, start bridge, run DHCP, configure TAP (IP/routes/DNS/policy routing), and wait for disconnect or signal. Also contains `runDHCP` which orchestrates the DHCP exchange through the tunnel. ### `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 completes. `ReadFrames()` reads batches of Ethernet frames from the server. `WriteFrames()` sends batches. `Bridge()` runs bidirectional frame forwarding between the tunnel and a TAP device, with an optional `FrameHandler` callback for intercepting frames (used by DHCP). `StartKeepalive()` sends periodic keepalive packets (every 3s). **`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/netcfg` **`netcfg.go`** — network configuration for the VPN tunnel. `ConfigureTAP()` sets IP address, routes, and DNS on the TAP interface from a DHCP lease. `ConfigurePolicyRoute()` sets up policy routing for asymmetric return paths. `AddServerRoute()` adds a host route to the VPN server via the current default gateway. `ResolveHost()` resolves hostnames to IPv4. ### `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()` and `SetMAC()` for hardware address management, and `SetUp()` to bring the interface up.