WireGuard on CR-LEVEL-04 — As-Built & Migration¶
Related pages
Design-phase as-built capture. Operational reference: VPN — WireGuard.
Version: 1.0 — 2026-07-06
Captured live from CR-LEVEL-04 (10.255.255.233, CCR2004, ROS 7.16.2). Purpose: document the VPN so peers can be re-homed off this box — now decided: CR-LEVEL-04 becomes the WAN business's bdr-2 (MOVE-PLAN §1), so this WireGuard migration is a hard blocker for that re-role.
Secrets exposed: the live capture includes the interface private key and per-peer private keys (
discovery/raw/CR-LEVEL-04/wg_*.txt, gitignored). These were printed during collection and must be treated as compromised — regenerate the server key and re-issue client configs as part of the move (§4). Do not commit the raw files.
1. What CR-LEVEL-04 actually is¶
Not just a metro router — it's a secondary WAN/VPN edge:
| Function | Detail |
|---|---|
| WAN | sfp-sfpplus12 = public 185.109.40.2/30, in wan list, MTU 1500 (⚠ not jumbo), masquerade NAT out this port |
| WireGuard hub | wg000, listen udp/18472, hub address 10.249.1.1/27, 12 peers on 10.249.1.2–.13 |
| VPN pool routing | 10.249.1.0/27 connected, redistributed into OSPF (redistribute=connected) → reachable from the whole internal network |
| GRE | gre-bolton → remote 178.17.243.197 (a "Bolton" site), currently DISABLED, address invalid — dormant/legacy |
| Metro uplink | single link sfp-sfpplus1 (10.254.9.5/30) to CR-LEVEL-02 — single-homed |
| Hardware note | has sfp28-1/2 (25G) ports — capable box, candidate for re-role |
Stability warning: during capture the box repeatedly dropped SSH (single uplink via LEVEL-02). A live VPN concentrator on a single-homed leg is fragile — another reason to move these peers to the HA edge.
Anomaly: input firewall also permits udp/18475 ("Allow Wireguard") but no second WG interface exists — stale rule, remove.
2. The peers (12)¶
Every peer's allowed-address is just its own /32 tunnel IP (standard hub-and-spoke). The intended WAN-only vs network-access split is expressed only by the DNS each client is handed — not by any firewall rule (see §3, this is the key finding).
Network-access peers (handed internal DNS 10.1.84.34)¶
| Peer | Tunnel IP | Last handshake | Notes |
|---|---|---|---|
| lewis | 10.249.1.2 | active | also individually in management list |
| sina | 10.249.1.3 | active | high traffic (~6.8 GiB) |
| chris | 10.249.1.4 | 6d | |
| james | 10.249.1.5 | 3d | high traffic (~7.1 GiB) |
| lewis-2 | 10.249.1.12 | 1d | |
| sean | 10.249.1.13 | active |
WAN-only peers (handed public DNS 8.8.8.8 / 8.8.4.4)¶
| Peer | Tunnel IP | Last handshake | Notes |
|---|---|---|---|
| sina-parents-1 | 10.249.1.6 | never | idle |
| sina-parents-2 | 10.249.1.7 | active | |
| sina-parents-3 | 10.249.1.11 | 2d | |
| jamie | 10.249.1.8 | active | |
| sadaf | 10.249.1.9 | 46m | |
| caldytablet | 10.249.1.10 | active |
All peers share client-endpoint=wgvpn.pubinvest.co.uk and is-responder=yes (this box is the responder; clients dial in).
3. ⚠ The split is NOT enforced today¶
The forward chain on CR-LEVEL-04 is:
accept established / related
drop invalid
jump nat (dstnat)
drop in-interface-list=wan ← only drops traffic entering from WAN
There is no final default-drop for forward, so RouterOS's default-accept applies. WireGuard peer traffic arrives on wg000 (not a wan interface), so none of it is filtered — every peer, including the "WAN-only" family devices, can currently reach the entire internal 10.0.0.0/8 simply by adding a route on their client. The DNS handed out is the only difference, and DNS is a client-side convenience, not a control.
Worse: the management address-list contains 10.249.1.0/26 — i.e. every VPN client (family included) is permitted to SSH / WinBox / HTTPS into routers. Plus 10.249.1.2 (lewis) individually.
Implication for the move: don't replicate this. The migration is the moment to make the WAN-only vs network-access split real, and to stop treating the whole VPN pool as trusted management.
4. Target: ONE instance, per-peer firewall policy (no user changes)¶
Recommended. Keep a single WireGuard instance and decide WAN-only vs network-access per peer in the firewall, keyed on each peer's tunnel /32. One server key, one listen port, one endpoint → client configs never change, and moving a user between the two classes is a one-line address-list edit.
Why it's safe — WireGuard pins the source: each peer's allowed-address is its own /32, so the crypto layer drops any packet whose source isn't that peer's assigned IP. A WAN-only peer therefore cannot spoof a network-access peer's source /32 to gain entry. Firewalling on source /32 is thus as strong as the tunnel itself.
/interface list member add interface=wg000 list=vpn
/ip firewall address-list
add list=vpn-full-access address=10.249.1.2 ;# lewis
add list=vpn-full-access address=10.249.1.3 ;# sina
add list=vpn-full-access address=10.249.1.4 ;# chris
add list=vpn-full-access address=10.249.1.5 ;# james
add list=vpn-full-access address=10.249.1.12 ;# lewis-2
add list=vpn-full-access address=10.249.1.13 ;# sean
/ip firewall filter
# 1. isolate peers from each other (family can't reach staff tunnels)
add chain=forward in-interface-list=vpn out-interface-list=vpn action=drop
# 2. full-access peers -> internal (jump to a scoped chain, not blanket 10/8 — zero-trust)
add chain=forward in-interface-list=vpn src-address-list=vpn-full-access action=accept
# 3. everyone else: no internal at all
add chain=forward in-interface-list=vpn dst-address=10.0.0.0/8 action=drop
add chain=forward in-interface-list=vpn dst-address=172.16.0.0/12 action=drop
# 4. WAN-only path: internet permitted (masquerade already covers NAT)
add chain=forward in-interface-list=vpn out-interface-list=wan action=accept
Membership of vpn-full-access is the policy. Promote/demote a user = add/remove their /32. No client touch, no key change, no reconnect. (Rule 2 should ideally jump to a chain that permits only what staff need — AD, specific server-room services — rather than blanket-accept, to keep DESIGN §10 zero-trust.)
Caveats, eyes open:
- DNS is client-side. WAN-only peers have 8.8.8.8 baked in their config, staff have 10.1.84.34. Firewall policy doesn't change that. Promoting a specific family peer to full-access later means they reach internal nets but still resolve via public DNS until their config is reissued once — fine for the no-change-now goal.
- Shared concentrator. One firewall slip affects both trust classes, and untrusted family devices share the instance with staff. Rule 1 (intra-VPN drop) + source-pinning contains the blast radius; if you want hard isolation instead, use §4-ALT.
- Management list: still remove the blanket 10.249.1.0/26 from router management lists (§3). With this model, only the vpn-full-access staff /32s (or a smaller admin subset) should ever be management sources.
4-ALT. Two instances (higher isolation, only if you want it)¶
If you'd rather physically separate the classes: WAN-only peers on an internet-only instance in guest/DMZ space (NAT to WAN, no 10/8), staff peers on an OPNsense road-warrior instance into a restricted zone. Stronger isolation, but this one requires reissuing the moved peers' configs (different server key/endpoint) — i.e. user changes. Only worth it if the shared-concentrator risk above is unacceptable.
4b. Where it runs & the move mechanics¶
- Run the single instance on the OPNsense pair (CARP HA — survives a node failure, unlike CR-LEVEL-04 today). WireGuard binds the CARP VIP; the address-list model above maps directly to OPNsense/pf per-peer rules. (Or keep it on a dedicated HA-capable RouterOS box if you prefer ROS tooling — the model is identical.)
- Regenerate the server keypair on the new endpoint (old key is exposed, §top). This is the one unavoidable reissue — but note it happens once, for everyone, as key hygiene, not as part of splitting users. Keep the DNS name
wgvpn.pubinvest.co.uk, re-point it to the new VIP; reissue all 12 configs with the new server public key. After that, the per-peer WAN/network policy is pure firewall and never touches a client again. - Preserve tunnel IPs
10.249.1.x— the firewall rules and logs stay meaningful, and the address-list keys off them. gre-bolton: disabled/dormant — confirm the Bolton site is dead, then delete (remote178.17.243.197).- Retire the stale
udp/18475input rule. - Sequence: stand up the instance on OPNsense → reissue configs (new server key) → cut over → apply the address-list policy → remove WG from CR-LEVEL-04 → box free for its MOVE-PLAN §8 role decision.
5. Follow-ups¶
- [ ] Rotate/regenerate WG server key; re-issue all 12 client configs once (keys exposed) — the only user-visible step, and it's key hygiene, not the split.
- [ ] Single instance + per-peer firewall by tunnel
/32(§4); thevpn-full-accesslist is the whole policy thereafter. - [ ] Scope rule 2 to a zero-trust chain (staff → only needed services), not blanket 10/8.
- [ ] Remove
10.249.1.0/26frommanagementlists fleet-wide; only staff/32s (or an admin subset) as management sources. - [ ] Confirm & delete
gre-bolton(Bolton site status). - [ ] Delete stale
udp/18475rule.