Fix: Filter out localhost/loopback IPs from device discovery#61
Fix: Filter out localhost/loopback IPs from device discovery#61sandinak wants to merge 4 commits into
Conversation
The discovery service was incorrectly reporting the local machine's network IP (e.g., 192.168.20.211) as the mixer IP address when receiving UDP broadcast packets. This happened because the local machine's own broadcast packets were being captured and reported as discovered devices. Root Cause: When listening for UDP broadcasts on port 47809, the discovery service receives packets from both the actual mixer AND the local machine's own network interfaces. The code was not filtering out the local machine's IP addresses, causing rinfo.address to return the local IP instead of the mixer's IP. Solution: - Added getLocalIPs() function to enumerate all local network interfaces - Added isLocalIP() function to check if an IP belongs to local machine - Filter out all local IPs (including 192.168.x.x, 10.x.x.x, etc.) - Filter out loopback addresses (127.0.0.0/8) - Early return in message handler to skip local discoveries Changes: - Import networkInterfaces from node:os - Added getLocalIPs() helper (lines 12-3- Added getLocalIPs() helper (lines 12-3- Added getLocalIPs() helpep() (line 92) - Filter check in message handler (lines 105-108) TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTemitted in the 'discover' event, preventing false positives from the local machine's own UDP broadcasts.
de4d63e to
8602a9c
Compare
Update: Corrected the FixI've updated this PR with the correct fix. The issue was not about localhost (127.0.0.1), but rather about the local machine's network IP being reported. Actual ProblemWhen the discovery service listens for UDP broadcasts, it receives packets from:
The code was reporting the local machine's IP (192.168.20.211) as the "discovered" mixer, which caused connection failures. Updated SolutionThe fix now:
Code ChangesAdded:
Modified:
ResultNow only remote device IPs (like the actual mixer) will be emitted in discovery events. The local machine's own broadcast packets are correctly filtered out. Testing✅ Build successful with |
Fixed 6 high severity vulnerabilities in dependencies: Changes: - Replaced npm-run-all with npm-run-all2 (maintained fork) - Updated @swc/cli and @swc/core to latest versions - Added overrides section to force secure versions of: - minimatch ^10.2.1 (was <10.2.1, had ReDoS vulnerability) - glob ^11.0.0 (was using old versions with vulnerable minimatch) - rimraf ^6.0.1 (was using old versions with vulnerable glob) Result: npm audit now shows 0 vulnerabilities Build tested and working correctly
Enhancements: - Added 'model' and 'deviceName' fields to DiscoveryType - model: Device model (e.g., 'StudioLive 16R') - deviceName: User-assigned name (e.g., 'Office') - name: Kept for backward compatibility (same as model) - Added console logging for better debugging: - Log filtered local IPs on startup - Log when discovery starts listening - Log each discovered device with model, name, IP, and serial This helps diagnose discovery reliability issues and provides more useful device information to applications.
Discovery: - Source-port filter: reject packets not from port 47809, preventing other software (DAW plugins, Universal Control, other app instances) from appearing as mixers - Refresh localIPs on every packet so VPN/dynamic interface changes don't produce stale filter entries API cleanup: - Remove debug console.log statements from simple/index.ts, packetParsers, messageProtocol, zlibUtil, and zlibNodeParser - Remove MeterServer.ts debug logging - Client.ts: remove unused debug instrumentation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Do you have examples of local processes emitting discovery packets, where they override the reported addresses? These LOCs should be correct in functionality
-- I can't verify the behaviour for the CS18AI as I don't own one, but I'll check out what the NSBs look like when on the network |
| // This rejects any other software sending UCNet-compatible packets from | ||
| // a different source port (e.g. another instance of this app, DAW | ||
| // plugins, or Universal Control running on the same machine). | ||
| if (rinfo.port !== 47809) return; |
There was a problem hiding this comment.
On the AVB network, the NSB 16.8 and NSB 8.8 emit from 49153/udp to (broadcast) 47809/udp
My packet capture didn't pick up the console broadcast on that network. Would have to look at the usual control network
| // The model name must look like a real PreSonus device. Known prefixes: | ||
| // "StudioLive", "CS18AI", "NSB". Reject anything that doesn't match to | ||
| // prevent other instances of this app from appearing as mixers. | ||
| const knownModelPrefix = /^(StudioLive|CS18AI|NSB)/i; |
| const discoveryData = { | ||
| name: model, // Keep 'name' for backward compatibility | ||
| model, | ||
| deviceName: deviceName || undefined, |
There was a problem hiding this comment.
The array destructure already assigns deviceName to undefined, no real need to provide a fallback value of undefined
|
|
||
| // eslint-disable-next-line | ||
| const [nameA, _, serial, nameB] = fragments; | ||
| const [model, _, serial, deviceName] = fragments; |
There was a problem hiding this comment.
This is welcomed info about the data structure, thanks!
Problem
The discovery service had multiple issues:
Incorrect IP Reporting: Discovery was returning the local machine's IP (192.168.20.211) instead of the actual mixer's IP address when receiving UDP broadcast packets, causing connection failures.
Missing Device Information: The UDP packet contains both the model name (e.g., "StudioLive 16R") and user-assigned device name (e.g., "Office"), but only the model was being captured.
Security Vulnerabilities: 6 high severity npm vulnerabilities in dependencies.
Limited Debugging: No logging to help diagnose discovery reliability issues.
Root Cause
When listening for UDP broadcasts on port 47809, the discovery service receives packets from both the actual mixer and local processes. The code was not filtering out local addresses, causing
rinfo.addressto sometimes return the host IP instead of the actual mixer's IP address.Solution
Commit 1: Fix Local IP Filtering
Added filtering logic to skip local machine IP addresses in the discovery message handler:
getLocalIPs()helper function usingnetworkInterfaces()fromnode:osto enumerate all local IPs (IPv4 and IPv6)isLocalIP()helper function to detect local machine addresses including loopback rangesCommit 2: Fix Security Vulnerabilities
Resolved all npm security issues:
npm-run-allwithnpm-run-all2(maintained fork)@swc/cliand@swc/coreto latest versionsoverridessection in package.json to force secure versions of transitive dependenciesCommit 3: Enhanced Device Information & Debugging
Improved discovery data and added debugging capabilities:
DiscoveryTypeinterface to include:model: Device model name (e.g., "StudioLive 16R")deviceName: User-assigned device name (e.g., "Office")name: Kept for backward compatibility (same as model)[Discovery] Found device: StudioLive 16R (Office) at 192.168.21.41 [RA1E24090034]Testing
npm run build- no TypeScript errorsnpm auditshows 0 vulnerabilitiesFound device: StudioLive 16R (Office) at 192.168.21.41 [RA1E24090034]Impact
namefield continues to workFiles Changed
src/lib/Discovery.ts- Local IP filtering and device name parsingsrc/lib/types/DiscoveryType.ts- Added model and deviceName fieldspackage.json- Updated dependencies and added overridespackage-lock.json- Locked secure dependency versionsPull Request opened by Augment Code with guidance from the PR author