From 40abf0979f93771ccfb58eecb8a6fcc5863ec604 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Fri, 4 Sep 2026 14:10:16 +0200 Subject: feat(packaging): ship a node firewall profile for inbound WebRTC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The packages carried a profile for LAN casting and none for the node's own peer traffic, on the reasoning that the node exposes only a loopback admin API. That is true of its administration surface and false of its transport. WebRTC binds an ephemeral UDP port per connection, so there is no fixed port to open, and a connection succeeds only if one side can initiate. Browsers publish their host candidate as an mDNS `.local` name, which aioice cannot resolve on any platform and discards — so the node can never call a browser back, and the browser must call the node. A node that refuses unsolicited inbound UDP is unreachable from every browser on its own LAN, leaving reflexive candidates, which fail whenever both peers share one public IP and the router will not hairpin. Hit twice in one session on two different hosts: a firewalld zone narrowed to mdns + 19550-19553/tcp, and a ufw host with default deny-incoming. Both presented as "the app cannot connect", neither as a firewall message. Passive like the cast profile: packaged, not activated. The guide says to scope it to a LAN zone or source, including the libvirt case, where traffic from a guest to its own hypervisor is not masqueraded and so must be scoped to the guest subnet rather than the LAN. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01DtfG7z6wHWj8RKHCvxQtY1 --- packaging/build/build-node.sh | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'packaging/build') diff --git a/packaging/build/build-node.sh b/packaging/build/build-node.sh index 9ad4968..bd81096 100755 --- a/packaging/build/build-node.sh +++ b/packaging/build/build-node.sh @@ -75,12 +75,20 @@ cp "$REPO/packaging/systemd/meshbay-node.service" \ cp "$REPO/packaging/systemd/meshbay-node-user.service" \ "$ROOT/usr/lib/systemd/user/meshbay-node.service" -# --- Firewall profile --------------------------------------------------------- -# UFW (Ubuntu/Debian) — carries the "MeshBay Cast" LAN-casting profile only. -# The node's own admin surface is a loopback API (127.0.0.1, token-gated) and -# is never firewall-exposed, so it ships no profile. +# --- Firewall profiles -------------------------------------------------------- +# The node's admin surface is a loopback API (127.0.0.1, token-gated) and is +# never firewall-exposed. Its *peer* traffic is: WebRTC binds an ephemeral UDP +# port per connection, and a peer that publishes an unroutable address — every +# browser does, as an mDNS .local name aioice cannot resolve — can only be +# reached if it calls the node. A node refusing unsolicited inbound UDP is +# therefore unreachable from browsers on its own LAN. Both profiles are passive: +# packaged, not activated, and meant to be scoped to a LAN zone/source. mkdir -p "$ROOT/etc/ufw/applications.d" cp "$REPO/packaging/firewall/ufw/meshbay" \ "$ROOT/etc/ufw/applications.d/" +mkdir -p "$ROOT/usr/lib/firewalld/services" +cp "$REPO/packaging/firewall/firewalld/meshbay-node.xml" \ + "$ROOT/usr/lib/firewalld/services/" + echo "==> meshbay-node staging ready at $ROOT" -- cgit v1.2.3