Skip to content

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 (remote 178.17.243.197).
  • Retire the stale udp/18475 input 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); the vpn-full-access list 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/26 from management lists fleet-wide; only staff /32s (or an admin subset) as management sources.
  • [ ] Confirm & delete gre-bolton (Bolton site status).
  • [ ] Delete stale udp/18475 rule.