From 13f840b9f2731231dee6f4d66ff73fd121b59ac2 Mon Sep 17 00:00:00 2001 From: sebingel Date: Mon, 6 Apr 2026 10:37:51 +0000 Subject: [PATCH] Refactor Fritz!Box guest WiFi MAC generation to use string_to_fake_mac MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous implementation derived the guest WiFi device MAC using a custom MD5 hash of the Fritz!Box hardware MAC, producing a locally-administered address with a 02: prefix. This was inconsistent with the project-wide convention of using string_to_fake_mac() from crypto_utils, which produces a fa:ce: prefixed address and is used by all other plugins (nmap_dev_scan, adguard_import, pihole_api_scan, etc.). A naive switch to string_to_fake_mac(host) would have introduced a stability problem: if the user reconfigures FRITZBOX_HOST from an IP address (e.g. 192.168.178.1) to a hostname (e.g. fritz.box), the fake MAC would change and the guest device would re-appear as a new unknown device in NetAlertX. The Fritz!Box hardware MAC is a stable identifier that does not change with the configured host string. Requested by reviewer jokob-sk in PR #1592. Changes: - Remove import hashlib (fritzbox.py:3) — no longer needed - Add import string_to_fake_mac from utils.crypto_utils (fritzbox.py:15) - Replace custom MD5-based MAC derivation in create_guest_wifi_device() with string_to_fake_mac(normalize_mac(fritzbox_mac)) (fritzbox.py:178) The Fritz!Box hardware MAC is fetched via TR-064 as before, but is now passed to the shared project utility instead of a custom hash. - Add host parameter to create_guest_wifi_device(fc, host) (fritzbox.py:169) Used as fallback input to string_to_fake_mac() if the hardware MAC cannot be retrieved. - Update call site in main() to pass host (fritzbox.py:224) The guest WiFi device MAC is now stable across host configuration changes and consistent with the fa:ce: prefix convention used across the project. --- front/plugins/fritzbox/fritzbox.py | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/front/plugins/fritzbox/fritzbox.py b/front/plugins/fritzbox/fritzbox.py index fa1088fd..5beaa164 100755 --- a/front/plugins/fritzbox/fritzbox.py +++ b/front/plugins/fritzbox/fritzbox.py @@ -1,6 +1,5 @@ #!/usr/bin/env python -import hashlib import os import sys from pytz import timezone @@ -13,6 +12,7 @@ from const import logPath # noqa: E402, E261 [flake8 lint suppression] from plugin_helper import Plugin_Objects, normalize_mac # noqa: E402, E261 [flake8 lint suppression] from logger import mylog, Logger # noqa: E402, E261 [flake8 lint suppression] from helper import get_setting_value # noqa: E402, E261 [flake8 lint suppression] +from utils.crypto_utils import string_to_fake_mac # noqa: E402, E261 [flake8 lint suppression] from fritzconnection import FritzConnection # noqa: E402, E261 [flake8 lint suppression] from fritzconnection.lib.fritzhosts import FritzHosts # noqa: E402, E261 [flake8 lint suppression] @@ -166,26 +166,16 @@ def check_guest_wifi_status(fc, guest_service_num): return guest_info -def create_guest_wifi_device(fc): +def create_guest_wifi_device(fc, host): """ Create a synthetic device entry for guest WiFi. - Derives a locally-administered MAC (02:xx:xx:xx:xx:xx) from the Fritz!Box MAC. + Derives a deterministic fake MAC from the Fritz!Box hardware MAC address. + Falls back to the configured host string if the MAC cannot be retrieved. Returns: Device dictionary """ try: - # Get Fritz!Box MAC address fritzbox_mac = fc.call_action('DeviceInfo:1', 'GetInfo').get('NewMACAddress', '') - - if fritzbox_mac: - # Derive a deterministic locally-administered MAC (02:xx:xx:xx:xx:xx). - # The 02 prefix sets the locally-administered bit, ensuring no collision - # with real OUI-assigned MACs. The remaining 5 bytes come from an MD5 - # hash of the Fritz!Box MAC so the guest MAC is stable across runs. - digest = hashlib.md5(f'GUEST:{normalize_mac(fritzbox_mac)}'.encode(), usedforsecurity=False).digest() - guest_mac = '02:' + ':'.join(f'{b:02x}' for b in digest[:5]) - else: - # Fallback if we can't get Fritz!Box MAC - guest_mac = '02:00:00:00:00:01' + guest_mac = string_to_fake_mac(normalize_mac(fritzbox_mac) if fritzbox_mac else host) device = { 'mac_address': guest_mac, @@ -234,7 +224,7 @@ def main(): if report_guest: guest_status = check_guest_wifi_status(fc, guest_service) if guest_status['active']: - guest_device = create_guest_wifi_device(fc) + guest_device = create_guest_wifi_device(fc, host) if guest_device: device_data.append(guest_device)