Unifi DHCP Integration for Hostnames?

Hi,

I'm wondering if it would be possible when not using Pi-Hole as DHCP, to integrate hostname lookup & sync via scripts for Unifi environments, like this script does? GitHub - farsonic/unifi-to-hosts-mapping: Log into UniFi controller and retrieve list of all known clients. Use this information to populate the /etc/hosts file with a mapping of IP/Username.

While I have that script working, it's using etc/hosts which I believe isn't best practice.

Thanks,
Shane.

Can you set Pi-hole Conditional Forwarding to use the Unifi as the upstream DNS server for your local domain you use in the aliases?

I've done that. Unfortunately it seems the Unifi UDM I am running doesn't currently share the hostname back to my pi-hole.

What does a dig return for a host name you'd like to show on Pi-hole?

pi@homebridge:~ $ dig 192.168.1.10

; <<>> DiG 9.11.5-P4-5.1-Raspbian <<>> 192.168.1.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 42138
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;192.168.1.10.                  IN      A

;; Query time: 65 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri May 01 14:00:32 AEST 2020
;; MSG SIZE  rcvd: 41
pi@homebridge:~ $ dig +answer -x 192.168.1.10

; <<>> DiG 9.11.5-P4-5.1-Raspbian <<>> +answer -x 192.168.1.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 52691
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

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

;; ANSWER SECTION:
10.1.168.192.in-addr.arpa. 2    IN      PTR     ShanesDesktop.

;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri May 01 14:01:29 AEST 2020
;; MSG SIZE  rcvd: 81

pi@homebridge:~ $ dig @192.168.1.1 192.168.1.10

; <<>> DiG 9.11.5-P4-5.1-Raspbian <<>> @192.168.1.1 192.168.1.10
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42220
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;192.168.1.10.                  IN      A

;; ANSWER SECTION:
192.168.1.10.           0       IN      A       192.168.1.10

;; Query time: 0 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Fri May 01 14:04:30 AEST 2020
;; MSG SIZE  rcvd: 57
pi@homebridge:~ $ dig @192.168.1.1 Shanes-Desktop

; <<>> DiG 9.11.5-P4-5.1-Raspbian <<>> @192.168.1.1 Shanes-Desktop
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 15284
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;Shanes-Desktop.                        IN      A

;; AUTHORITY SECTION:
.                       3600    IN      SOA     a.root-servers.net. nstld.verisign-grs.com. 2020050100 1800 900 604800 86400

;; Query time: 91 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Fri May 01 14:06:22 AEST 2020
;; MSG SIZE  rcvd: 118

This dig command shows that your Pi-hole knows a name for 192.168.1.10. If a similar lookup, forced through your UDM, returns the same, I'd say it works as expected.

Maybe your observation is just confused by mixing up some dig options? (click for more).

Reverse lookup of a hostname for a given IP address through a specific DNS server (e.g. your UDM at 192.168.1.1) requires -x option:

dig @192.168.1.1 -x <host-ip-address> +short

where +short will just give you the names.

Here, you used the right syntax to query Shanes-Desktop, yet a previous command shows DNS to know ShanesDesktop as a name (without a hyphen).


EDIT:
I know Ubiquiti's Edge Router family can be configured to make use of dnsmasq, mitigating update of local DNS records on device. I do not know about their Unifi product line.

Should your adopted dig commands reveal that indeed your UDM isn't returning local host records, you may want to check Ubiquiti 's support.

Hey @shanelord, welcome to the pihole community.

The script you linked above is fairly outdated and might not support newer devices. It doesn't look up hostnames by querying the controller but uses the controller API to get the desired information.

If you want to try out something, I would change the following:

  1. With the upcoming pihole v5.0 one can create Local DNS records via the WEB GUI. The information is saved in /etc/pihole7custom.list. I would modify the script to write to that file instead of /etc/hosts. That has the advantage that you can see (and modify) the entries via WEB GUI also.

  2. The script itself imports a unifi library (that's why you have to run sudo pip install unifi before). That pip is also outdated. But someone forked it and it is actively maintained. You could try to use the new forked version as a backend for the actual script.

Good luck.

Looks good, what the issue is relates to the fully qualified local domain.

The domain you use in Conditional Forwarding needs to be the data entered on the Unifi configuration. So if you have .lan as the Local domain name, then Unifi needs to be set for ShanesDesktop.lan. What is happening now is Pi-hole is asking for the hostname with the Local domain name added and Unifi doesn't know that.

I've adjusted the script to write to the custom.list file, but the default hosts output uses a tab delimeter rather than a space when it writes to the file, and pi-hole doesn't recognise it. If I manually edit the custom.list after import via the script and delete the tab and replace with a space, it shows in the pi-hole 5.0 UI fine.

Any chance the custom.list could treat a tab delimiter as a space and let it work? Or anyone have better python knowledge that can work out how to adjust the client-mapping.py file to copy the hosts as IP-space-Hostname rather than IP-tab-Hostname ?

Dan,

I've got my local domain added from the Unifi config in the conditional forwarding field - I can see my desktop has the primary domain suffix showing correctly under network properties (Windows 10).

Doesn't seem to work though... the client-mapping script is working at the moment with /etc/hosts , although making it work with custom.list would be better!

This all could be an issue with my Unifi UDM - heaven knows it has it's issues right now.

Just wish I could work out how to make the script output from client-mapping.py insert a space between IP and Hostname instead of a TAB so it working in custom.list

Thanks,
Shane.

Do that again and see if the Unifi is correctly returning the FQDN with the local domain added on.

You can write python scripts but that is just vastly over-complicating things, adding in multiple points of failure and fall over.

I've tried - still not working.

In the mean time, I've found how to change the tab to a space by editing the hosts.py file python-hosts/hosts.py at 96bf28fd6917bf6b5deb3f153a61337c4a84b693 · jonhadfield/python-hosts · GitHub used by the client-mapping.py script.

Where it says:

"{0}\t{1}\n".format(

change to':

"{0} {1}\n".format(

Then I use the command:
sudo python /home/pi/client-mapping.py -f /etc/pihole/custom.list -c ControllerIP -u Username -p Password

All shows up in the Custom DNS section fine, and with the crontab updated to run this every 15 minutes if IP addresses change this gets updated dynamically.

Guess this will do for now.

Thanks,
Shane.

Great you figured it out. I was going to suggest these exact same steps - but you were faster :slight_smile:

It would be good if you could open an feature request here on discourse (or even a pull request on github :wink: about allowing pihole to import custom.list seperated with tabs. This might help others in the future.
There has to be only one line added

Add $line = str_replace("\t"," ", $line);

Glad it's working for you. I'm closing the feature request as it appears Unifi responds to dig requests so Conditional Forwarding is the proper approach.

Sorry but while it responds, it doesn’t respond with the local domain correctly so conditional formatting doesn’t work.

It always returns ShanesDesktop.

with nothing after the “.”

I'm sure the folks that handle Unifi would be glad to fix that oversight.

Edit: If you can show us something from Unifi that says the behavior seen is intended and they don't have any plans to change it, then we can talk about patching Pi-hole to fix their broken implementation. As it is now we don't really know if that's what they intend to happen.

No problems. I’ve raised a support ticket and hope they respond.

I’m happy for this to be moved out of feature request and into general if that suits.

If possible though - could ignoring the tab delimiter change as per @yubiuser above be implemented? Then at least the input from the script (or any other possible ones like it in future) could work without changes.

Thanks for all of your help.

Tab changes, probably not. Easier to change the script to output what Pi-hole expects. Think of it like an API, we have our specs and they work, the clients need to implement the agreement correctly.

Ok - I've forked a few repositories and created one that works with Pi-Hole 5.0

Hope this helps others if they have the same issue as me. If not, at least I have it working for my environment :slight_smile:

2 Likes

One thing you could also do in your own fork: leave hosts.py untouched but loop over custom.list after it was written and str_replace all tabs by spaces.