Just to be sure, this?
@DL6ER Can there be a pihole
shortcut for this? It seems to be a very helpful thing.
@deHakkelaar Why the -e eth0
setting? What happens if you omit this and a machine has multiple active interfaces?
Just to be sure, this?
@DL6ER Can there be a pihole
shortcut for this? It seems to be a very helpful thing.
@deHakkelaar Why the -e eth0
setting? What happens if you omit this and a machine has multiple active interfaces?
There could be. However, nmap
is not a dependency of Pi-hole and I wouldn't want to add it for the very few cases where this may be used. It would make more sense to write a cheat-sheet or something similar and put it on there.
I noticed by doing a tcpdump
, if I omit the interface argument -e eth0
, nmap
will broadcast a DHCPDISCOVER
on one (connected) interface only and not both.
Most of the times, being specifyk is a good thing
I agree with @DL6ER.
Another dependencie with its own dependencies.
Another snag I noticed, the broadcast-dhcp-discover
script doesnt report anything with nmap
version =< 7.40 (Debian Stretch for example).
I tested this by installing the nmap
v7.70 Buster version on a Pi of mine running Stretch.
EDIT: If below could be ported magically somehow
Would be nice addition to the debugger.
Could be done, but where will we find the time?...
You may have to run that a few times in short succession, or from two consoles on the same machine at the same time: That broadcast-dhcp-discover script is a bit unreliable, as it just returns the very first DHCP answer it receives.
And if I read the code from that GitHub link correctly, then that fix addresses multiple interfaces, but still processes only the first answer received via each interface.
On Raspberry Pi OS/Debian systems, sudo dhcpcd -T
will yield similar results without having to install nmap
- unfortunately in the same arbitrary first answer accepted fashion.
Yeah the "Response 1 of 1:" line threw me off thinking it will list all responses ... assumptions again
My Debian laptop is running NetworkManager
and not dhcpcd5
.
And I believe that one doesnt broadcast anything if you configured a static IP & DNS like in case of Pi-hole:
pi@ph5:~ $ man dhcpcd
[..]
-T, --test
On receipt of DHCP messages just call
/lib/dhcpcd/dhcpcd-run-hooks with the reason of TEST
which echos the DHCP variables found in the message to
the console. The interface configuration isn't touched
and neither are any configuration files. The
rapid_commit option is not sent in TEST mode so that the
server does not lease an address. To test INFORM the in‐
terface needs to be configured with the desired address
before starting dhcpcd.
I flipped on all three DHCP services that I have available, my router and two (wired) Pi-hole instances to run some tests.
My client laptop connected through WiFi only reported my PH v5 node @10.0.0.4
:
dehakkelaar@laptop:~$ sudo nmap -e wlan0 --script broadcast-dhcp-discover
[..]
| Server Identifier: 10.0.0.4
Above is consistent on another wired client:
xbian@avr ~ $ sudo nmap -e eth0 --script broadcast-dhcp-discover
[..]
| Server Identifier: 10.0.0.4
My PH v5 host reports only itself:
pi@ph5:~ $ sudo nmap -e eth0 --script broadcast-dhcp-discover
[..]
| Server Identifier: 10.0.0.4
And my PH v4 host wont report a thing bc its still on nmap v7.40.
Reluctant to install nmap v7.70 bc I have to stir up libc.so.6
version dependency which I wont do on this live system.
So the broadcast-dhcp-discover
script is not that reliable to investigate DHCP servers active on the network.
As alternative, you could do a:
dehakkelaar@laptop:~$ sudo nmap -sU -p67 --open 10.0.0.0/24
Starting Nmap 7.70 ( https://nmap.org ) at 2020-09-04 02:40 CEST
Nmap scan report for 10.0.0.1
Host is up (0.00089s latency).
PORT STATE SERVICE
67/udp open|filtered dhcps
MAC Address: 50:46:5D:xx:xx:xx (Asustek Computer)
Nmap scan report for noads.dehakkelaar.nl (10.0.0.2)
Host is up (0.0015s latency).
PORT STATE SERVICE
67/udp open|filtered dhcps
MAC Address: B8:27:EB:xx:xx:xx (Raspberry Pi Foundation)
Nmap scan report for ph5.dehakkelaar.nl (10.0.0.4)
Host is up (0.0025s latency).
PORT STATE SERVICE
67/udp open|filtered dhcps
MAC Address: B8:27:EB:xx:xx:xx (Raspberry Pi Foundation)
Nmap done: 256 IP addresses (8 hosts up) scanned in 5.13 seconds
And instead of doing a broadcast, do a unicast dhcp-discover
on the IP's:
dehakkelaar@laptop:~$ sudo nmap -sU -p67 --script dhcp-discover 10.0.0.2
Starting Nmap 7.70 ( https://nmap.org ) at 2020-09-04 02:36 CEST
Nmap scan report for noads.dehakkelaar.nl (10.0.0.2)
Host is up (0.0011s latency).
PORT STATE SERVICE
67/udp open dhcps
| dhcp-discover:
| DHCP Message Type: DHCPACK
| Server Identifier: 10.0.0.2
| IP Address Lease Time: 23h42m03s
| Subnet Mask: 255.255.255.0
| Broadcast Address: 10.0.0.255
| Domain Name Server: 10.0.0.2
| Domain Name: dehakkelaar.nl
|_ Router: 10.0.0.1
MAC Address: B8:27:EB:xx:xx:xx (Raspberry Pi Foundation)
Nmap done: 1 IP address (1 host up) scanned in 0.95 seconds
If want to be sure what DHCP response gets in first on a client, you'd have to run nmap
with broadcast-dhcp-discover
on that client.
But it still does show other useful data like DNS servers, gateway etc advertised via DHCP.
This almost convinced me that this is a valuable thing to add to the debugger, however, I found some strange results in my own local network. Maybe you have suggestions on how to improve the automated scanning.
Step: Get address ranges of all interfaces
(for simplicity, I only the devices attached to eth2
which represents my local home network)
$ ip a
[...]
3: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether X brd ff:ff:ff:ff:ff:ff
inet 192.168.2.223/24 brd 192.168.2.255 scope global dynamic noprefixroute eth2
valid_lft 81690sec preferred_lft 81690sec
[...]
Step: Scan UDP ports 67 on this network:
$ sudo nmap -sU -p67 --open 192.168.2.223/24
Starting Nmap 7.60 ( https://nmap.org ) at 2020-09-04 09:47 CEST
Nmap scan report for pi.hole (192.168.2.10)
Host is up (0.00037s latency).
PORT STATE SERVICE
67/udp open|filtered dhcps
MAC Address: X (Hewlett Packard)
Nmap scan report for webradio.lan (192.168.2.239)
Host is up (0.15s latency).
PORT STATE SERVICE
67/udp open|filtered dhcps
MAC Address: X (Frontier Silicon)
Nmap scan report for android.lan (192.168.2.244)
Host is up (0.25s latency).
PORT STATE SERVICE
67/udp open|filtered dhcps
MAC Address: X (Unknown)
Nmap done: 256 IP addresses (6 hosts up) scanned in 8.05 seconds
This result is a bit unexpected: Obviously, only the pi.hole
host actually hosts a DHCP server, the others are likely just dropping all incoming connections. Something to watch out for in the following
Step: Scan each of the reported hosts using the dhcp-discover
script:
$ sudo nmap -sU -p67 --script dhcp-discover 192.168.2.10
Starting Nmap 7.60 ( https://nmap.org ) at 2020-09-04 09:56 CEST
Nmap scan report for pi.hole (192.168.2.10)
Host is up (0.00029s latency).
PORT STATE SERVICE
67/udp open dhcps
| dhcp-discover:
| DHCP Message Type: DHCPACK
| Server Identifier: 192.168.2.10
| IP Address Lease Time: 22h31m50s
| Subnet Mask: 255.255.255.0
| Broadcast Address: 192.168.2.255
| Domain Name Server: 192.168.2.10
| Domain Name: lan
|_ Router: 192.168.2.1
MAC Address: X (Hewlett Packard)
Nmap done: 1 IP address (1 host up) scanned in 0.76 seconds
So this worked, great.
$ sudo nmap -sU -p67 --script dhcp-discover 192.168.2.239
Starting Nmap 7.60 ( https://nmap.org ) at 2020-09-04 09:56 CEST
Nmap scan report for Internet-Radio.lan (192.168.2.239)
Host is up (0.088s latency).
PORT STATE SERVICE
67/udp open|filtered dhcps
MAC Address: X (Frontier Silicon)
Nmap done: 1 IP address (1 host up) scanned in 6.40 seconds
False positive, acknowledged.
$ sudo nmap -sU -p67 --script dhcp-discover 192.168.2.244
Starting Nmap 7.60 ( https://nmap.org ) at 2020-09-04 09:57 CEST
Nmap scan report for dominik-android.lan (192.168.2.244)
Host is up (0.085s latency).
PORT STATE SERVICE
67/udp closed dhcps
MAC Address: X (Unknown)
Nmap done: 1 IP address (1 host up) scanned in 0.94 seconds
False positive, acknowledged.
So the idea is now to run step 1, extract all possible subnets (most of the time there will be only one, but you never know for sure). Then run steps 2 for all extracted subnets and step 3 for all extracted subnets * detected devices (may contain a lot of false-positives).
As much as I like the idea of adding this to the debugger, the entire process took quite some time (roughly 10 seconds even if scripted) with only one scanned interface due to the false positives may taking a long time to respond. So I'd rather favor what I dismissed above, to really add a pihole scandhcp
(or similar) so it can be done easily on request of a user.
I see that the nmap
scripting engine (NSE) is written in Lua
(pinging @DanSchaper just for awareness), so it may be worthwhile to explore a variant of implementing all the three points I mentioned above directly in the script to avoid complex bash
scripting around them.
In the end it turned out to be easier - and more reliable if you want to receive multiple offers - to implement this completely ourselves. No added dependencies anywhere.
Example:
$ sudo pihole-FTL dhcp-discover
Sending DHCPDISCOVER on interface lo ...
Nobody replied to our request on this interface
Sending DHCPDISCOVER on interface eth1 ...
Nobody replied to our request on this interface
Sending DHCPDISCOVER on interface eth2 ...
Received 300 bytes from 192.168.2.10
Offered IP address: 192.168.2.223
Server IP address: 192.168.2.10
Relay-agent IP address: N/A
DHCP options:
Message type: DHCPOFFER
Server identification: 192.168.2.10
Lease time: 86400 (1d 0h 0m 0s)
Renewal time: 43200 (12h 0m 0s)
Rebindung time: 75600 (21h 0m 0s)
Subnet mask: 255.255.255.0
Broadcast address: 192.168.2.255
DNS server 1: 192.168.2.10
Domain name: "lan"
Router 1: 192.168.2.1
--- end of options ---
Sending DHCPDISCOVER on interface lxcbr0
Received 300 bytes from 10.0.3.1
Offered IP address: 10.0.3.16
Server IP address: 10.0.3.1
Relay-agent IP address: N/A
DHCP options:
Message type: DHCPOFFER
Server identification: 10.0.3.1
Lease time: 3600 (1h 0m 0s)
Renewal time: 1800 (30m 0s)
Rebindung time: 3150 (52m 30s)
Subnet mask: 255.255.255.0
Broadcast address: 10.0.3.255
Router 1: 10.0.3.1
DNS server 1: 10.0.3.1
--- end of options ---
The timeout until we wait for offers is currently hard-coded to two seconds.
Please try it yourself!
I am, as always, very interested in your opinion and suggestions for further improvements:
pihole checkout ftl new/dhcp-discover
This. Is. Awesome. Absolutely crazy!!!
You guys rock. You just wrote over 650 lines of complex C code in just two hours! F.U.C.K.!
Its MAD crazy how quick
I had partial success while trying out below outdated PHP5 code:
I got it sort of to send but in the end, too many things had to be ported to PHP7
This is truly amazing
Thanx allot!
EDIT:
pi@noads:~ $ tail -f /var/log/pihole.log | grep dnsmasq-dhcp
Sep 4 13:30:13 dnsmasq-dhcp[7056]: DHCPDISCOVER(eth0) b8:27:eb:xx:xx:xx
Sep 4 13:30:13 dnsmasq-dhcp[7056]: DHCPOFFER(eth0) 10.0.0.109 b8:27:eb:xx:xx:xx
EDIT2: @DL6ER , can you send a DHCPINFORM
as well instead of a DHCPDISCOVER
?
Some feedback,
I noticed if I flip on all three DHCP servers again, its same old race condition again who is quickest responding (not the own host at 10.0.0.4
it seems):
pi@ph5:~ $ pihole-FTL dhcp-discover
Sending DHCPDISCOVER on interface lo ...
Nobody replied to our request on this interface
Sending DHCPDISCOVER on interface eth0 ...
Received 303 bytes from 10.0.0.2
Offered IP address: 10.0.0.109
Server IP address: 10.0.0.2
Relay-agent IP address: N/A
DHCP options:
Message type: DHCPOFFER
Server identification: 10.0.0.2
Lease time: 86400 (1d 0h 0m 0s)
Renewal time: 43200 (12h 0m 0s)
Rebindung time: 75600 (21h 0m 0s)
Subnet mask: 255.255.255.0
Broadcast address: 10.0.0.255
DNS server 1: 10.0.0.2
Domain name: "dehakkelaar.nl"
Router 1: 10.0.0.1
--- end of options ---
And when supply IP argument, I get to see two of three active DHCP servers:
pi@ph5:~ $ pihole-FTL dhcp-discover 10.0.0.1
Sending DHCPDISCOVER on interface lo ...
Nobody replied to our request on this interface
Sending DHCPDISCOVER on interface eth0 ...
Received 312 bytes from 10.0.0.1
Offered IP address: 10.0.0.110
Server IP address: 10.0.0.1
Relay-agent IP address: N/A
DHCP options:
Message type: DHCPOFFER
Server identification: 10.0.0.1
Lease time: 86400 (1d 0h 0m 0s)
Renewal time: 43200 (12h 0m 0s)
Rebindung time: 75600 (21h 0m 0s)
Subnet mask: 255.255.255.0
Broadcast address: 10.0.0.255
DNS server 1: 10.0.0.1
Unknown option 252 with length 1
Unknown option 44 with length 4
Domain name: "dehakkelaar.nl"
Router 1: 10.0.0.1
--- end of options ---
Received 303 bytes from 10.0.0.2
Offered IP address: 10.0.0.109
Server IP address: 10.0.0.2
Relay-agent IP address: N/A
DHCP options:
Message type: DHCPOFFER
Server identification: 10.0.0.2
Lease time: 86400 (1d 0h 0m 0s)
Renewal time: 43200 (12h 0m 0s)
Rebindung time: 75600 (21h 0m 0s)
Subnet mask: 255.255.255.0
Broadcast address: 10.0.0.255
DNS server 1: 10.0.0.2
Domain name: "dehakkelaar.nl"
Router 1: 10.0.0.1
--- end of options ---
And trying to discovering the own host @10.0.0.4
, I get to see reply from my other Pi again @10.0.0.2
:
pi@ph5:~ $ pihole-FTL dhcp-discover 10.0.0.4
Sending DHCPDISCOVER on interface lo ...
Nobody replied to our request on this interface
Sending DHCPDISCOVER on interface eth0 ...
Received 303 bytes from 10.0.0.2
Offered IP address: 10.0.0.109
Server IP address: 10.0.0.2
Relay-agent IP address: N/A
DHCP options:
Message type: DHCPOFFER
Server identification: 10.0.0.2
Lease time: 86400 (1d 0h 0m 0s)
Renewal time: 43200 (12h 0m 0s)
Rebindung time: 75600 (21h 0m 0s)
Subnet mask: 255.255.255.0
Broadcast address: 10.0.0.255
DNS server 1: 10.0.0.2
Domain name: "dehakkelaar.nl"
Router 1: 10.0.0.1
--- end of options ---
EDIT:
Rebindung lost in translation
There are no arguments for this command... So we got different results for one and the same test. We pick up all valid packets that arrive at the interface. I'll have to set up a few DHCP servers when back home Monday.
Not sure if this is really a race collision on the wire (we can't do anything about this, then) or if we maybe just have to extend the timeout from two seconds to something larger.
Not sure what you want, "as well" or "instead of"? As well wouldn't make much/any difference. "Instead" seems wrong, isn't the DHCPINFORM
meant to be send to specific addresses instead of the broadcast.
The most recent DHCPv4 Standard [RFC2131] added a new DHCPv4 message: DHCPINFORM. The intent of the DHCPINFORM message was for clients that used manually entered fixed IPv4 addresses to still be able to get some configuration state dynamically.
We likely also want to see if a client would obtain a proper address from the server.
Yeah I meant instead of.
About DHCPINFORM
:
DHCPInform Message
DHCPInform is a new DHCP message type, defined in RFC 2131. DHCPInform is used by DHCP clients to obtain DHCP options.
And I notice just now its doing broadcast and not unicast so no IP arguments:
EDIT:
Your right:
DHCPINFORM - Client to server, asking only for local configuration
parameters; client already has externally configured
network address.
Yeah maybe extend the timeout a little bit.
When have all three active, sometimes I get report from only one DHCP server and sometimes two but never the own host.
I recon that comes with broadcasting not to your own IP.
Yes, that's also why you would not get an IP address from your own host. I can see some value in testing if the interface hosts an DHCP server on the device itself.
This adds more and more tests and with an increased timeout this may become unhandy. I will experiment with parallelizing all the requests. Should be possible, may only a bit harder to implement. When we can do everything at once we can easily test the local host as well plus grant ourselves a comfortable timeout of maybe even up to 10 seconds.
The scan is now fully-multithreaded and the global timeout is 10 seconds. I have a lack of local DHCP servers in my hotel WiFi, however, I set up a local dnsmasq
on my laptop and the scan picked up both the AP's DHCP server as well as my new local one. I've seen that the local dnsmasq
DHCP often (but not always!) needs a few seconds until it replies.
@deHakkelaar This may explain why you've seen sometimes one, sometimes more DHCP servers. Please try again.
I've also found that my local dnsmasq
very well responds to broadcast messages, so no need to send to the interface's local address in my case:
dnsmasq-dhcp: DHCPDISCOVER(wlp4s0) xx:xx:xx:xx:xx:xx
dnsmasq-dhcp: DHCPOFFER(wlp4s0) 192.168.3.191 xx:xx:xx:xx:xx:xx
dnsmasq-dhcp: no address range available for DHCP request via lo
dnsmasq-dhcp: DHCP packet received on enp0s25 which has no address
You can see here that dnsmasq
received requests on all three interfaces my laptop has (we also try to discover on unconfigured interfaces!). However, it is not configured to serve addresses in the 127.0.0.1/8
range, and there is no cable in enp0s25
so this interface is completely down. Everything seems 100% correct here.
edit:
I also added these for you. I picked what my DHCP servers do, so far, because I didn't feel like adding all the 200+ possible options which may never be seen in the wild.
This is really a very useful tool.
Yeah I noticed with time nmap
with unicast, mine all need about 3.5 seconds to respond.
A very sleek feature especially bc the own host gets reported as well which nmap
doesnt do when broadcasting.
Troubleshooting DHCP has gotten allot easier.
Amazing job !
pi@ph5:~ $ pihole-FTL dhcp-discover
Scanning all your interfaces for DHCP servers
Timeout: 10 seconds
* Received 303 bytes from eth0:10.0.0.4
Offered IP address: 10.0.0.195
Server IP address: 10.0.0.4
Relay-agent IP address: N/A
DHCP options:
Message type: DHCPOFFER
Server identification: 10.0.0.4
Lease time:1d (86400 seconds)
Renewal time:12h (43200 seconds)
Rebinding time:21h (75600 seconds)
Subnet mask: 255.255.255.0
Broadcast address: 10.0.0.255
DNS server 1: 10.0.0.4
Domain name: "dehakkelaar.nl"
Router 1: 10.0.0.1
--- end of options ---
* Received 303 bytes from eth0:10.0.0.2
Offered IP address: 10.0.0.109
Server IP address: 10.0.0.2
Relay-agent IP address: N/A
DHCP options:
Message type: DHCPOFFER
Server identification: 10.0.0.2
Lease time:1d (86400 seconds)
Renewal time:12h (43200 seconds)
Rebinding time:21h (75600 seconds)
Subnet mask: 255.255.255.0
Broadcast address: 10.0.0.255
DNS server 1: 10.0.0.2
Domain name: "dehakkelaar.nl"
Router 1: 10.0.0.1
--- end of options ---
* Received 312 bytes from eth0:10.0.0.1
Offered IP address: 10.0.0.109
Server IP address: 10.0.0.1
Relay-agent IP address: N/A
DHCP options:
Message type: DHCPOFFER
Server identification: 10.0.0.1
Lease time:1d (86400 seconds)
Renewal time:12h (43200 seconds)
Rebinding time:21h (75600 seconds)
Subnet mask: 255.255.255.0
Broadcast address: 10.0.0.255
DNS server 1: 10.0.0.1
WPAD server: "
"
NetBIOS name server 1: 10.0.0.1
Domain name: "dehakkelaar.nl"
Router 1: 10.0.0.1
--- end of options ---
Ps. those 44 & 252 options are coming from the Asus router which I dont use ... who needs NETBIOS
EDIT: maybe reporting the IP three times is a bit redundant:
* Received 303 bytes from eth0:10.0.0.2
Server IP address: 10.0.0.2
Server identification: 10.0.0.2
Maybe drop the second line ?
This is not very nice, so it presents a simlpe newline as path to the WPAD server. I fixed it.
These lines are the same in your own setup.
They are, in fact, three entirely different items:
Received 303 bytes from eth0:10.0.0.2
<--- the address of the sender of the packetServer IP address: 10.0.0.2
<--- the address stored in the field siaddr
Server identification: 10.0.0.2
<--- this address is the argument of DHCP option 54There are many possible scenarios where they may be different, like when you serve a network through a proxy server or use any other kind of NAT-server. We should keep as much information as we have.
This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.