Multi-user collision: livekit-server binds on every global IPv6, EADDRINUSE on sibling user's mycelium bridge #31

Open
opened 2026-04-29 02:39:29 +00:00 by sameh-farouk · 0 comments
Member

Context

Multi-user Hero boxes provision a per-user mycelium IPv6 /64 bridge (e.g. br-sameh at 4a0:6976:8fa7:efc:5::1, br-ashraf at 4a0:6976:8fa7:efc:1::1). Each user runs their own livekit-server configured with node_ip = <their bridge IP>, expecting traffic to be scoped to that interface.

Bug

livekit-server uses Pion's UDP port-mux for the RTC port (default 7882). When rtc.ips.includes is unset, Pion auto-enumerates every global IPv6 address on the host and tries to bind UDP/7882 on each. Result: the second user to start hits EADDRINUSE on a sibling user's bridge IP, even though that IP isn't theirs.

Observed on dev box:

listen udp [4a0:6976:8fa7:efc:1::1]:7882: bind: address already in use

That IP is br-ashraf, but the message comes from sameh's livekit-server attempting to bind it via Pion auto-enumeration.

The collision is amplified by stale bridge addresses lingering after a user is removed (separate multi_user_del cleanup gap), but the root cause is the unrestricted Pion enumeration.

Fix

Render rtc.ips.includes: ["<node_ip>/128"] into the generated livekit.yaml so the SFU pins UDP binding (and ICE candidate advertisement) to its configured node_ip only.

Per livekit upstream, this is the documented restriction mechanism:

Verification

Patch tested on dev box 138.201.206.39. Both users' livekit-server instances now bind only on their own bridge IP and run concurrently. PR: #TBD.

## Context Multi-user Hero boxes provision a per-user mycelium IPv6 /64 bridge (e.g. `br-sameh` at `4a0:6976:8fa7:efc:5::1`, `br-ashraf` at `4a0:6976:8fa7:efc:1::1`). Each user runs their own `livekit-server` configured with `node_ip = <their bridge IP>`, expecting traffic to be scoped to that interface. ## Bug livekit-server uses Pion's UDP port-mux for the RTC port (default 7882). When `rtc.ips.includes` is unset, Pion auto-enumerates **every global IPv6 address on the host** and tries to bind UDP/7882 on each. Result: the second user to start hits `EADDRINUSE` on a sibling user's bridge IP, even though that IP isn't theirs. Observed on dev box: ``` listen udp [4a0:6976:8fa7:efc:1::1]:7882: bind: address already in use ``` That IP is `br-ashraf`, but the message comes from sameh's `livekit-server` attempting to bind it via Pion auto-enumeration. The collision is amplified by stale bridge addresses lingering after a user is removed (separate `multi_user_del` cleanup gap), but the root cause is the unrestricted Pion enumeration. ## Fix Render `rtc.ips.includes: ["<node_ip>/128"]` into the generated `livekit.yaml` so the SFU pins UDP binding (and ICE candidate advertisement) to its configured `node_ip` only. Per livekit upstream, this is the documented restriction mechanism: - https://github.com/livekit/livekit/issues/1876 - https://github.com/livekit/livekit/issues/3842 ## Verification Patch tested on dev box `138.201.206.39`. Both users' `livekit-server` instances now bind only on their own bridge IP and run concurrently. PR: #TBD.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_livekit#31
No description provided.