Reverse-engineering UniFi inform protocol for multi-tenant routing

✍️ OpenClawRadar📅 Published: March 9, 2026🔗 Source
Reverse-engineering UniFi inform protocol for multi-tenant routing
Ad

UniFi inform protocol structure

Every UniFi device (access points, switches, gateways) phones home to its controller via HTTP POST to port 8080 every 10 seconds. This handles device stats, config sync, firmware versions, and client counts. While the payload is AES-128-CBC encrypted, the header contains plaintext device identification.

Packet header details

The first 40 bytes of every inform packet are unencrypted:

Offset Size Field
────── ───── ──────────────────────────
0      4B    Magic: "TNBU" (0x544E4255)
4      4B    Packet version (currently 0)
8      6B    Device MAC address
14     2B    Flags (encrypted, compressed, etc.)
16     2B    AES IV length
18     16B   AES IV
34     4B    Data version
38     4B    Payload length
42+    var   Encrypted payload (AES-128-CBC)

The MAC address at byte offset 8 is completely unencrypted. "TNBU" is "UBNT" backwards (Ubiquiti's ticker symbol and default SSH credentials).

Ad

MAC extraction and routing

Extracting the MAC requires minimal code:

header := make([]byte, 40)
if _, err := io.ReadFull(conn, header); err != nil {
    return err
}
if string(header[0:4]) != "TNBU" {
    return fmt.Errorf("not an inform packet")
}
mac := fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", 
    header[8], header[9], header[10], 
    header[11], header[12], header[13])

With the MAC in hand, routing becomes simple: maintain a table mapping MAC addresses to tenants, then forward the entire packet (header and encrypted payload untouched) to the correct backend. The proxy can be implemented in about 200 lines of Go with an in-memory MAC-to-tenant lookup table.

Controller port overview

Other controller ports include:

  • 8443 TCP/HTTPS: Web UI and API
  • 3478 UDP: STUN
  • 6789 TCP: Speed test (internal)
  • 27117 TCP: MongoDB (internal)
  • 10001 UDP: L2 discovery (local only)

The MAC-based routing primarily serves as a fallback for edge cases like devices that haven't been reconfigured yet or factory-reset devices re-adopting. Once adopted, devices can be pointed at tenant-specific subdomains using standard Host header routing.

📖 Read the full source: HN AI Agents

Ad

👀 See Also

Claude Code Logs Every Session to Disk — Here's How to Index and Recall Them
Tools

Claude Code Logs Every Session to Disk — Here's How to Index and Recall Them

Claude Code writes every session turn to ~/.claude/projects/ as JSONL. One user indexed 1026 sessions (57MB, 76K turns) into SQLite+FTS5 with an MCP server for search and thread recall across sessions.

OpenClawRadar
Interact MCP: Faster Web Browsing for Claude Code with Persistent Chromium
Tools

Interact MCP: Faster Web Browsing for Claude Code with Persistent Chromium

Interact MCP is a Model Context Protocol tool that keeps a persistent Chromium browser in-process, reducing browser action times from 2-5 seconds to 5-50ms after the initial call. It features a ref system for element interaction without CSS selectors and includes 46 tools for web automation.

OpenClawRadar
Bernstein: A Kubernetes-like orchestrator for AI coding agents with verification and model policies
Tools

Bernstein: A Kubernetes-like orchestrator for AI coding agents with verification and model policies

Bernstein is an orchestrator for AI coding agents that includes independent verification of agent outputs, model policy controls, 13 agent adapters, and deterministic Python-based scheduling. The project has 5000+ tests and features like circuit breakers, cost anomaly detection, and PII scanning.

OpenClawRadar
Memento v1.0: Local Persistent Memory for AI Coding Agents
Tools

Memento v1.0: Local Persistent Memory for AI Coding Agents

Memento v1.0 is a fully local memory layer for AI coding agents that runs embeddings, storage, and search on your machine with no cloud dependencies. It uses all-MiniLM-L6-v2 embeddings, HNSW indexing, and supports multiple IDEs with 17 MCP tools.

OpenClawRadar