#17257: fix(bonjour): stop mDNS flood on multi-NIC same-LAN setups (#17222)
gateway
stale
size: M
trusted-contributor
Cluster:
Gateway Resilience and Configuration
## Summary
Running `openclaw gateway` on a machine with multiple network interfaces on the same LAN (e.g. both ethernet and WiFi) causes an mDNS flood — every device on the network starts continuously querying `openclaw.local` and the machine responds from both IPs, making the LAN unusable.
Closes #17222
lobster-biscuit
## Root Cause
`startGatewayBonjourAdvertiser` calls ciao's `getResponder()` with no options, so the mDNS responder binds to all network interfaces. When two interfaces share the same LAN (like `enp5s0` at 192.168.1.130 and `wlan0` at 192.168.1.118), ciao advertises and responds on both, triggering a flood of conflicting mDNS responses with cache-flush bits set.
## Changes
- Before: mDNS responder binds to all interfaces — multi-NIC same-LAN setups cause mDNS storms
- After: responder is restricted to the primary LAN interface via `pickPrimaryLanIPv4()` (prefers en0/eth0, falls back to first external IPv4)
The fix adds a `networkInterface` option to `GatewayBonjourAdvertiseOpts` and passes it through to ciao's `getResponder({ interface })`. The caller in `server-discovery-runtime.ts` resolves the primary LAN IP using the existing `pickPrimaryLanIPv4()` helper.
## Tests
- `src/infra/bonjour.test.ts` — 2 new tests: verifies `getResponder` receives the `interface` option when `networkInterface` is set, and receives `undefined` when omitted. Both fail before fix, pass after.
- All 9 bonjour tests pass, all 75 infra tests pass, all 44 gateway tests pass
- `pnpm build && pnpm check` pass
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR fixes an mDNS flood issue on machines with multiple network interfaces on the same LAN (e.g., both Ethernet and WiFi). The fix pins the ciao mDNS responder to a single primary LAN interface via the existing `pickPrimaryLanIPv4()` helper, rather than binding to all interfaces which caused conflicting mDNS responses.
- Added `networkInterface` option to `GatewayBonjourAdvertiseOpts` and wired it through to ciao's `getResponder({ interface })` in `src/infra/bonjour.ts`
- `server-discovery-runtime.ts` resolves the primary LAN IP via `pickPrimaryLanIPv4()` (prefers `en0`/`eth0`, falls back to first external IPv4) and passes it as `networkInterface`
- The `undefined` case (no LAN IP found) is handled correctly — ciao falls back to binding all interfaces, preserving existing behavior for single-NIC setups
- Well-tested: 3 new unit tests in `bonjour.test.ts` and 2 new integration tests in `server-discovery-runtime.test.ts`
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge — it's a targeted, well-tested fix that gracefully falls back to existing behavior when no primary LAN IP is found.
- The change is minimal and focused: a single new option threaded through existing plumbing, with a correct ternary guard that avoids passing `{ interface: undefined }` to ciao. The `undefined` fallback preserves existing behavior for single-NIC setups. All edge cases (set, omitted, explicitly undefined) are covered by tests. No security concerns, no breaking API changes, and no unintended side effects.
- No files require special attention.
<sub>Last reviewed commit: e4e4dfa</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#3831: fix: ignore mDNS socket errors to prevent gateway crashes
by cici1029 · 2026-01-29
80.9%
#4653: fix(gateway): improve crash resilience for mDNS and network errors
by AyedAlmudarra · 2026-01-30
80.1%
#19026: fix(gateway): use loopback for local CLI-to-gateway connections
by Phineas1500 · 2026-02-17
77.9%
#22056: fix(gateway): use loopback for self-connections regardless of bind ...
by usedhonda · 2026-02-20
76.3%
#22110: fix(tools): prefer loopback for internal tool-to-gateway RPC calls
by pierreeurope · 2026-02-20
74.7%
#19437: Gateway: respect custom bind host for local health/RPC target resol...
by frudas24 · 2026-02-17
73.8%
#23666: fix(doctor): openclaw-browser.service falsely flagged as duplicate ...
by yinghaosang · 2026-02-22
73.7%
#11455: fix(gateway): default gateway.mode to local when unset
by AnonO6 · 2026-02-07
73.6%
#22804: fix: prioritize loopback for internal gateway calls (issue #22706)
by ambicuity · 2026-02-21
73.4%
#18441: feat(gateway): add localNetworks config for subnet-scoped auto-pairing
by JayMishra-source · 2026-02-16
73.1%