The problem

UniFi offers a robust and reliable range of networking equipment. In my homelab, I’ve been running their gateway, controller, switches, and access points for an extended period, and they’ve consistently delivered solid performance and ease of management.

Image Description

However, after replacing my old pfSense box with the UniFi Gateway Max (UXG-MAX), I encountered some unexpected issues. The device initially struggled to adapt to my local setup, and oddly enough, those issues were only resolved after first linking it to a UniFi Cloud Controller, and then migrating it to my Cloud Key Gen2 Plus (UCK-G2-PLUS). Despite the migration, one quirk remained: the so-called “convenience” URL setup.ui.com, which is used during the initial setup of the gateway never deactivated itself. As a result, reverse DNS lookups for the gateway’s IP consistently returned that URL, which was not the intended behavior.

Image Description

It got to a point where I decided that it was time to fix it, but how?

Understanding why

According to my support inquiry with UniFi Support, the setup.ui.com URL is assigned when a device is in its initial adoption state or has been factory reset. This web interface is designed to simplify the adoption process, particularly for users without a dedicated controller.

Once a device has been successfully adopted, it is expected to update its reverse DNS (PTR) record to reflect the device’s assigned name rather than the default setup.ui.com.

To make it even worse, the setup.ui.com URL has a self-signed certificates and gives the error: NET::ERR_CERT_AUTHORITY_INVALID.

Image Description

The error NET::ERR_CERT_AUTHORITY_INVALID in Google Chrome means that the browser does not trust the certificate authority (CA) that issued the website’s SSL/TLS certificate. This typically happens with self-signed certificates or certificates issued by a private/internal CA.

You can however access the site if you use the IP of the gateway, but it only tells us what we already know and does not fix the issue.

Image Description

In my case, due to adoption issues that occurred over a year ago, this process didn’t complete properly. As a result, every time a change was made via the UniFi Network Console, a new configuration was pushed to the gateway and unfortunately, it continued to reintroduce the setup.ui.com entry in the configuration.

 {
    "hostName": "setup.ui.com",
     "registerNonQualified": false,
     "address": {
	   "address": "192.168.0.1",
	   "version": "v4"
    }
},

Device deepdive to find potential fix

Since the device runs a variety of open-source software packages on a Linux-based system, it was time to dig a bit deeper and see if there was a way to work around the issue.

The first step was to gain a better understanding of the software pipeline and how the various components are interconnected.

Device Firmware versions

UCK-G2-PLUS

  • Network 9.1.120
  • UniFi OS 4.2.12

UXG-MAX

  • 4.1.13 FW

UDAPI

UDAPI is a framework used for processing Universal Dependencies data, and in the UniFi system, it aggregates all controller-provided configuration into a JSON file located at /data/udapi-config/udapi-net-cfg.json.

This file contains the complete configuration that the device relies on to initialize and manage its software components. Notably, the configuration snippet responsible for the setup.ui.com entry.

 {
    "hostName": "setup.ui.com",
     "registerNonQualified": false,
     "address": {
	   "address": "192.168.0.1",
	   "version": "v4"
    }
},

UDAPI is responsible for launching the necessary services, passing the appropriate runtime arguments, and generating dynamic configuration files within the /run directory for each component. All based on the contents of the JSON configuration.

Image Description As you can see in this image the /usr/bin/ubios-udapi-server process has a lot of sub processes to other applications due to this.

DNSMASQ

One of the key open-source components involved is DNSMASQ, which is responsible for handling reverse DNS (PTR) lookups. The very behavior we’re trying to correct.

dnsmasq is a lightweight, easy-to-configure DNS forwarder and DHCP server used widely in embedded systems, routers (e.g., OpenWRT), and local networks.

As we can see in the process tree its running with the following parameters:

/usr/sbin/dnsmasq --conf-dir=/run/dnsmasq.conf.d/ --pid-file=/run/dnsmasq.pid --resolv-file=/etc/resolv.dnsmasq

As we’ve already established, the /run/dnsmasq.conf.d/ directory is dynamically generated each time a new configuration is deployed via UDAPI. This means any manual changes made there are overwritten on the next update, and since DNSMASQ relies on those files, modifying them directly isn’t a viable long-term solution especially without a reliable way to trigger a reload.

That leaves us with the /etc/resolv.dnsmasq file as a potential workaround, since it directly relates to the DNS resolution process we’re aiming to correct.

# Generated automatically by ubios-udapi-server
search bb.online.no 

# dynamic nameservers
# eth3
# disabled 192.168.3.1
# tunovpnc1
# disabled 10.0.0.243
# static nameservers
# eth4
nameserver 1.1.1.1
nameserver 8.8.8.8

Sadly its only contains the forwarding DNS servers and that is also configurable in the controller.

String searching in files

By this point, it was late at night, and my CTF instincts kicked in. I decided to search the system for any files containing setup.ui.com to uncover more clues about the software components involved and gain deeper insight into the issue.

root@UXGMax:~# grep -rnw '/run' -e 'setup.ui.com'
/run/dns.conf.d/dnsmasq-tunovpnc1.conf:18:host-record=setup.ui.com,192.168.0.1
/run/dns.conf.d/dnsmasq-eth3.conf:18:host-record=setup.ui.com,192.168.0.1
/run/dns.conf.d/dnsmasq-eth4.conf:18:host-record=setup.ui.com,192.168.0.1
/run/dnsmasq.conf.d/dns.conf:17:host-record=setup.ui.com,192.168.0.1

