Vai al testo principale

MAC spoofing con indirizzo casuale generato dal kernel Linux

Stavo litigando con un Microchip LAN 9500 senza la EEPROM in cui salvare il suo indirizzo MAC. Usando il driver smsc95xx fornito dalla mainline di Linux, mi sono accorto che il kernel stava (ragionevolmente) creando un indirizzo random ad ogni reboot.

Al mio cliente questo non piaceva, e del resto l'oggetto avrebbe dovuto lavorare solo all'interno di una LAN, così ho iniziato a cercare un modo per fare MAC spoofing.

Ho trovato questo link interessante, che mi ha dato le prime idee su come affrontare il problema.

Tuttavia, nessuno dei metodi automatici proposti stava funzionando nella mia distribuzione Yocto. Ad esempio, il "Method 1", basato su /etc/systemd/network/00-default.link, mi dava questo messaggio di errore nel journalctl:

Dec 12 09:22:26 colibri-imx6 systemd-udevd[273]: Could not set Alias,
MACAddress or MTU on eth1: Device or resource busy
Dec 12 09:22:26 colibri-imx6 systemd-udevd[273]: Could not apply link
config to eth1: Device or resource busy

Temo che systemd stava cercando di applicare la regola troppo presto, quando l'interfaccia eth1 era ancora occupata a fare altro.

Un altro problema con il metodo standard di spoofing è legato al MAC address da ottenere, che dovrà essere cambiato manualmente per ogni macchina, e questo non è semplice da gestire. Pensai che la cosa migliore sarebbe lasciare che il kernel generi l'indirizzo casuale al primo boot, e che poi il sistema lo riusi ai reboot successivi.

Ecco come sono riuscito a ottenere questo obiettivo, e qualche suggerimento nel caso che voglia fare lo stesso.

Prima di tutto, ho scelto, nel mio filesystem, dove mettere gli script per lo spoofing. Ho deciso di creare una directory apposita, /var/local/mac_spoof/.

Poi, ho aggiunto la seguente regola di udev, creando un file di una linea in /etc/dev/rules.d/75-mac-spoof.rules. Questo il suo contenuto:

ACTION=="add", SUBSYSTEM=="net", KERNEL=="eth1", RUN+="/var/local/mac_spoof/mac_spoof.sh %k"

Per finire, questo è lo script /var/local/mac_spoof/mac_spoof.sh:

#!/bin/sh

ETH=$1
BATCH=/var/local/mac_spoof/${ETH}_spoof.batch
ADDR=$(cat /sys/class/net/$ETH/address)

# Create batch file if not exists (first boot)
if [ ! -f $BATCH ]
then
        echo link set dev $ETH down > $BATCH
        echo link set dev $ETH address $ADDR >> $BATCH
        echo link set dev $ETH up >> $BATCH
fi

# Apply ip batch, or delete it if anything failed
ip -batch $BATCH || rm -f $BATCH

Come funziona lo script

mac_spoof.sh è chiamato da udev ogni volta che l'interfaccia eth1 viene aggiunta al sistema. Il suo compito è:

  • controllare se il file /var/local/mac_spoof/eth1_spoof.batch esiste; in caso negativo, lo crea scrivendo il batch ip per eseguire MAC spoofing d'ora in avanti. L'indirizzo (variabile ADDR) è letto da sysfs, e basandosi sul fatto che è stato creato in maniera random dal kernel;
  • applicare il batch ip, or cancellare il file the eth1_spoof.batch in caso di fallimento.

Ecco come controllare che tutto sia andato bene: l'indirizzo MAC in eth1_spoof.batch deve essere lo stesso di quello ritornato dal comando ip (o ifconfig). Nel mio caso, si può vedere che è 52:23:64:e2:fa:ad in entrambi i casi:

root@colibri-imx6:~# cat /var/local/mac_spoof/eth1_spoof.batch
link set dev eth1 down
link set dev eth1 address 52:23:64:e2:fa:ad
link set dev eth1 up

root@colibri-imx6:~# ip addr show eth1
4: eth1: <BROADCAST,MULTICAST,DYNAMIC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
        link/ether 52:23:64:e2:fa:ad brd ff:ff:ff:ff:ff:ff
        inet 169.254.138.55/16 brd 169.254.255.255 scope global eth1
        valid_lft forever preferred_lft forever
        inet6 fe80::5023:64ff:fee2:faad/64 scope link
        valid_lft forever preferred_lft forever

Questo metodo ha funzionato nel mio caso, non posso assicurare che funzioni su qualsiasi distribuzione o situazione; se trovi qualcosa da segnalarmi, contattami.