diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-04 15:36:53 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-04 15:36:53 +0200 |
| commit | 74941aae5451c03a296413710fe888b1924e8c27 (patch) | |
| tree | 8dda07ea4f7c909122650a829447b871ca5b0997 /packaging/win/firewall.ps1 | |
| parent | d04b915580c8ba05beb0943a6fab9b04e12294e4 (diff) | |
| download | meshbay-74941aae5451c03a296413710fe888b1924e8c27.tar.gz | |
feat(packaging): offer one elevated firewall step instead of two dialogs
Installing used to mean clicking through two separate Windows "Allow
access" prompts later — one for MeshBay.exe, one for meshbay-node.exe —
each confusing on its own and worse before the exe carried a version
resource. Adding a firewall rule needs admin, and the installer is
deliberately per-user with no elevation, so this can only ever be opt-in.
packaging/win/firewall.ps1 (new, shipped as an extraResource at
resources\firewall.ps1): idempotent add/remove of the two inbound UDP
rules ("MeshBay", "MeshBay Node"), grouped, logged to
%TEMP%\meshbay-firewall.log. Locates both executables from its own path,
no arguments needed beyond the action.
build/installer.nsh: customInstall asks "Allow MeshBay through Windows
Firewall now?" and runs firewall.ps1 via NSIS ExecShellWait "runas" — one
UAC prompt — only when not ${Silent}; declining or dismissing UAC falls
back to Windows' own per-process prompts, unchanged. customUnInstall
offers the same in reverse, defaulted to No (a stale rule for a deleted
exe is inert, so this should not nag on the way out) and skipped for a
silent uninstall.
Verified: rebuilt MeshBay-Setup-0.1.0.exe (electron-builder compiles the
new LogicLib.nsh / ExecShellWait NSIS successfully); firewall.ps1 run
unelevated fails cleanly into its log ("Access is denied") rather than
silently doing nothing, confirming the fallback path. Node suite 835
pass / 25 skip.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'packaging/win/firewall.ps1')
| -rw-r--r-- | packaging/win/firewall.ps1 | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/packaging/win/firewall.ps1 b/packaging/win/firewall.ps1 new file mode 100644 index 0000000..abed109 --- /dev/null +++ b/packaging/win/firewall.ps1 @@ -0,0 +1,68 @@ +<# +.SYNOPSIS + Add (or remove) the inbound Windows Firewall rules MeshBay needs. + +.DESCRIPTION + WebRTC binds an ephemeral UDP port per connection and the browser always + dials the node (aioice cannot resolve the peer's mDNS `.local` candidate), + so the node must accept unsolicited inbound UDP. Without a rule, Windows + pops an "Allow access" dialog the first time each of MeshBay.exe and + meshbay-node.exe binds a socket. + + The installer runs this once, elevated, so the user answers one UAC prompt + instead of two firewall dialogs later. Declining the installer's offer is + fine -- the dialogs are the fallback. + + Shipped as an extraResource at <install>\resources\firewall.ps1, so it + locates the two executables from its own path and takes no arguments beyond + the action. Runs elevated and windowless, so it leaves a trace at + %TEMP%\meshbay-firewall.log. + +.PARAMETER Action + add (default) create/replace the rules + remove delete them +#> +[CmdletBinding()] +param( + [ValidateSet("add", "remove")] + [string]$Action = "add" +) + +$ErrorActionPreference = "Stop" +$log = Join-Path $env:TEMP "meshbay-firewall.log" +"[{0}] {1}" -f (Get-Date -Format s), $Action | Add-Content $log + +# This script sits at <install>\resources\firewall.ps1. +$resources = $PSScriptRoot +$install = Split-Path -Parent $resources +$GROUP = "MeshBay" + +$targets = @( + @{ Name = "MeshBay"; Path = Join-Path $install "MeshBay.exe" } + @{ Name = "MeshBay Node"; Path = Join-Path $resources "node-runtime\meshbay-node.exe" } +) + +try { + foreach ($t in $targets) { + # Idempotent: clear any existing rule of this name first. + Remove-NetFirewallRule -DisplayName $t.Name -ErrorAction SilentlyContinue + + if ($Action -eq "add") { + if (-not (Test-Path $t.Path)) { + " skip $($t.Name): $($t.Path) not found" | Add-Content $log + continue + } + New-NetFirewallRule -DisplayName $t.Name -Group $GROUP ` + -Direction Inbound -Action Allow ` + -Program $t.Path -Protocol UDP -Profile Any | Out-Null + " allowed $($t.Name) ($($t.Path))" | Add-Content $log + } + else { + " removed $($t.Name)" | Add-Content $log + } + } +} +catch { + " ERROR: $_" | Add-Content $log + throw +} |