Intro

These are the mad writings of an lone engineer and not official documentation.

Here be dragons.

What is this?

This book documents what I've observed and learned about UniFi and how the SDN works. This book is based on and is a continuation of previous works of others. There is no set reading order for this book.

💡 Tip: You can search through this book by clicking on the 🔍 icon at the top of the page, or by pressing the s key.

Who is this for?

This book is for anyone who is interested in how UniFi's SDN devices work. You should be familiar with networking and some knowledge of data encryption and compression.

Contributing

This book is open source! Find a typo? Was something overlooked? Send a pull request!

License

This book is released under the Apache License 2.0

Protocols

This section documents what I've learned about how the UniFi protocols are structured.

Discovery Protocol

A factory reset UniFi device will send discovery packets as multicast to 233.89.188.1. The packets are based on Type-Length-Value (TLV). The value is a list of TLVs.

Packet Structure

OffsetSizeName
0u8Packet version
1u8Type
2-3u16Length
4[u8]Value

There are currently two (maybe three?) packet versions. At the moment this document is only covering version 2.

Packet Value Types

TypeNameContent
0x01HardwareAddress[u8; 6]
0x02IpInfoHardwareAddress([u8; 6]), IPv4([u8; 4])
0x03FirmwareVersionString
0x04UnknownUnknown
0x05UnknownUnknown
0x06UsernameString
0x07Salt[u8]
0x08Challenge[u8]
0x09UnknownUnknown
0x0AUptimei64
0x0BHostnameString
0x0CPlatformString
0x0DESSIDString
0x0EWModei32
0x0FUnknownUnknown
0x10UnknownString
0x11UnknownUnknown
0x12Sequence *i32
0x13Serial **String
0x14UnknownUnknown
0x15ModelString
0x16MinimumControllerVersionString
0x17IsDefaultbool
0x18Unknownbool
0x19Unknownbool
0x1AUnknownbool
0x1BVersionString
0x1CUnknowni32
0x1DUnknownString

* Sequence is an incrementing number
** Serial is usually the hardware address without any separators

Inform Protocol

UniFi devices communicate to their controller via HTTP POST as application/x-binary containing it's current status every ~10 seconds to the inform URL. The inform URL defaults to http://unifi:8080/inform but may be set to the controller's IP address. A controller will respond with either a no-op and an interval for the next inform or command for the device to execute. A UniFi device will execute commands and send another inform packet. Requests and responses share the same format encoded in big endian byte order. When reading, inform packets are decrypted before decompression, inverse is true for writing. There is currently only one payload version. Payload version 1 is JSON content and is the current version.

Encryption/Decryption

There are two possible ciphers used to encrypt the inform payload. Although you can send the controller plain-text, it will not respond to non-encrypted payloads. AES-CBC is used, and is the default, if the 1st-bit is set on the flag, or AES-GCM if the 1st-bit and 4th-bit are set. The Initialization Vector is 16 bytes in length and is sent in the header. The default encryption authkey is the MD5 hash of ubnt (ba86f2bbe107c7c57eb5f2690775c712). When decrypting AES-GCM the first 40 bytes of the packet is used as the additional authenticated data (AAD) and the last 16 bytes of the payload is the tag.

Compression/Decompression

There are two possible compression modes used at the moment. The default method is ZLib and uses the 2nd-bit of the flag. Snappy is another possible compression method and uses the 3rd-bit.

Packet Structure

OffsetSizeName
0-3u32Magic Header (TNBU or 1414414933)
4-7u32Packet Version
8-13[u8; 6]Hardware Address
14-15u16Flags
16-31[u8; 16]Initialization Vector for encryption
32-35u32Payload Version
36-39u32Payload Length
40-n[u8]Payload

Flags

ValueBitsName
0x010b0000000000000001Encrypted
0x020b0000000000000010ZLibCompressed
0x040b0000000000000100SnappyCompressed
0x080b0000000000001000EncryptedGCM

Inform Protocol JSON Payload

# TODO: Write about the inform JSON payload content, there is a lot here...

Table of Contents

Command Payloads

There are six command types at the moment.

NameType
_typeString: Inform Command Type
use_alertbool
device_idString
datetimeString
timeu64
cmdString
mgmt_cfgString
system_cfgString
md5sumString
urlString
versionString
intervalu64
server_time_in_utcString

Inform Command Type

TypeDescription
noopDo nothing
setparamUpdate a config (mgmt_cfg / system_cfg)
upgradeUpgrade the device using the firmware file located at url
rebootReboot the device
cmdRun a cmd
setdefaultFactory reset the device

Adoption

Official documentation for UniFi adoption methods

Layer 2 Adoption

UniFi adopts devices within the layer 2 network via an SSH remote command to assign the authkey used for inform encryption. The controller will send /usr/bin/syswrapper.sh set-adopt <inform_url> <authkey> to the device using the default username and password of ubnt:ubnt.

Layer 3 Adoption

Layer 3 adoption works by having a new device reach out with an inform packet to a 'remote' controller over HTTP POST using the default authkey. The new device will show as Pending Adoption in the UniFi controller UI until an operator adopts the device.

Adoption Process

On the first inform packet during adoption the controller will respond with a setparam command that will set the device's unique authkey as well as other config settings. The second response will provision the device and contain the device's configuration.

Config

This section documents what I've learned about how the UniFi configuration is structured.

Management Config

# TODO: Write about the management configuration.

System Config

# TODO: Write about the system configuration.

Previous works of others