summaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
authorJames O'Doherty <james@theodohertyfamily.com>2026-05-22 10:14:03 -0400
committerJames O'Doherty <james@theodohertyfamily.com>2026-05-22 10:14:03 -0400
commit5dbc46f3c1c75bf922bcc1c3df342323c23c04ce (patch)
tree1a2840366e5d39aa3d9e8d868dd5893f5c488373 /README.md
parent764d3e67fc783c487f42d398d1b85a5a1f0d8ef0 (diff)
docs: update README and AGENTS.md to reflect embedded launcher architecture
Diffstat (limited to 'README.md')
-rw-r--r--README.md16
1 files changed, 10 insertions, 6 deletions
diff --git a/README.md b/README.md
index 26d7c22..1b09bb7 100644
--- a/README.md
+++ b/README.md
@@ -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