Skip to content

wireguard: add Guest Party Mode - #148

Merged
ispyisail merged 2 commits into
masterfrom
feat/wireguard-guest-network-wizard
Jul 30, 2026
Merged

wireguard: add Guest Party Mode#148
ispyisail merged 2 commits into
masterfrom
feat/wireguard-guest-network-wizard

Conversation

@ispyisail

Copy link
Copy Markdown
Owner

Stacked on #145 (base branch is refactor/dedup-wg-client-config), for the same shared config builder #146/#147 use. Sibling of both, not stacked on either. Opened against the same base to keep merge order simple.

Sourced from a real forum thread (viewtopic.php?p=67974): a user wanted to host a temporary "LAN party" network for guests over WireGuard, isolated from the real home LAN.

The forum thread's own answer reached too far

The suggested fix was a second wg1 interface, "not in the GUI." wireguard_gargoyle has exactly one hardcoded server instance (config server 'server', not a list), so that's real backend/schema work.

It's unnecessary for what was actually asked. Two settings the WireGuard page already exposes do the whole job:

  • wireguard_server_subnet_access (lan_access) gates the firewall.lan_wg_forwarding section entirely. Off, and there is no forwarding rule into lan at all, not a narrowed one, an absent one.
  • wireguard_server_client_to_client (c2c) gates forward on the wg firewall zone. On, and guests reach each other and the router (where a shared game server would live).

So v1 here is a mode, not a new network: flip those two settings for the party, flip them back after. No new isolation mechanism, no new firewall rules, no new interface.

Why this can't be pure orchestration, unlike #146/#147

Both settings are global to the single WireGuard instance. Starting a party also cuts off any existing road-warrior (a family member's phone) relying on wg0 for LAN access, for as long as the party is on. This PR's entire design is about making that safe and reversible, not hiding it:

  • Warn and require confirmation before starting, if the server already has enabled clients. Names how many will be affected.
  • Capture the pre-party lan_access/c2c into new wireguard_gargoyle.server options (party_active, party_saved_lan_access, party_saved_c2c) before flipping, not into /tmp, so End Guest Party Mode still works after a reboot mid-party. Verified directly, not assumed: built a second, independent jsdom window seeded only from what the first window had actually persisted (simulating a real config reload), and confirmed both the active-party detection and the restore still work from that fresh state.
  • End Guest Party Mode restores the captured values exactly, not hardcoded defaults, tested against three different starting lan_access/c2c combinations, not just the shipped default.

Naming

Checked first, per the RFC's own instruction: basic.sh already has basicS.GNet="Guest Network" for the Wi-Fi guest network feature (grep-verified). "Guest Network" would collide with that in a user's mind. Named this "Guest Party Mode" instead.

Two real bugs found via an end-to-end smoke run, before any formal test existed

  1. Same have_privkey bug as wireguard: add a Remote Access Setup Wizard #146: addWgClientModal()'s own prefill sets that dropdown to false (correct, no key exists yet); generating a key afterward never flipped it back, so the just-generated private key was silently discarded on commit. Same fix as wireguard: add a Remote Access Setup Wizard #146.
  2. uciOriginal vs uci: unlike the Restrictions page, wireguard.js's saveChanges() does not update uciOriginal inline, it relies on a full page reload in production, 5 seconds after the save completes. openGuestPartyWizard()'s active-party check and guestPartyEnd()'s read of the saved values were both checking uciOriginal, which is stale mid-session (or in any flow, like this one, that reopens the wizard more than once without a reload in between). Fixed both to read the live uci, which is correct both immediately after a local change and on a genuinely fresh page load.

Reuse, same pattern as #146

generateKeyPair, addWgClientModal/addAc, saveChanges, wgBuildClientConfig/downloadAc are all called unchanged, not reimplemented. The config handoff (always-available .conf download, QR mentioned only as informational text pointing at the separate QR Code page) is identical to #146's design, not the RFC's original typeof encWireGuardQrCode sketch (superseded during #146's build; see that PR for why).

Testing

18 new tests:

  • party-isolation.test.js (5): asserted on the actual firewall sections saveChanges() emits, not just the lan_access UCI value, since the real guarantee is "no forwarding rule exists" and a value-only check would still pass if configureFirewall() regressed.
  • party-restore.test.js (7): three distinct starting lan_access/c2c combinations, the mid-party flip actually taking effect, party_active/party_saved_* correctly cleared afterward, and the reboot-survival simulation described above.
  • party-existing-clients.test.js (6): no re-key, an existing client's section and its own downloadable config both untouched by a full start/end cycle, and a two-guests-in-one-party case.

Full wireguard+qr-code suite: 86/86. This branch has neither #146's nor #147's code (sibling branches, not stacked), so their own wizard-*.test.js files fail here, confirmed as the same branch-topology artifact #147 already documented, not a regression, by excluding them and by stashing this entire diff and re-running.

Full node lane, same exclusion applied: clean, only the same 2 pre-existing unrelated failures (access-dropbear-preserve, vlan/switchinfo-emit), reconfirmed pre-existing on this branch by stashing.

page_lint.test.sh doesn't cover plugin pages (documented limitation). Hand-verified instead: all 9 new haserl <%~ %> references and all 11 new JS wgStr.* references checked one-for-one against the i18n file, all present, no gaps.

node --check clean, tabs verified, no em dashes, i18n BOM intact.

Not verified

Two real devices connecting to each other during an active party. Everything above is jsdom.

Out of scope (v2, explicitly not built here)

True simultaneous operation (party guests and family road-warriors isolated from each other at the same time) needs a genuinely second WireGuard instance, real schema and backend work across wireguard.js, wireguard.sh, and wireguard.firewall. Not a "v1.1"; scope separately if anyone actually wants it once v1 ships. Also out of scope: the forum thread's literal 10.50.0.x subnet request, the shared 10.64.0.x subnet already satisfies the actual isolation requirement.

Lets a user host a temporary, isolated WireGuard network for guests (e.g. a
LAN party): guests see each other and the router, never the real home LAN.
Flips the server's existing lan_access/client-to-client settings for the
duration and restores them exactly on End Guest Party Mode, since
wireguard_gargoyle has exactly one hardcoded server instance and both
settings are global to it.

Warns and requires confirmation before starting if the server already has
enabled clients, since starting a party also cuts off their LAN access for
as long as it's on. Captures the pre-party lan_access/c2c into new
wireguard_gargoyle.server options rather than /tmp, so ending the party still
works after a reboot mid-party. Named "Guest Party Mode" rather than "Guest
Network" to avoid colliding with the existing Wi-Fi guest network feature.
@ispyisail
ispyisail changed the base branch from refactor/dedup-wg-client-config to master July 30, 2026 08:17
@ispyisail
ispyisail merged commit 2454960 into master Jul 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant