generare un ID univoco macchina coerente


20

Possiamo generare un ID univoco per ogni PC, qualcosa come uuuidgen, ma non cambierà mai a meno che non ci siano modifiche hardware? Stavo pensando di unire CPUID e MACADDR e li ho hash per generare un ID coerente, ma non ho idea di come analizzarli usando lo script bash, quello che so è come posso ottenere CPUID da

dmidecode -t 4 | grep ID

e

ifconfig | grep ether

quindi devo combinare quelle stringhe esadecimali e cancellarle usando sha1 o md5 per creare stringhe esadecimali a lunghezza fissa.
Come posso analizzare quell'output?


4
Qual è esattamente il problema che stai cercando di risolvere usando questo metodo?
Darkhogg,

1
Sono con Darkhogg. In genere è una cattiva idea provare a fare questo genere di cose in questi giorni. La virtualizzazione ha reso inutile la pratica di associare il software all'hardware fisico. Di solito c'è una risposta migliore se si esaminano attentamente le proprie esigenze (che è ciò a cui Darkhogg sta guidando).
Calphool,

4
non lo uso per associare un software a una macchina, è un impianto di mining di Linux che deve identificarsi con il servizio di monitoraggio e monitoraggio del cloud, invece di nominare migliaia di rig manualmente, ho bisogno di identificarli in modo univoco usando il loro ID hardware
uray

1
@ user77710: In tal caso, ti preoccupi davvero dell'hardware? Perché non generare semplicemente un UUID sulla macchina se non esiste. Questo è il punto di un UUID: sono universalmente unici (le loro probabilità di sovrapposizione sono astronomicamente improbabili). serverfault.com/questions/103359/how-to-create-a-uuid-in-bash
Calphool

1
@JoeRounceville - Non intendevo dire che SecureBoot stesso fosse la soluzione - sebbene supporti i certificati autofirmati - ma piuttosto il suo metodo . Ma utilizza un'API offerta dal firmware del sistema - e qualsiasi sistema UEFI avrà tutti gli UUID di cui potresti aver bisogno già impostato nel nome di ciascuna variabile del firmware - vedi la mia risposta. Inoltre, non hai bisogno di alcuna applicazione - o bash- per generare un UUID su qualsiasi Linux. cat /proc/sys/kernel/random/uuid.
Mikeserv,

Risposte:


21

Che ne dici di questi due:

$ sudo dmidecode -t 4 | grep ID | sed 's/.*ID://;s/ //g'
52060201FBFBEBBF
$ ifconfig | grep eth1 | awk '{print $NF}' | sed 's/://g'
0126c9da2c38

È quindi possibile combinarli e cancellarli con:

$ echo $(sudo dmidecode -t 4 | grep ID | sed 's/.*ID://;s/ //g') \
       $(ifconfig | grep eth1 | awk '{print $NF}' | sed 's/://g') | sha256sum 
59603d5e9957c23e7099c80bf137db19144cbb24efeeadfbd090f89a5f64041f  -

Per rimuovere il trattino finale, aggiungi un'altra pipe:

$ echo $(sudo dmidecode -t 4 | grep ID | sed 's/.*ID://;s/ //g') \
       $(ifconfig | grep eth1 | awk '{print $NF}' | sed 's/://g') | sha256sum |
  awk '{print $1}'
59603d5e9957c23e7099c80bf137db19144cbb24efeeadfbd090f89a5f64041f

Come sottolinea @mikeserv nella sua risposta , il nome dell'interfaccia può cambiare tra gli stivali. Ciò significa che ciò che è eth0 oggi potrebbe essere eth1 domani, quindi se fai grep per eth0te potresti ottenere un indirizzo MAC diverso su boot diversi. Il mio sistema non si comporta in questo modo, quindi non posso davvero testarlo ma le possibili soluzioni sono:

  1. Grep per HWaddrl'output di ifconfigma mantenerli tutti, non solo quello corrispondente a una scheda NIC specifica. Ad esempio, sul mio sistema ho:

    $ ifconfig | grep HWaddr
    eth1      Link encap:Ethernet  HWaddr 00:24:a9:bd:2c:28  
    wlan0     Link encap:Ethernet  HWaddr c4:16:19:4f:ac:g5  

    Prendendo entrambi gli indirizzi MAC e facendoli passare sha256sum, dovresti essere in grado di ottenere un nome univoco e stabile, indipendentemente da quale NIC è chiamata come:

    $ echo $(sudo dmidecode -t 4 | grep ID | sed 's/.*ID://;s/ //g') \
         $(ifconfig | grep -oP 'HWaddr \K.*' | sed 's/://g') | sha256sum |
          awk '{print $1}'
    662f0036cba13c2ddcf11acebf087ebe1b5e4044603d534dab60d32813adc1a5    

    Si noti che l'hash è diverso da quelli sopra perché sto passando entrambi gli indirizzi MAC restituiti ifconfiga sha256sum.

  2. Crea invece un hash basato sugli UUID dei tuoi dischi rigidi:

    $ blkid | grep -oP 'UUID="\K[^"]+' | sha256sum | awk '{print $1}'
    162296a587c45fbf807bb7e43bda08f84c56651737243eb4a1a32ae974d6d7f4

