aboutsummaryrefslogtreecommitdiffstats
path: root/packaging/win/firewall.ps1
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-04 15:54:05 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-04 15:54:05 +0200
commit7ff675fdc0866ca40bdb703bc95c0cc60e3edd87 (patch)
tree46a3cd561a876dfea9aa511b3410b5224a032613 /packaging/win/firewall.ps1
parent74941aae5451c03a296413710fe888b1924e8c27 (diff)
downloadmeshbay-7ff675fdc0866ca40bdb703bc95c0cc60e3edd87.tar.gz
feat(packaging): cover LAN casting in the Windows firewall step, too
firewall.ps1 only handled WebRTC. The cast HTTP relay (src/cast-relay.js, fixed TCP 19550-19553) and Chromecast/Smart TV mDNS discovery (src/cast-chromecast.js, bonjour-service, UDP 5353) are a separate surface on the client and were still hitting Windows' own "Allow access" dialog. Now four named rules: MeshBay / MeshBay Node stay program-scoped with no port restriction (there is no fixed WebRTC port to name -- the Windows equivalent of the broad 1024-65535/udp range the Linux packaging needs, since netfilter has no program scoping); MeshBay Cast / MeshBay Cast Discovery add the program AND the fixed port, matching packaging/firewall/*/meshbay-cast.xml exactly. test_packaging_win.py cross-checks the port numbers against cast-relay.js's own constants and the Linux firewalld definition, so the three descriptions of one port range can't quietly drift apart. Verified: rebuilt MeshBay-Setup-0.1.0.exe; the deployed firewall.ps1 carries all four rules. Node suite 836 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.ps162
1 files changed, 42 insertions, 20 deletions
diff --git a/packaging/win/firewall.ps1 b/packaging/win/firewall.ps1
index abed109..bf1b32b 100644
--- a/packaging/win/firewall.ps1
+++ b/packaging/win/firewall.ps1
@@ -3,19 +3,33 @@
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.
+ Two independent things need an inbound allow, and Windows prompts
+ "Allow access" for each the first time it happens if there is no rule:
+
+ 1. WebRTC (MeshBay.exe and meshbay-node.exe). It binds an ephemeral UDP
+ port per connection, and the browser always dials the node -- aioice
+ cannot resolve the peer's mDNS `.local` candidate to call back -- so the
+ node (and, during ICE connectivity checks, the client) must accept
+ unsolicited inbound UDP. There is no fixed port, so these rules are
+ scoped by PROGRAM with no LocalPort restriction, which is the Windows-
+ native way to say "this binary, any port it happens to bind" -- the
+ Linux packaging (packaging/firewall/) has to approximate the same thing
+ with a broad 1024-65535/udp port range because netfilter has no
+ equivalent program scoping.
+ 2. LAN casting (MeshBay.exe only): the HTTP relay to a Chromecast/Smart TV
+ (src/cast-relay.js, fixed TCP 19550-19553) and mDNS device discovery
+ (src/cast-chromecast.js via bonjour-service, UDP 5353). Both scoped by
+ program AND port -- narrower than the WebRTC rules, since these ports
+ are fixed and known. Matches packaging/firewall/*/meshbay-cast.xml.
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.
+ instead of up to four dialogs spread across first use of chat, downloads
+ and casting. Declining the installer's offer is fine -- the dialogs are
+ the fallback, one per program/port combination as each is first used.
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
+ 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
@@ -37,28 +51,36 @@ $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" }
+$client = Join-Path $install "MeshBay.exe"
+$node = Join-Path $resources "node-runtime\meshbay-node.exe"
+
+# Program-scoped, any port: the ephemeral-UDP-port problem WebRTC always has.
+# Port-scoped as well: the two fixed, known ports LAN casting actually uses.
+$rules = @(
+ @{ Name = "MeshBay"; Path = $client; Protocol = "UDP"; LocalPort = "Any" }
+ @{ Name = "MeshBay Node"; Path = $node; Protocol = "UDP"; LocalPort = "Any" }
+ @{ Name = "MeshBay Cast"; Path = $client; Protocol = "TCP"; LocalPort = "19550-19553" }
+ @{ Name = "MeshBay Cast Discovery"; Path = $client; Protocol = "UDP"; LocalPort = "5353" }
)
try {
- foreach ($t in $targets) {
+ foreach ($r in $rules) {
# Idempotent: clear any existing rule of this name first.
- Remove-NetFirewallRule -DisplayName $t.Name -ErrorAction SilentlyContinue
+ Remove-NetFirewallRule -DisplayName $r.Name -ErrorAction SilentlyContinue
if ($Action -eq "add") {
- if (-not (Test-Path $t.Path)) {
- " skip $($t.Name): $($t.Path) not found" | Add-Content $log
+ if (-not (Test-Path $r.Path)) {
+ " skip $($r.Name): $($r.Path) not found" | Add-Content $log
continue
}
- New-NetFirewallRule -DisplayName $t.Name -Group $GROUP `
+ New-NetFirewallRule -DisplayName $r.Name -Group $GROUP `
-Direction Inbound -Action Allow `
- -Program $t.Path -Protocol UDP -Profile Any | Out-Null
- " allowed $($t.Name) ($($t.Path))" | Add-Content $log
+ -Program $r.Path -Protocol $r.Protocol -LocalPort $r.LocalPort `
+ -Profile Any | Out-Null
+ " allowed $($r.Name) ($($r.Protocol) $($r.LocalPort), $($r.Path))" | Add-Content $log
}
else {
- " removed $($t.Name)" | Add-Content $log
+ " removed $($r.Name)" | Add-Content $log
}
}
}