Every UniFi device phones home to its controller on port 8080. The payload is AES-encrypted, but the header is plaintext, and that's enough to build multi-tenant routing.
A few years ago I ran a small UniFi hosting service. Managed cloud controllers for MSPs and IT shops who didn't want to run their own. Every customer got their own VPS running a dedicated controller.
The product worked. People wanted hosted controllers, mostly so they didn't have to deal with hardware, port forwarding, backups. The problem was the economics.
Each customer needed their own VPS. DigitalOcean droplets ran $4-6/month. I was charging $7-8. That's $1-2 of margin per customer, and any support request at all wiped it out. I was essentially volunteering.
The obvious fix is multi-tenancy: put multiple controllers on shared infrastructure instead of giving every customer their own VM. But UniFi controllers aren't multi-tenant. Each one is its own isolated instance with its own database and port bindings. You need a routing layer, something in front that can look at incoming traffic and figure out which customer it belongs to.
For the web UI on port 8443, that's easy. Subdomain per customer behind a reverse proxy, nothing special. But the inform protocol on port 8080 is where things get interesting.
What inform does
Every UniFi device (access points, switches, gateways) phones home to its controller. An HTTP POST to port 8080 every 10 seconds. This is how the controller keeps track of everything: device stats, config sync, firmware versions, client counts.
The payload is AES-128-CBC encrypted. So I assumed you'd need per-device encryption keys to do anything useful with the traffic, which would mean you'd need the controller's database, which would mean you're back to one instance per customer.
Then I looked at the raw bytes.
... continue reading