Watch
1
0
Fork
You've already forked SouveraineOS
0

docs: Wiuf VPN — phone split-tunnel + semi-intelligent gate

This commit is contained in:
Fimeg 2026-07-30 14:19:31 -04:00
commit 051da9e0d3

View file

@ -0,0 +1,98 @@
# Wiuf VPN — phone split-tunnel + semi-intelligent gate
Status: deployed on the Pixel 3 (blueline) 2026-07-30. Laptop profile removed
(same keys — see Caveats); it gets a fresh Wiuf peer of its own.
This is the practical client config; the aspirational per-consumer policy engine
lives in `NET_LAYER_PLAN.md`. That engine is not yet built, so this sits on
NetworkManager directly.
## What it does
- A NetworkManager WireGuard connection **`wiuf`** that routes **only
`10.10.0.0/16`** (covers the `.10` / `.20` / `.30` segments) over the tunnel
and resolves **`~wiuf.net`** via the LAN Pi-hole (`10.10.20.5`). Everything
else (LTE, general internet) stays on the default link — so this does **not**
funnel the phone's whole connection through home, and it does **not** grab the
default route at boot (`autoconnect=false`).
- A gate (`wiuf-vpn-gate`) that brings the tunnel **up only off the home LAN and
only when there's an internet path**, and **down** on the home LAN (already
direct) or with no service. Triggered by the NM dispatcher on link changes,
with a 90 s backstop timer.
## Endpoint facts (why it's pinned to IPv4)
- `sub.wiuf.net`**`173.246.142.24`**, which is the **home WAN**. UDP `51822`
is port-forwarded to the WG server inside.
- It also has an AAAA (`2604:5580:22::adf6:8e18`), but the phone has **no global
IPv6 on wifi**, and the v6 path is dead. The endpoint is therefore pinned to
`173.246.142.24:51822`. This works on both wifi (direct v4) and cell
(clat gives v4-over-v6).
- **NAT loopback**: when the phone is *on* the home wifi it cannot handshake to
the home WAN — the router doesn't reflect the UDP forward back inside
(`transfer: 0 B received`). This is expected and irrelevant: the gate never
brings the tunnel up at home.
## The connection (keyfile)
`/etc/NetworkManager/system-connections/wiuf.nmconnection`:
```ini
[connection]
id=wiuf
type=wireguard
interface-name=wgpi
autoconnect=false
permissions=
[wireguard]
private-key=kFH0g2VTkzV5F6KBBCtZ8A9KH1c4uwtvoIOtye9lomo=
peer-routes=true
[wireguard-peer.P3Fbw93BAJyRs14aRZcEULAHD/8NcR3HU2T5lA/mADE=]
preshared-key=H5GpVr7xszqvFDj6mtQm3+Ii93TTHc2KPJmJ6LFNwUc=
allowed-ips=10.10.0.0/16;
endpoint=173.246.142.24:51822
persistent-keepalive=25
[ipv4]
method=manual
addresses=10.8.0.5/24
dns=10.10.20.5
dns-search=~wiuf.net
never-default=true
[ipv6]
method=disabled
```
> Rotate the private key / PSK when the laptop is re-keyed (see Caveats). These
> currently match the old laptop peer.
## The gate
- `/usr/local/bin/wiuf-vpn-gate` — idempotent up/down controller. Logs to
`journalctl -t wiuf-vpn-gate`.
- `/etc/NetworkManager/dispatcher.d/99-wiuf-vpn` — runs the gate on any link
`up`/`down`.
- `wiuf-vpn-gate.timer` — fires the gate every 90 s as a backstop.
Logic: home wifi (wlan0 has a `10.10.x` addr) → down; no default route → down;
otherwise up, and verifies a handshake (received bytes > 0), recycling if dead.
## Caveats
- **Shared keys.** The phone inherited the laptop's peer (`10.8.0.5`, same
private key + PSK). WireGuard maps one public key to one endpoint, so the two
devices cannot be connected at the same time until the laptop is given its own
peer. That's the "replace shortly" item.
- **Validation pending on cell.** Handshake can't be confirmed from inside the
LAN (NAT loopback). The gate self-confirms off-LAN; check
`journalctl -t wiuf-vpn-gate | grep "handshake ok"` after first cell use.
- **Pangolin alternative.** `10.10.20.120` (WIUF-Docker, `gitea.wiuf.net`) runs
fosrl **Pangolin** (reverse proxy atop traefik, manages crowdsec) with a REST
API. Exposing specific services through Pangolin (public HTTPS + auth) is an
alternative to VPN for those services — but raw `10.10.x` + Pi-hole domains
still need the tunnel, so VPN stays. A public `dns.wiuf.net` was considered
and rejected: it only resolves names, doesn't route to them, and is redundant
once the tunnel is up.