è carino, ma come sbarazzarsi del trattino finale "-"?
Uray,

@ user77710 vedi risposta aggiornata.
terdon

1
Immagino che cpuid sia peggio ... wikipedia.org/wiki/cpuid
mikeserv

@mikeserv ah, sì davvero, vedo il tuo punto. Grazie, risposta modificata.
terdon

Genera lo stesso ID per tutti i SO guest sullo stesso host.
Nitinkumar Ambekar,

23

In primo luogo, si ricorda che il CPUID è sicuramente non è un comunemente accessibili marcatore che identifica in modo univoco per qualsiasi sistema entro e non oltre un processore Intel Pentium III. Mentre l'hash con gli indirizzi MAC può certamente portare a marcatori univoci, ciò è dovuto solo alle qualità uniche dei MAC stessi e il CPUID in questo caso non è altro che circostanziale. Inoltre, è probabile che l'hash risultante non sia più unico dell'UUID della scheda madre, e questo è molto più facile da recuperare e il processo è molto meno soggetto a errori. Da wikipedia.org/wiki/cpuid :

EAX = 3 : numero di serie del processore

Vedi anche: Pentium III § Polemiche su problemi di privacy

Ciò restituisce il numero seriale del processore. Il numero di serie del processore è stato introdotto su Intel Pentium III, ma a causa di problemi di privacy, questa funzione non è più implementata sui modelli successivi (il bit di funzionalità PSN viene sempre cancellato). Anche i processori Efficeon e Crusoe di Transmeta offrono questa funzionalità. Le CPU AMD, tuttavia, non implementano questa funzione in nessun modello di CPU.

Puoi visualizzare un cpuid analizzato da cat /proc/cpuinfosolo o semplicemente lscpu.

Questo ti dà tutti gli indirizzi MAC per le interfacce di rete riconosciute dal kernel Linux, penso:

ip a | sed '\|^ *link[^ ]* |!d;s|||;s| .*||'

Potrebbe essere necessario filtrare tale elenco se potrebbe includere reti virtuali con MAC generati casualmente. Puoi farlo direttamente con i flag nella chiamata ip. Vedere ip a helpper informazioni su come farlo.

Si noti inoltre che questo problema non è univoco ipe deve essere affrontato anche se lo si utilizza ifconfig, ma che può essere gestito in modo più affidabile ip- che fa parte della iproute2suite di rete e viene attivamente gestito - rispetto a quanto può fare ifconfig- di cui è membro del net-toolspacchetto e ha visto l'ultima versione di Linux nel 2001 . A causa delle modifiche alle funzionalità del kernel dalla sua ultima versione, ifconfigè noto che riporta erroneamente alcuni flag delle funzionalità di rete e il suo uso dovrebbe essere evitato, se possibile.

Comprendi, tuttavia, che il filtro con nomi di interfaccia del kernel come eth[0-9]non è un mezzo affidabile per farlo, poiché questi possono cambiare in base al loro ordine di rilevamento parallelo udevdurante il processo di avvio. Per ulteriori informazioni, vedere Nomi di rete prevedibili .

Poiché dmidecodenon è installato sul mio sistema, all'inizio ho pensato di creare un elenco di numeri di serie di dischi rigidi generati come:

lsblk -nro SERIAL

Fallo lsblk --helpper alcuni indizi sul perfezionamento di tale elenco, ad esempio per tipo di disco. Considera anche lspcie / o lsusbforse.

Combinarli è facile:

{ ip a | sed ... ; lsblk ... ; } | #abbreviated... for brevity...
    tr -dc '[:alnum:]' | #deletes all chars not alphanumeric - including newlines
    sha256sum #gets your hash

Dato che mi hai informato che stai mettendo le risorse dell'utente al tuo posto ai loro ID univoci, e non è possibile fare affidamento sul fatto che i dischi rigidi esistano, ho pensato di cambiare il mio approccio.

Detto questo, ho guardato di nuovo nel filesystem e ho trovato la /sys/class/dmi/idcartella. Ho controllato alcuni dei file:

cat ./board_serial ./product_serial

###OUTPUT###
To be filled by O.E.M.
To be filled by O.E.M.

Tuttavia, questo sembra essere abbastanza buono, ma non pubblicherò l'output:

sudo cat /sys/class/dmi/id/product_uuid

Mi aspetto che sia lì che dmidecodeottiene gran parte delle sue informazioni e in effetti sembra proprio così . Secondo man dmidecodete puoi anche semplificare molto il tuo utilizzo di questo strumento specificando l'argomento:

dmidecode -s system-uuid

Più semplice, tuttavia, puoi semplicemente leggere il file. Si noti che questo particolare file identifica in modo specifico una scheda madre. Ecco un estratto dalla patch del kernel 2007 che originariamente implementava queste esportazioni nel /sysfsfilesystem virtuale:

+DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor,      0444, DMI_BIOS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(bios_version,         0444, DMI_BIOS_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(bios_date,        0444, DMI_BIOS_DATE);
+DEFINE_DMI_ATTR_WITH_SHOW(sys_vendor,       0444, DMI_SYS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(product_name,         0444, DMI_PRODUCT_NAME);
+DEFINE_DMI_ATTR_WITH_SHOW(product_version,   0444, DMI_PRODUCT_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(product_serial,    0400, DMI_PRODUCT_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(product_uuid,         0400, DMI_PRODUCT_UUID);
+DEFINE_DMI_ATTR_WITH_SHOW(board_vendor,         0444, DMI_BOARD_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(board_name,       0444, DMI_BOARD_NAME);
+DEFINE_DMI_ATTR_WITH_SHOW(board_version,     0444, DMI_BOARD_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(board_serial,         0400, DMI_BOARD_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(board_asset_tag,   0444, DMI_BOARD_ASSET_TAG);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_vendor,    0444, DMI_CHASSIS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_type,         0444, DMI_CHASSIS_TYPE);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_version,   0444, DMI_CHASSIS_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_serial,    0400, DMI_CHASSIS_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_asset_tag, 0444, DMI_CHASSIS_ASSET_TAG);

Potresti essere in grado di utilizzare quei dati da solo per identificare il sistema, se la scheda madre è sufficiente. Ma puoi combinare queste informazioni con i MAC del sistema nello stesso modo in cui ho dimostrato che potresti fare con i dischi rigidi:

sudo sh <<\CMD | tr -dc '[:alnum:]' | sha256sum
        ip a | sed '\|^ *link[^ ]* |!d;s|||;s| .*||'
        cat /sys/class/dmi/id/product_uuid 
CMD

Il kernel Linux può anche generare UUID per te:

cat /proc/sys/kernel/random/uuid #new random uuid each time file is read

O:

cat /proc/sys/kernel/random/boot_id #randomly generated per boot

Certo, viene generato casualmente e dovrai ripensare l'assegnazione degli ID, ma è almeno tanto semplice quanto ottenere . E dovrebbe essere abbastanza solido se riesci a trovare un modo per chiave.

Infine, sui sistemi UEFI questo diventa molto più facile da fare, poiché ogni variabile di ambiente del firmware EFI include il proprio UUID. La variabile d'ambiente {Platform,}LangCodes-${UUID}dovrebbe essere presente su ogni sistema UEFI, dovrebbe persistere al riavvio e persino alla maggior parte degli aggiornamenti e modifiche del firmware, e qualsiasi sistema Linux con il efivarfsmodulo caricato può elencare uno o entrambi i nomi semplicemente come:

printf '%s\n' /sys/firmware/efi/efivars/*LangCodes-*

La forma più vecchia - LangCodes-${UUID}è apparentemente ora deprecata , e sui sistemi più recenti dovrebbe essere PlatformLangCodes-${UUID}ma, secondo le specifiche, l'una o l'altra dovrebbe essere presente in ogni sistema UEFI. Con un piccolo sforzo, puoi definire il tuo riavvio delle variabili persistenti e forse fare un uso maggiore del generatore UUID del kernel in quel modo. Se interessati, guarda gli efitools .


non ha nemmeno hard disk o alcun disco in esecuzione, il suo impianto di mining, se non sai cosa sia vedere questo diit.cz/sites/default/files/images/3988/… la macchina virtuale non può eseguire 6 GPU su un singolo scheda madre
uray,

in ogni caso non dovrebbe mai usare un numero casuale poiché ha battuto lo scopo di nominare costantemente la macchina, mentre si avvia l'ID non dovrebbe cambiare
uray

@ user77710 - Dang, amico, quella cosa è bella. Quella è una macchina? Probabilmente hai ragione, ma potrebbe essere possibile con una combinazione di XDMX e Chromium - alcuni elementi grafici distribuiti. Ad ogni modo, non importa - l'ho avuto al contrario. Chi vorrebbe battere i propri soldi? Stavo pensando a qualcosa di licenza software o qualcosa del genere: stai facendo conti bancari.
Mikeserv,

Sono alcuni trucchi eleganti che hai fatto lì, +1.
terdon

@terdon - il complimento è molto apprezzato, ma, per la maggior parte, non sono trucchi. ip2è specificamente progettato per essere analizzato e può darsi che non lo stia facendo abbastanza bene - sospetto che la stessa cosa possa essere fatta quasi senza grep/sed. Probabilmente lo stesso potrebbe essere fatto con la stessa facilità udevadm. E ogni nome di variabile di ambiente EFI è progettato per essere identificato in modo univoco proprio per questo tipo di situazioni.
Mikeserv,

19

Molte distribuzioni moderne spediscono un file /etc/machine-idcontenente una stringa esadecimale di 32 caratteri molto probabilmente unica. Ha origine da systemd, dove una manpage contiene più informazioni e può essere appropriata per il tuo scopo.


+1, @XZS, puoi aggiungere qui anche le informazioni pertinenti dall'URL.
Ramesh,

1
Questo va bene e ho trovato informazioni simili e le ho quasi usate ... ma ero già impegnato in un percorso diverso. Tuttavia, va notato che questo è dbusspecifico, penso, e cambia se un sistema operativo viene cancellato / reinstallato.
Mikeserv,

Questo è davvero fantastico.
GeneCode

5

Su molte macchine Linux, il file /var/lib/dbus/machine-idcontiene un ID univoco per ogni distribuzione Linux ed è possibile accedervi chiamando dbus_get_local_machine_id(). Questo è probabilmente lo stesso di /etc/machine-idcui sopra. Funziona anche su installazioni Linux virtuali. L'ho verificato sulle attuali distribuzioni Ubuntu, SuSE e CentOS.


1
In Fedora 19 + 20 quel file non esiste. E 'qui: /etc/machine-id.
slm

Forse non ero abbastanza chiaro. Il punto era che se non lo trovi in ​​un posto, guarda nell'altro. Oppure scrivi il tuo programma usando la chiamata di funzione.
Rankeney,

0

È necessario modificare l'ID macchina quando cambia l'hardware? L'ID macchina viene utilizzato per proteggere qualcosa? Il modo migliore credo di avere un ID macchina "coerente" è archiviando una stringa casuale da qualche parte nel sistema e in questo modo se uno qualsiasi dell'hardware cambia, allora l'ID macchina non cambierà. Questo è utile anche per i sistemi virtualizzati in cui l'accesso all'hardware è limitato e l'ID MAC è 00: 00: 00: 00

Prova qualcosa di simile a questo script sh per creare e ottenere l'ID:

#!/bin/sh
FILE="/etc/machine-id"

if [ ! -f $FILE ]; then
    cat /dev/urandom|tr -dc A-Z0-9|head -c32 > $FILE;
fi

cat $FILE;

Dato che il tuo /dev/urandomindica comunque Linux, puoi semplicemente fare ciò cat /proc/sys/kernel/random/uuid >$FILEche genera casualmente un UUID formattato correttamente su ogni lettura. Tuttavia, qualsiasi persistenza implementata su disco è soggetta a cancellazione e, a condizione che sia accettabile e fornita dbussia installata, dovresti probabilmente fare come suggerito invece da @XZS.
Mikeserv,

0

Le altre risposte forniscono una serie di modi per estrarre gli ID dall'hardware. Potresti decidere di utilizzare un pezzo di hardware come identificatore o molti. Ciò è problematico se è necessario scambiare o sostituire arbitrariamente pezzi di hardware.

Alcune persone potrebbero invece archiviare un ID generato sul proprio hard disk (o usare l'UUID) ma i hard disk possono essere clonati.

I moduli TPM e l'avvio sicuro potrebbero fornire un mezzo per associare la scheda madre e altro hardware con un'installazione su un disco rigido.

In questi casi è sempre un po 'più semplice fornire ulteriori informazioni su ciò che si desidera ottenere.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.