summaryrefslogtreecommitdiffstats
path: root/packaging/firewall
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-04 14:10:16 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-04 14:10:16 +0200
commit40abf0979f93771ccfb58eecb8a6fcc5863ec604 (patch)
tree9fe1c57408125a306831d09f243df1d75cf64ffd /packaging/firewall
parent8288714853952aca6b3511268b9d772f1b7f489f (diff)
downloadmeshbay-40abf0979f93771ccfb58eecb8a6fcc5863ec604.tar.gz
feat(packaging): ship a node firewall profile for inbound WebRTC
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 `<uuid>.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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DtfG7z6wHWj8RKHCvxQtY1
Diffstat (limited to 'packaging/firewall')
-rw-r--r--packaging/firewall/firewalld/meshbay-node.xml6
-rw-r--r--packaging/firewall/ufw/meshbay5
2 files changed, 11 insertions, 0 deletions
diff --git a/packaging/firewall/firewalld/meshbay-node.xml b/packaging/firewall/firewalld/meshbay-node.xml
new file mode 100644
index 0000000..2f863ec
--- /dev/null
+++ b/packaging/firewall/firewalld/meshbay-node.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<service>
+ <short>MeshBay Node</short>
+ <description>Inbound WebRTC/ICE for a MeshBay node. Peers connect over a DataChannel negotiated through the hub; there is no fixed listening port, because aiortc binds an ephemeral UDP port per connection. A peer that cannot reach the node directly can only be reached if the node initiates, which requires the peer to publish a routable address — browsers do not, they publish an mDNS .local name the node cannot resolve. So a node that refuses unsolicited inbound UDP is unreachable from any browser it cannot itself call back. Apply this to the zone holding the LAN interface only; it does not belong in an internet-facing zone. The node's administration surface is unaffected: it is a loopback API on 127.0.0.1 and is never exposed here.</description>
+ <port protocol="udp" port="1024-65535"/>
+</service>
diff --git a/packaging/firewall/ufw/meshbay b/packaging/firewall/ufw/meshbay
index 732e5d8..b87afdb 100644
--- a/packaging/firewall/ufw/meshbay
+++ b/packaging/firewall/ufw/meshbay
@@ -2,3 +2,8 @@
title=MeshBay Chromecast relay
description=HTTP relay for casting decrypted video to LAN devices
ports=19550:19553/tcp|5353/udp
+
+[MeshBay Node]
+title=MeshBay node WebRTC/ICE
+description=Inbound UDP for peer connections; scope it to your LAN with "from"
+ports=1024:65535/udp