Skip to content

Resolve client identity from complete UniFi data - #1094

Open
Jason-Morcos wants to merge 1 commit into
Ozark-Connect:mainfrom
Moballo-LLC:agent/fix-client-ip-resolution
Open

Resolve client identity from complete UniFi data#1094
Jason-Morcos wants to merge 1 commit into
Ozark-Connect:mainfrom
Moballo-LLC:agent/fix-client-ip-resolution

Conversation

@Jason-Morcos

Copy link
Copy Markdown
Contributor

Problem

UniFi's legacy stat/sta responses can omit a usable IP—or the client entirely—for devices behind newer UniFi bridges and consoles. The v2 active/history endpoints can still carry the address, while an IPv6 address may only be recoverable by joining the gateway neighbor table to the active client's MAC.

The Client Performance page currently treats those clients as unidentified even though the controller has enough data to resolve them.

Fix

  • enrich legacy client records from cached v2 active and history data
  • fall back to a direct v2 active-client identity when stat/sta omits the client
  • for IPv6 only, map the exact neighbor-table address to a MAC and join it to the active client
  • preserve the requested address, friendly name, wired/network metadata, and existing WiFiman/AP enrichment
  • retain cache invalidation when an address has genuinely moved to another device

Validation

  • 11 focused tests cover current/last/fixed address precedence, case-insensitive v2 enrichment, stale-data precedence, active-client mapping, exact IPv6 neighbor parsing, and metadata preservation
  • full Release NetworkOptimizer.Web.Tests: 1,291 passed

The validation used fixtures only; it made no controller, gateway, client, or network changes.

@tvancott42

Copy link
Copy Markdown
Collaborator

@Jason-Morcos do you have a concrete example of this happening? I haven't seen this one in the wild, even after adding the enhancements recently that resolve VPN/Tailscale/Teleport IPs on Client Performance.

Just curious what triggered the investigation and if I can repro it on one of my sites.

@Jason-Morcos

Jason-Morcos commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Thanks - yes. I was having an issue with some of my devices getting identified when trying to do LAN speed tests.

The first concrete case was a normal local iPhone (my iPhone). NetworkOptimizer received its actual LAN IPv4 address, but the available UniFi record had no current ip; only last_ip/fixed_ip matched. Client Performance originally matched only Ip, despite the model already exposing BestIp. But I think you actually already fixed the bug that was impacting that one

The case that current main still misses was a local, dual-stack Mac connected through both dock Ethernet and Wi-Fi:

  • stat/sta did not yield a client matching the request address.
  • The 720-hour history query did not contain a matching record either.
  • The v2 active-clients endpoint did contain the active device, its MAC, friendly identity, network metadata, and IPv4 address.
  • When the browser address was IPv6, UniFi’s active-client model did not expose that IPv6 address, but ip -6 neigh show on the gateway mapped the exact IPv6 neighbor to the same MAC present in v2 active clients.

On the unpatched path, IdentifyClientAsync exhausted stat/sta and history and returned null. With this change, an authenticated probe using the client’s forwarded IPv4 resolved directly from v2 active data, and the same probe using its IPv6 address resolved through the exact IPv6-neighbor-to-MAC join. Both returned the correct local client identity rather than “Device Not Found.”

This is separate from the VPN/Tailscale/Teleport enhancement. Those addresses intentionally receive a synthetic VPN identity because they are not ordinary UniFi LAN clients. This case is an ordinary local client that UniFi knows, but whose identity is split across legacy client data, v2 active data, and—for IPv6—the gateway neighbor table.

A minimal fixture reproduction would be:

  1. Have stat/sta omit the client or provide no usable address.
  2. Return the client’s MAC and IPv4 from v2/api/site/{site}/clients/active.
  3. Request Client Performance using that IPv4.

For the IPv6 variant, use a local IPv6 request address, a gateway neighbor row mapping it to the client MAC, and a v2 active record with that MAC. The focused tests in the PR model both shapes.

(I previously basically was running this code locally and had scripted up a way to patch every new NetworkOptimizer release to keep this fix in place)

@Jason-Morcos
Jason-Morcos force-pushed the agent/fix-client-ip-resolution branch from a42af7f to 836d56e Compare August 3, 2026 04:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants