Like countless others, I got fed up with ad’s on the interwebs enough to the point where I installed a Pi-hole to block them at the network level. And it did a brilliant job, I highly recommend setting one up on your own network.
Except there was one minor issue, well more of an annoyance really, all the logging and reporting from Pi-hole only showed IP addresses and not hostnames. Now, I don’t know about you, but I’m not one for memorizing which IP address is being used by each device on my network.
I did some investigating into this problem and it turns out Pi-hole will pull hostnames from the /etc/hosts files. And the easiest way to populate this list is to use the built in DHCP server. So I manually updated my hosts file with the few static IP addresses I have on my network, and they showed up in Pi-holes logs as expected. But I like to be difficult and didn’t want to move my DHCP server from my firewall to the Pi-hole – there had to be another way.
DHCP by it’s nature uses network broadcasts to request and assign IP addresses. This is great because it means any device on the network can see DHCP traffic. The idea here is simple, pick up those DHCP broadcasts, pull out the hostname of the device making the request and the IP address that gets assigned, then use that info to update the hosts file. I’m also using fingerbank to fingerprint the device and append some extra details to the hsotname to make identification a little easier in Pi-hole. So instead of something like 192.168.1.101, you see Galaxy-A50__Samsung_Android.
The Script
You can download the script from my GitHub repository. For those of you new to GitHub, click on the green ‘Clone or Download’ button on the right hand side and you get get a .zip containing the latest code from there. Extract the .zip and copy the contents to your scripts folder on your Pi-hole.
Setup
There are a few things to install before we get started. First there are a couple of python packages we can pull from pip. Run the following commands:
sudo pip3 install pip --upgrade
sudo pip3 install python-hosts
sudo pip3 install urllib3
sudo pip3 install requests
Next you’ll need to install tcpdump:
sudo apt-get install tcpdump
And finally, scapy:
git clone https://github.com/secdev/scapy
cd scapy
sudo python3 setup.py install
Fingerbank
PiHost will query fingerbank to get a profile of devices on the network. This allows us to append useful info to the device name to help identify what we’re looking at in the PiHole console. You’ll need to create a free account with Fingerbank to get your API key.
Once you have your API Key, update the secrets.py file to include your key.
Testing PiHost
Running the following command will launch PiHost in as the currently logged in user. This will allow you to see any output on the terminal. Good for testing, but we’ll setup something more permanent in a minute.
sudo python3 pihost.py
At this point you should see ‘Starting’ on your screen, and not much else. Go ahead and release/renew the IP address of a device connected to your network. A message will now be displayed showing that the device has been detected and added to /etc/hosts. Within a few minutes you should start seeing the hostname for this device showing up in Pi-holes logs.
Launching PiHost at startup
It’s not very practical to have to log in and manually run PiHost all the time, so now we’re going to make it run automatically at startup. There are a number of ways to run something at startup in Linux, but in this case we’ll add the command to the rc.local file. Edit the file /etc/rc.local using the editor of your choice. You must edit it with root permissions:
sudo vi /etc/rc.local
Add the command to launch PiHost at startup. Make sure to use the absolute reference to the file.
sudo python3 /home/pi/pihost.py &
IMPORTANT: Don’t forget the ‘&’ at the end. This will fork the process and allow booting to continue. Without this the system would wait for this process to complete before continuing to boot. Because PiHost keeps looping and never stops sniffing for DHCP packets the boot process would be waiting indefinitely.
To Do
While I’ve found this script to be very reliable in picking up on IPv4 clients, it’s still lacking any support for IPv6 clients – they still won’t show hostnames in Pi-hole. I’d like to extend this script in the near future to match IPv6 addresses to hostnames as well.
Wrapping up
It may take some time for all the devices on your network to go through the DHCP process again and for them to be added to /etc/hosts, but you should start seeing device names appearing in your Pi-hole without too much delay. Don’t forget that you’ll need to manually add devices with static IP addresses to the hosts file as PiHost won’t pick them up.
Hello, I try to execute the following
sudo python3 pihost.py
And send me the next error:
Traceback (most recent call last):
File “pihost.py”, line 171, in
sniff(iface = interface, filter=’udp and (port 67 or 68)’, prn = handle_dhcp _packet, store = 0)
File “/usr/local/lib/python3.7/dist-packages/scapy-2.4.5rc1.dev186-py3.7.egg/s capy/sendrecv.py”, line 1300, in sniff
sniffer._run(*args, **kwargs)
File “/usr/local/lib/python3.7/dist-packages/scapy-2.4.5rc1.dev186-py3.7.egg/s capy/sendrecv.py”, line 1165, in _run
**karg)] = iface
File “/usr/local/lib/python3.7/dist-packages/scapy-2.4.5rc1.dev186-py3.7.egg/s capy/arch/linux.py”, line 497, in __init__
attach_filter(self.ins, filter, self.iface)
File “/usr/local/lib/python3.7/dist-packages/scapy-2.4.5rc1.dev186-py3.7.egg/s capy/arch/linux.py”, line 166, in attach_filter
bp = compile_filter(bpf_filter, iface)
File “/usr/local/lib/python3.7/dist-packages/scapy-2.4.5rc1.dev186-py3.7.egg/s capy/arch/common.py”, line 150, in compile_filter
raise OSError(error)
OSError: b’wlan0: No such device exists (SIOCGIFHWADDR: No such device)’
LikeLike
I fix the problem, I change wlan0 to eth0 in the file pihost.py.
thanks anyway
LikeLike