We know the files in /run was generated by UDAPIso they could not be altered and would not persist.

After some time i found the default configuration files for UDAPI used by UniFi in the following location:

/usr/share/ubios-udapi-server/uxg-a690.default 
/usr/share/ubios-udapi-server/uxg-a690.fallback

One is the first default deployment and the other one is a fallback if a configuration deploy broke.

root@UXGMax:~# grep -A 7 -B 2 "setup.ui.com" /usr/share/ubios-udapi-server/uxg-a690.default
"hostRecords": [
	{
		"hostName": "setup.ui.com",
		"address": {
			"address": "192.168.1.1",
			"version": "v4"
		},
		"registerNonQualified": false,
		"ttl": 60
	},

Sadly after editing this files, restarting the device and clearing my DNS cache it did not help and the rDNS (PTR) still responded with setup.ui.com.

The fix is always right in front of you

While investigating where dnsmasq stores its reverse DNS records, I realized an important detail: by default, DNSMASQ does not store reverse DNS entries persistently. Instead, it dynamically serves PTR lookups based on three distinct sources.

DHCP Leases File

When DNSMASQ is used as a DHCP server, it can dynamically provide reverse DNS based on the current leases.

/var/lib/misc/dnsmasq.leases

This file contains current leases, and DNSMASQ uses it to provide forward and reverse DNS entries for clients.

Static DHCP Configuration

In your dnsmasq.conf or included config files (e.g., /etc/dnsmasq.d/*.conf), you might have entries like:

dhcp-host=aa:bb:cc:dd:ee:ff,set:device1,192.168.1.50,mydevice

This creates a static lease and allows reverse resolution of 192.168.1.50 to mydevice.

/etc/hosts

If you add entries like:

192.168.1.10 myhost.lan

Then DNSMASQ will serve a DNS and most importantly in our case, reverse DNS (PTR) entry for 192.168.1.10 to myhost.lan.

Solution

One thing I’ve learned over the years especially through countless CTF challenges is that processes like these often resolve certain values before any configuration files or runtime arguments are even considered.

That got me thinking: could it really be as simple as adding a line like 192.168.0.1 UGXMax.bendiksens.net to /etc/hosts and effectively hijacking the .arpa resolution before the system processes the dynamic configuration?

Let’s try it out.

root@UXGMax:~# cat /etc/hosts
127.0.0.1       localhost
127.0.1.1       UXGMax  # local hostname added automatically by ubios-udapi-server
192.168.0.1 UXGMax.bendiksens.net
# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

After rebooting the device, I was pleasantly surprised to see that the entry I added to /etc/hosts persisted. Encouraged by this, I began testing the behavior on my desktop by first flushing the DNS cache, then running a series of tests using dig, tracepath, and reviewing the route table to confirm.

duux@DorrisV2:~$ resolvectl flush-caches

duux@DorrisV2:~$ dig -x 192.168.0.1

; <<>> DiG 9.18.30-0ubuntu0.24.04.2-Ubuntu <<>> -x 192.168.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3332
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;1.0.168.192.in-addr.arpa.      IN      PTR

;; ANSWER SECTION:
1.0.168.192.in-addr.arpa. 1     IN      PTR     UXGMax.bendiksens.net.

;; Query time: 2 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Thu Jun 05 01:47:29 CEST 2025
;; MSG SIZE  rcvd: 88

duux@DorrisV2:~$ tracepath vg.no
 1?: [LOCALHOST]                      pmtu 1500
 1:  UXGMax.bendiksens.net                                 0.564ms 
 1:  UXGMax.bendiksens.net                                 0.572ms 
 2:  ti0182a400-gw.ti.telenor.net                          1.832ms 
 3:  no reply
 4:  ti0300b315-ae1-0.ti.telenor.net                       1.894ms 
^C

duux@DorrisV2:~$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         UXGMax.bendikse 0.0.0.0         UG    100    0        0 enp5s0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.0.0     0.0.0.0         255.255.254.0   U     100    0        0 enp5s0

HOLY SHIT! IT WORKED!

And it even seems to persist over changes in controller and reboots.

However, the config file that UDAPI uses, still is been populated with the entry on changes.

 {
    "hostName": "setup.ui.com",
     "registerNonQualified": false,
     "address": {
	   "address": "192.168.0.1",
	   "version": "v4"
    }
},

Lucky the workaround going in before it is applied.

Follow-up with Support

As of writing this my support case is still ongoing.

I’m going to loop in one of our product experts to ensure this can be addressed as quickly and satisfactorily as possible. They will reach out once they’ve had the opportunity to sufficiently review.

I’ve shared my workaround with them and asked for confirmation on whether it’s an acceptable and supported solution.

Please escalate it as planned. I’d like to ensure that the proposed workaround is viable as a long-term solution.

Will update once I get a response from them.

UPDATE 2025-06-06

I would like to mention that the problem you are facing is unusual and unexpected.

I found similar posts on the web of people having the same issue. It’s strange that they don’t know about this issue as it seems to be some what small, but common issue ranging from 9 years back to so early as few months.

https://www.reddit.com/r/Ubiquiti/comments/1k412gc/why_is_the_gateway_named_setupuicom/ https://community.ui.com/questions/How-to-remove-setup-ubnt-com-on-USG-Pro

New logs have been sent to support.