Randomize system hostname from device profile to match MAC identity
This commit is contained in:
@@ -11,6 +11,7 @@ import json
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import socket
|
||||
import sqlite3
|
||||
import time
|
||||
from pathlib import Path
|
||||
@@ -58,6 +59,7 @@ class MacManager(BaseModule):
|
||||
self._wifi_iface: Optional[str] = None
|
||||
self._original_eth_mac: Optional[str] = None
|
||||
self._original_wifi_mac: Optional[str] = None
|
||||
self._original_hostname: Optional[str] = None
|
||||
self._db_path = self._resolve_db_path()
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
@@ -90,6 +92,8 @@ class MacManager(BaseModule):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self._original_hostname = socket.gethostname()
|
||||
|
||||
# Select and apply profile
|
||||
self._profile = self._select_profile()
|
||||
if self._profile is None:
|
||||
@@ -131,6 +135,18 @@ class MacManager(BaseModule):
|
||||
logger.warning("Failed to restore original MAC: %s", exc)
|
||||
|
||||
self._cleanup_dhclient_conf()
|
||||
|
||||
if self._original_hostname:
|
||||
try:
|
||||
import subprocess
|
||||
subprocess.run(
|
||||
["hostnamectl", "set-hostname", self._original_hostname],
|
||||
check=True, capture_output=True,
|
||||
)
|
||||
logger.debug("Hostname restored to %s", self._original_hostname)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self._running = False
|
||||
self.state.set_module_status(self.name, "stopped")
|
||||
logger.info("MacManager stopped — original MACs restored")
|
||||
@@ -145,6 +161,8 @@ class MacManager(BaseModule):
|
||||
base["profile_name"] = self._profile.get("device_name", "unknown")
|
||||
base["applied_mac"] = self._profile.get("applied_mac", "unknown")
|
||||
base["dhcp_hostname"] = self._profile.get("dhcp_hostname", "unknown")
|
||||
if self._profile.get("applied_hostname"):
|
||||
base["applied_hostname"] = self._profile["applied_hostname"]
|
||||
if self._eth_iface:
|
||||
try:
|
||||
base["current_eth_mac"] = get_mac(self._eth_iface)
|
||||
@@ -304,6 +322,8 @@ class MacManager(BaseModule):
|
||||
|
||||
logger.debug("TCP stack: TTL=%d, window=%d", ttl, tcp_win)
|
||||
|
||||
self._set_system_hostname(profile)
|
||||
|
||||
def _write_dhclient_conf(self, profile: dict) -> None:
|
||||
"""Write dhclient.conf with hostname + vendor class matching the profile."""
|
||||
hostname = profile.get("dhcp_hostname", "localhost")
|
||||
@@ -327,6 +347,24 @@ class MacManager(BaseModule):
|
||||
except (IOError, PermissionError) as exc:
|
||||
logger.warning("Failed to write dhclient.conf: %s", exc)
|
||||
|
||||
def _set_system_hostname(self, profile: dict) -> None:
|
||||
"""Set system hostname to match the device profile for full fingerprint consistency."""
|
||||
import subprocess
|
||||
hostname = profile.get("dhcp_hostname", "")
|
||||
if not hostname:
|
||||
return
|
||||
suffix = "".join(f"{random.randint(0, 15):x}" for _ in range(4))
|
||||
new_hostname = f"{hostname}-{suffix}"
|
||||
try:
|
||||
subprocess.run(
|
||||
["hostnamectl", "set-hostname", new_hostname],
|
||||
check=True, capture_output=True,
|
||||
)
|
||||
profile["applied_hostname"] = new_hostname
|
||||
logger.info("System hostname set to %s", new_hostname)
|
||||
except Exception as exc:
|
||||
logger.warning("Failed to set hostname: %s", exc)
|
||||
|
||||
def _cleanup_dhclient_conf(self) -> None:
|
||||
"""Remove our DHCP config on clean exit."""
|
||||
conf_file = "/etc/dhcp/dhclient.conf.d/bb-profile.conf"
|
||||
|
||||
Reference in New Issue
Block a user