diff options
| author | James O'Doherty <james@theodohertyfamily.com> | 2026-05-22 10:14:03 -0400 |
|---|---|---|
| committer | James O'Doherty <james@theodohertyfamily.com> | 2026-05-22 10:14:03 -0400 |
| commit | 5dbc46f3c1c75bf922bcc1c3df342323c23c04ce (patch) | |
| tree | 1a2840366e5d39aa3d9e8d868dd5893f5c488373 /README.md | |
| parent | 764d3e67fc783c487f42d398d1b85a5a1f0d8ef0 (diff) | |
docs: update README and AGENTS.md to reflect embedded launcher architecture
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 16 |
1 files changed, 10 insertions, 6 deletions
@@ -24,6 +24,15 @@ Beyond wrapping commands, `wg-wrap` provides management sub-commands to handle p The tool focuses on a direct, transparent data path: `Linux Application` $\rightarrow$ `Linux Kernel Routing` $\rightarrow$ `TUN Device` $\rightarrow$ `Userspace WireGuard` $\rightarrow$ `UDP Socket` $\rightarrow$ `Internet`. +### Rootless Bootstrap Loop +To achieve rootless network isolation without interfering with the Go runtime's multi-threaded scheduler, `wg-wrap` employs a bootstrap pattern: +1. **Initial Launch**: The Go binary starts and detects it is not in an isolated network namespace. +2. **Helper Deployment**: It writes an embedded C launcher binary to a secure temporary location. +3. **Namespace Transition**: It uses `syscall.Exec` to replace itself with the C launcher. +4. **Isolation**: The C launcher performs the `unshare(CLONE_NEWUSER | CLONE_NEWNET)` sequence, maps the current user to root (UID 0) inside the namespace, and disables supplementary groups. +5. **Re-entry**: The launcher then `execvp`s the original `wg-wrap` binary. +6. **Execution**: The second instance of `wg-wrap` detects it is now isolated and proceeds to initialize the VPN and execute the target application. + ### Persistent Namespaces To support multiple commands using the same VPN profile without re-establishing the tunnel, `wg-wrap` utilizes persistent network namespaces. - **Mechanism**: Instead of relying on the process lifecycle to keep the namespace alive, `wg-wrap` "bind-mounts" the network namespace file to a known location on disk (e.g., `/run/user/$UID/wg-wrap/profiles/<profile-name>`). @@ -73,15 +82,10 @@ To support multiple commands using the same VPN profile without re-establishing | **Routing** | Host Routing Table | Isolated Namespace Table | ## Implementation Roadmap -1. **Bootstrap Logic**: Implement the `unshare` and re-execution flow. - - Use `golang.org/x/sys/unix` for `Unshare` and user mapping. - - **Strategy**: Follow the "pasta/slirp4netns" model—create the network namespace first. This grants the process root-like privileges *within the namespace*, allowing the creation of the TUN device without requiring global `CAP_NET_ADMIN` on the host. +1. **Bootstrap Logic**: Implement the `unshare` and re-execution flow via an embedded C launcher. (DONE) 2. **TUN/WG Integration**: Integrate the `tun` device with the `wireguard-go` device. - - Leverage `golang.zx2c4.com/wireguard/tun` for interface management. 3. **Routing Automation**: Automate the `ip` command sequence for interface and route setup. 4. **Config & Profile Management**: Implement a robust parser for WireGuard configuration files and a full profile management system (import, list, edit, delete) targeting `~/.config/wg-wrap/profiles/`. - - 5. **Lifecycle Management**: Ensure the TUN and WireGuard devices are cleaned up upon process termination. ## Technical Gotchas & Implementation Details |
