Skip to content

AxelVTN/unifi-gateway

 
 

Repository files navigation

UniFi Gateway Emulator Build & Release

A Python 3 daemon that emulates a Ubiquiti UniFi Gateway (UGW3) to a UniFi Controller. This allows non-Ubiquiti routers (OpenWRT, OPNSense, pfSense, or any Linux/FreeBSD router) to appear in the UniFi Controller UI and report network statistics.

How It Works

The daemon runs alongside your non-Ubiquiti router and periodically sends "inform" packets to your UniFi Controller — the same binary protocol that real UniFi devices use. The controller sees a UGW3 gateway and displays its stats (interfaces, traffic, connected clients, routes, etc.) in the dashboard.

Your UniFi APs, switches, and other devices continue connecting to the controller normally. This project fills the "gateway" slot so the controller has a complete view of your network topology.

┌──────────────────┐     inform (HTTP POST)     ┌───────────────────┐
│  This Daemon     │ ─────────────────────────► │  UniFi Controller │
│  (emulates UGW3) │                            │                   │
└────────┬─────────┘                            │  Sees complete    │
         │ reads stats from                     │  network topology │
┌────────▼─────────┐                            │                   │
│  Your Router     │     UniFi APs/Switches ──► │                   │
│  (OPNSense/etc)  │     also inform normally   └───────────────────┘
└──────────────────┘

Requirements

  • A running UniFi Controller (self-hosted or Cloud Key)
  • Network access from the daemon to the controller's /inform endpoint

Installation

Debian / Ubuntu (apt)

curl -fsSL https://amd989.github.io/unifi-gateway/setup-apt.sh | sudo bash
sudo apt install unifi-gateway

RHEL / Rocky / Fedora (dnf)

curl -fsSL https://amd989.github.io/unifi-gateway/setup-rpm.sh | sudo bash
sudo dnf install unifi-gateway

OpenWRT

The OpenWRT packages ship pure Python source and depend on python3, python3-psutil, and python3-pycryptodome from the OpenWRT feeds — keeping the package tiny for flash-constrained devices.

# Auto-detects apk (25.12+) or opkg (older)
curl -fsSL https://amd989.github.io/unifi-gateway/setup-openwrt.sh | sh

Then install with whichever package manager your version uses:

# OpenWRT 25.12+ (apk)
apk add unifi-gateway

# OpenWRT pre-25.12 (opkg)
opkg install unifi-gateway

FreeBSD / OPNSense / pfSense (pkg)

curl -fsSL https://amd989.github.io/unifi-gateway/setup-pkg.sh | sudo sh
sudo pkg install unifi-gateway

Docker

docker pull ghcr.io/amd989/unifi-gateway:latest
docker compose up -d

See the Docker section below for details.

Standalone Binaries

Pre-built binaries are also available from Releases if you prefer manual installation.

Platform Binary
Linux x86_64 unifi-gateway-linux-amd64
Linux ARM64 unifi-gateway-linux-arm64
Linux ARMv7 unifi-gateway-linux-armhf
FreeBSD x86_64 unifi-gateway-freebsd-amd64

From Source

pip install -r requirements.txt

Quick Start

1. Install dependencies

pip install -r requirements.txt

2. Configure

Copy the sample config and edit it:

cp conf/unifi-gateway.sample.conf conf/unifi-gateway.conf

Edit conf/unifi-gateway.conf:

[gateway]
# Map UniFi logical ports to your real system interfaces
ports = [ { "ifname": "eth0", "name": "WAN", "type": "wan", "realif": "eth0" }, { "ifname": "eth1", "name": "LAN", "type": "lan", "realif": "br-lan" } ]

# Your LAN-side IP and MAC (how the controller identifies this device)
lan_ip = 192.168.1.1
lan_mac = aa:bb:cc:dd:ee:ff

The realif values must match your actual system interface names (check with ip link on Linux or ifconfig on FreeBSD).

3. Adopt to controller

python unifi_gateway.py set-adopt -s http://your-controller:8080/inform

The first run sends a discovery inform. Go to the UniFi Controller UI, find the new "USG" device, and click Adopt. Then run set-adopt again to complete the handshake:

python unifi_gateway.py set-adopt -s http://your-controller:8080/inform

4. Run

# Foreground (recommended for initial testing)
python unifi_gateway.py run

# Background daemon (Linux only)
python unifi_gateway.py start

# Stop / restart
python unifi_gateway.py stop
python unifi_gateway.py restart

Platform Setup

OpenWRT

The daemon works with OpenWRT's default dnsmasq DHCP server. Typical interface mapping:

ports = [ { "ifname": "eth0", "name": "WAN", "type": "wan", "realif": "eth0" }, { "ifname": "eth1", "name": "LAN", "type": "lan", "realif": "br-lan" } ]

DHCP leases are auto-detected at /tmp/dhcp.leases.

OPNSense (FreeBSD)

