in network tab, decode and id "Private MAC" addresses
What does this PR aim to accomplish?:
In RFC7042 section 2.1 specifies the “Local bit”: The Local bit is zero for globally unique EUI-48 identifiers assigned by the owner of an OUI or owner of a longer prefix. If the Local bit is a one, the identifier has been considered by IEEE 802 to be a local identifier under the control of the local network administrator...
Both iOS and Android use this as part of their randomized anti-tracking mechanisms. So, display it to admins, so they can tell what device is their phone.
How does this PR accomplish the above?:
If there is no decoded manufacture, check the private bit, and then print "Private MAC"
By submitting this pull request, I confirm the following:
- I have read and understood the contributors guide, as well as this entire template. I understand which branch to base my commits and Pull Requests against.
- I have commented my proposed changes within the code and I have tested my changes.
- I am willing to help maintain this change if there are issues with it later.
- It is compatible with the EUPL 1.2 license
- I have squashed any insignificant commits. (
git rebase) - I have checked that another pull request for this purpose does not exist.
- I have considered, and confirmed that this submission will be valuable to others.
- I accept that this submission may not be used, and the pull request closed at the will of the maintainer.
- I give this submission freely, and claim no ownership to its content.
- [x] I have read the above and my PR is ready for review. Check this box to confirm
I'm not sure what your goal here is.
so they can tell what device is their phone
You should have other means to figure out what you phone is, I guess.
I'm not sure what your goal here is.
Goal is the same - to tell what device is what in the network tab - right now, I see things like:
48:f8:b3:xx:xx:xx Cisco-Linksys, LLC
98:90:96:xx:xx:xx Dell Inc.
which is great. But on a device which is using a private MAC address - make sure the user knows that the blank is on purpose, not a failure of the lookup mechanism.
detect and display a “Private MAC” label for locally-administered MAC addresses.
I don't think "Private MAC" is a good description. I think most users will ask "what does it mean Private MAC?" or similar questions.
If the intention is to make clear that blank/empty is on purpose, we should use "N/A", or "(not available)", or simply leave it empty.
I've never really thought about this before. All of my docker containers are given real addresses on my network using macvlan
In this case, I don't know if the word's "Private MAC" would help me very much and agree with RD that we should go with "N/A" or something similar....
But then that also raises the question... "What does N/A mean, in this case?"
I don't want to be entirely dismissive of the idea, I agree there is some room for improvement as to how the information is displayed.
But then that also raises the question... "What does N/A mean, in this case?"
I think we can try "No vendor info available", but I'm not sure if this is necessary.
Another possibility is to leave the table as it is, but add a note on the page bottom (above the colors legend). Something like:
There are a few different use cases:
- Vendor lookup success (MAC found in the database)
- things display as they do today.
- Vendor lookup failure (MAC not found in the database). This happens when:
- The MAC is legitimate
- But the OUI prefix isn’t in the vendor database
- Or the database is outdated
- Locally administered / randomized MAC address (U/L bit set). This happens when:
- iOS / Android / Windows uses a randomized MAC
- The U/L bit (0x02) in the first octet indicates “locally administered”
- These cannot have vendor info because no OUI was assigned
The goal was to disambiguate 2 and 3 (since they are very different).
I agree - maybe "Private MAC" isn't the most searchable term. Wikipedia and the RFC suggests "Locally administered" - that's likely the best term (as it shows up in the most searches)...
All of my docker containers are given real addresses on my network using macvlan
technically - all EUI-48 identifiers all "real" - I'm just trying to tease apart:
- universally administered addresses (UAA), which is uniquely assigned to a device by its manufacturer.
- locally administered addresses (LAA), which is assigned to a device by software or a network administrator, overriding the burned-in address of a physical device.
Locally administered MAC addresses help explain a wide range of normal networking behavior that can otherwise can look confusing in Pi-hole’s UI. In modern networks, a device may reboot or a container may be recreated and come back with a new MAC, multiple virtual machines may share templates that generate related addresses, or Docker and Kubernetes workloads may appear and disappear as infrastructure scales. When Pi-hole shows these MACs without vendor information, users often assume something is broken - perhaps the lookup database is out of date, the device is unknown or suspicious, or Pi-hole failed to identify the client correctly. By detecting and labeling these as locally administered, Pi-hole makes it clear that the behavior is intentional and standards-compliant, not an error, and helps users understand why certain DHCP or group assignments change over time.
The change is very small - checking a single standards-defined bit in the MAC address - and provides disproportionately large clarity and increases trust in the UI. As locally generated addresses are now extremely common across virtualization, container networking, software-defined networking, and privacy-protecting devices, this update helps Pi-hole better reflect the way real networks operate today.
I get this is a little outside the scope of pi-hole. I'm OK if that is the conclusion - it was just an itch that I needed to scratch..
Updated UI to "Locally Administered" (with the url to Wikipedia.)
If this is what people are looking for - the best thing would to do would be to add description of local addresses to : https://github.com/pi-hole/docs/tree/master/docs/guides/misc and point there, which I'm happy to do - but won't bother until others with approval rights say it's a good idea :)
Thanks
I like the idea of having these identified, but I wonder about the display style suggested.
No other circumstance adds a wikipedia link under each corresponding entry in the table and the visual clutter that this adds:
Compare with the somewhat more tasteful way that mock MAC addresses are indicated (italic text and a mouseover reading "Mock MAC Adddress"
Is there perhaps something a little more in line with this that could be used for the Locally Administered MACs ?
I agree with @rrobgill, we should not add a wikipedia link to each entry. Maybe a combination of 'N/A' as vendor + the tooltip with 'Locally administered'?
yes - I wasn't suggesting the link to wp was a good idea - only that if folks wanted - there could be a link there.
I tried the pop-up suggestion - and IMHO - is sucked worse. In order to see the popup, you have to mouse over each MAC, and it takes ~500-750 ms for the mouse to stabilise and the popup to appear. It defeats the purpose of scanning over something and seeing something quickly...
Having just "local address" - seems like the right idea to me. It appears like every other company name, fits in a single line, and is easily scanned by the eye.
Since I was there - and some of the above discussion was asking - added a lookup failed, since - this should not happen, and to me - it is a red flag...
Make sure to distinguish:
- OUI looking working successfully (works as is - Display company name)
- Private MAC address (Displays "Local Address")
- OUI lookup failure/Unregistered (Displays "Unregistered")
- Mock MAC address (Displays as is "Mock MAC address")
- Unknown Format (Displays "Unknown Format" - which in theory never happens).
If a string is chosen to stand in place of the vendor identifier, would be better to set it in FTL?
That way whatever string is chosen could be added directly to the network table in the same manner as entries from the manufacturer database rather than diverging what is presented to the user from what is stored in the database.
Insert code
// Check for special locally administered addresses if vendor not found
if(rc == SQLITE_DONE && strlen(hwaddr) >= 2)
{
const char second_char = tolower(hwaddr[1]);
if(second_char == '2')
strncpy(vendor, "Local - AA", MAXVENDORLEN);
else if(second_char == 'a')
strncpy(vendor, "Local - EL", MAXVENDORLEN);
else if(second_char == 'e')
strncpy(vendor, "Local - SA", MAXVENDORLEN);
vendor[MAXVENDORLEN - 1] = '\0';
}
BEFORE
if(rc != SQLITE_DONE && rc != SQLITE_ROW)
{
// Error
log_err("getMACVendor(\"%s\") - SQL error step: %s", hwaddr, sqlite3_errstr(rc));
It would execute once only, when the device is added to the network table, instead of in the browser every time the network page is rendered. All that the script would then need to handle would be any special formatting or mouseover tooltip (if implemented), in a similar manner as mock-MAC handling.
eg:
// Local administration marker
if (data.hwaddr && data.hwaddr.includes(":")) {
switch (data.hwaddr[1]) {
case "2": //
case "a": //
case "e": //
$("td:eq(1)", row).css("font-style", "oblique");
$("td:eq(1)", row).attr("title", "Locally administered MAC address");
break;
default:
break;
}
}
Also the current approach of looking at only bit 2 could report some misconfigured devices as being "Locally managed".
The local devices as defined in 7042 has been updated by rfc9542. There are three active and one reserved ranges of locally administered addresses:
- Administratively Assigned (x2:xx:xx:xx:xx:xx) such as typically used by phones and containers. This would be the range used by Apple and Android MAC randomization. Corresponding with the original "Private MAC" concept of this PR.
- Extended Local (xA:xx:xx:xx:xx:xx) assigned by manufacturers within their allocated address range. There are in the order of 250 examples of these ranges already present in the MAC database. If Locally managed devices are receiving special treatment in the web UI, should these be identified differently from other Locally managed addresses?
- Standard assigned (xE:xx:xx:xx:xx:xx) where the MAC is assigned locally by a protocol within this range.
- There is also a reserved space (x6:xx:xx:xx:xx:xx) which is for future use.
Devices with the multicast bit set (bit 1, any MAC with an odd number in the second hex digit) should likely not be identified as locally managed here, and probably neither should any devices in the reserved range.
I'd like @DL6ER's thoughts on this subject, too.
@rrobgill - thanks for pointers. Yes - RFC 9542 formally obsoletes RFC 7042 - that is totally correct, however, many modern OSes do not implement the Structured Local Address Plan (SLAP) that you correctly and accurately describe (yet).
Examples: Linux bridge / macvlan → U/L=1 See : https://github.com/torvalds/linux/blob/master/include/linux/etherdevice.h#L236-241
static inline void eth_random_addr(u8 *addr)
{
get_random_bytes(addr, ETH_ALEN);
addr[0] &= 0xfe; /* clear multicast bit */
addr[0] |= 0x02; /* set local assignment bit (IEEE802) */
}
Few OSes implement the SLAP rules that I know of - They simply generate “random MAC with local bit set., copying the linux code.
So ~25% of all such MACs end up in x6, which if you decode it according to 9542 - you get alot of "Reserved (Invalid Use)" labels...
I did update things - it's still pretty trival, and did re-order and add multicast like you rightly suggested.
Ok - I think this is the way to do it - display them all as "Locally Administered", and a mouse over will decode the SLAP encodings.
Opinions welcome.
This is what things look like. Comments welcome.