Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/docs/substrate/VPN-WIUF.md
Fimeg 25bb99c850 VPN: correct the port, the peer, and the keepalive
51822 not 51820; the phone has its own peer (10.8.0.6) rather than sharing
the laptop's key; keepalive 25 not 0. Records that the autonomous gate is
dead and why a full tunnel that cannot handshake takes the machine with it.
2026-07-31 07:57:30 -04:00

123 lines
5.2 KiB
Markdown

# Wiuf VPN — phone split-tunnel
> **Corrected 2026-07-30 evening, proven working off-LAN.** Three things below
> were wrong and cost an hour:
>
> - **The port is 51822 (or 51821), NOT 51820.** A generated
> `SouveraineOS-Phone.conf` said 51820; it sends and never receives.
> - **The phone has its OWN peer now: `wiufph`, address 10.8.0.6.** The old
> `wiuf` profile shared its address *and private key* with the laptop, so
> WireGuard could only ever hold one of them, and that key is no longer
> listed server-side.
> - **`persistent-keepalive` must be 25**, not the `0` the generated conf
> carries, or the tunnel dies behind carrier NAT.
>
> Verified from a foreign network (`10.10.30.x`): handshake in 8 s, gitea
> `HTTP 200` in 0.126 s, Pi-hole reachable, internet unaffected.
>
> **The autonomous gate described below is DEAD** — it recycled the tunnel 652
> times in 90 minutes and could not be switched off. Replaced by a deliberate
> quick toggle in the shell's right panel. Never reinstate a timer or an NM
> dispatcher hook here; if posture must be automatic it belongs in sessiond as
> an Action (DEVICE-STATE-MACHINE §12).
>
> **Also note:** `allowed-ips=0.0.0.0/0` is a full tunnel — bringing that up
> when it cannot handshake black-holes the whole machine. Split-tunnel
> (`10.10.0.0/16` + `never-default=true`) fails safe instead.
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.