The daemon auto-detects FreeBSD and uses arp -an for the neighbor table, netstat -rn for routing. It supports KEA DHCP (OPNSense's default DHCP server) with auto-detection of the lease file at /var/db/kea/kea-leases4.csv.

Typical interface mapping (check your interfaces with ifconfig):

ports = [ { "ifname": "eth0", "name": "WAN", "type": "wan", "realif": "vmx0" }, { "ifname": "eth1", "name": "LAN", "type": "lan", "realif": "vmx1" } ]
dhcp_lease_file = /var/db/kea/kea-leases4.csv
dhcp_lease_format = kea

Recommended setup using a Python virtual environment:

python3 -m venv /opt/unifi-gateway/venv
/opt/unifi-gateway/venv/bin/pip install -r requirements.txt
/opt/unifi-gateway/venv/bin/python unifi_gateway.py set-adopt -s http://your-controller:8080/inform
/opt/unifi-gateway/venv/bin/python unifi_gateway.py run

pfSense (FreeBSD)

Same as OPNSense but uses ISC dhcpd instead of KEA:

dhcp_lease_file = /var/dhcpd/var/db/dhcpd.leases
dhcp_lease_format = isc

Generic Linux (Debian, Ubuntu, etc.)

Works out of the box. Uses /proc/net/dev for multicast counters, /proc/net/route for default gateway, and /etc/resolv.conf for nameservers.

Docker

Build and run

docker build -t unifi-gateway .
docker run -d --name unifi-gateway --network host \
  -v $(pwd)/conf:/app/conf \
  unifi-gateway

Docker Compose

docker compose up -d

For automatic adoption on first start, set the UNIFI_ADOPT_URL environment variable in docker-compose.yml:

environment:
  - UNIFI_ADOPT_URL=http://your-controller:8080/inform

Note: network_mode: host is required so the daemon can read the host's real network interfaces. This only works on Linux — Docker Desktop on Windows/macOS does not support host networking.

Service Management

Packages automatically install and enable the service. After configuring, just start it:

Platform Start Logs
systemd (Debian/Ubuntu/RHEL) sudo systemctl start unifi-gateway journalctl -u unifi-gateway -f
rc.d (FreeBSD/OPNSense) sudo service unifi_gateway start tail -f /var/log/unifi-gateway.log
procd (OpenWRT) /etc/init.d/unifi-gateway start logread -e unifi-gateway

Updates are handled by your package manager: apt upgrade, dnf upgrade, opkg upgrade, apk upgrade, or pkg upgrade.

Configuration Reference

Environment Variables

Variable Default Description
UNIFI_GW_CONFIG conf/unifi-gateway.conf Path to config file
UNIFI_GW_LOG_LEVEL DEBUG Log level (DEBUG, INFO, WARNING, ERROR)
UNIFI_GW_LOG_FILE (stderr) Log to file instead of stderr
UNIFI_ADOPT_URL (none) Controller inform URL for automatic adoption on start
UNIFI_ADOPT_KEY (none) Auth key for auto-adoption (optional, rarely needed)

Config File (conf/unifi-gateway.conf)

[global]

Key Default Description
pid_file unifi-gateway.pid PID file path for daemon mode
disable_broadcast True Disable UDP multicast discovery

[gateway]

Key Default Description
ports (required) JSON list mapping UniFi ports to real interfaces
lan_ip (required) LAN IP address
lan_mac (required) LAN MAC address
firmware 4.4.18.5052168 Reported firmware version
device UGW3 Device model string
device_display UniFi-Gateway-3 Display name
use_aes_gcm False Use AES-GCM encryption (set by controller)
hostname (auto-detected) Override reported hostname
dhcp_lease_file (auto-detected) Path to DHCP lease file
dhcp_lease_format dnsmasq Lease format: dnsmasq, isc, or kea
ping_target ping.ubnt.com Host for latency measurement
speedtest_file ./speedtest.json Path to speedtest results JSON
platform UNIFI-GW Platform string in discovery broadcasts

[provisioned]

Populated automatically by the controller after adoption. Do not edit manually.

Speed Test

The controller can trigger speed tests. Install speedtest-cli for this to work:

pip install speedtest-cli

Results are saved to speedtest.json and reported in the next inform cycle.

Architecture

Module Purpose
unifi_gateway.py Entry point, inform loop, controller response handling, adoption
unifi_protocol.py TNBU binary protocol: AES-CBC/GCM encryption, zlib/snappy compression, JSON payload construction
datacollector.py Cross-platform data collection via psutil (Linux + FreeBSD), with platform-specific fallbacks
tools.py Helper functions for building if_table and network_table structures
tlv.py TLV encoding for UDP discovery packets
daemon.py Unix daemon (double-fork, PID file)

License

MIT — see LICENSE.

Acknowledgments

This project builds upon and was inspired by:

Protocol documentation:

About

UniFi Gateway emulator for third-party routers

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Python 78.1%
  • Java 10.5%
  • Shell 8.6%
  • HTML 2.6%
  • Dockerfile 0.2%