generuj spójny unikalny identyfikator maszyny

20

Czy możemy wygenerować unikalny identyfikator dla każdego komputera, coś w rodzaju uuuidgen, ale nigdy się nie zmieni, chyba że nastąpią zmiany sprzętowe? Myślałem o połączeniu CPUID i MACADDR i skrótu, aby wygenerować spójny identyfikator, ale nie mam pojęcia, jak je parsować za pomocą skryptu bash, wiem, jak mogę uzyskać CPUID

dmidecode -t 4 | grep ID

i

ifconfig | grep ether

następnie muszę połączyć te ciągi szesnastkowe i mieszać je za pomocą sha1 lub md5, aby utworzyć ciąg szesnastkowy o stałej długości.
Jak mogę przeanalizować ten wynik?

uray
źródło
4
Jaki dokładnie problem próbujesz rozwiązać za pomocą tej metody?
Darkhogg
1
Jestem z Darkhoggiem. Zasadniczo jest to zły pomysł, aby robić takie rzeczy w dzisiejszych czasach. Wirtualizacja sprawiła, że ​​praktyka wiązania oprogramowania ze sprzętem fizycznym stała się bezcelowa. Zwykle jest lepsza odpowiedź, jeśli dokładnie przeanalizujesz swoje wymagania (do czego dąży Darkhogg).
Calphool
4
Nie używam tego do wiązania oprogramowania z maszyną, to platforma wydobywcza Linux musi się zidentyfikować w usłudze kontroli i monitorowania w chmurze, zamiast ręcznie nazwać tysiące platform, muszę je jednoznacznie zidentyfikować za pomocą identyfikatora sprzętowego
uray
1
@ user77710: Jeśli tak, to czy naprawdę zależy ci na sprzęcie? Dlaczego nie wygenerować UUID na komputerze, jeśli nie istnieje? Właśnie o to chodzi w przypadku UUID - są one uniwersalnie unikalne (ich prawdopodobieństwo nakładania się jest astronomicznie nieprawdopodobne). serverfault.com/questions/103359/how-to-create-a-uuid-in-bash
Calphool
1
@JoeRounceville - Nie miałem na myśli, że SecureBoot sam jest rozwiązaniem - chociaż obsługuje samopodpisane certyfikaty - ale raczej jego metodą . Ale używa interfejsu API oferowanego przez oprogramowanie układowe systemu - a każdy system UEFI będzie miał tyle identyfikatorów UUID, ile można potrzebować już w nazwie każdej zmiennej oprogramowania układowego - patrz moja odpowiedź. Ponadto nie potrzebujesz żadnej aplikacji - lub bash- do wygenerowania UUID na dowolnym systemie Linux. cat /proc/sys/kernel/random/uuid.
mikeserv

Odpowiedzi:

21

A co z tymi dwoma:

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

Następnie możesz je łączyć i mieszać za pomocą:

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

Aby usunąć końcową kreskę, dodaj jeszcze jedną rurkę:

$ 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

Jak wskazuje @mikeserv w swojej odpowiedzi , nazwa interfejsu może się zmieniać między butami. Oznacza to, że dzisiejszym eth0 może być jutro eth1, więc jeśli grep dla niego, eth0możesz uzyskać inny adres MAC na różnych butach. Mój system nie zachowuje się w ten sposób, więc nie mogę naprawdę przetestować, ale możliwe rozwiązania to:

  1. Witaj HWaddrw danych wyjściowych, ifconfigale zachowaj wszystkie, nie tylko te odpowiadające konkretnej karcie sieciowej. Na przykład w moim systemie mam:

    $ 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  

    Chwytając oba adresy MAC i przekazując je sha256sum, powinieneś być w stanie uzyskać unikalną i stabilną nazwę, niezależnie od tego, która karta sieciowa nazywa się:

    $ 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    

    Zauważ, że skrót różni się od powyższych, ponieważ przekazuję oba adresy MAC zwrócone przez ifconfig się sha256sum.

  2. Zamiast tego utwórz skrót na podstawie identyfikatorów UUID dysków twardych:

    $ blkid | grep -oP 'UUID="\K[^"]+' | sha256sum | awk '{print $1}'
    162296a587c45fbf807bb7e43bda08f84c56651737243eb4a1a32ae974d6d7f4
terdon
źródło
to miłe, ale jak się pozbyć końcowej kreski „-”?
uray
@ user77710 zobacz zaktualizowaną odpowiedź.
terdon
1
Myślę, że cpuid jest gorszy ... wikipedia.org/wiki/cpuid
mikeserv
@mikeserv ah, tak, rzeczywiście rozumiem twój punkt widzenia. Dziękuję, edytowano odpowiedź.
terdon
Generuje ten sam identyfikator dla wszystkich systemów operacyjnych gościa na tym samym hoście.
Nitinkumar Ambekar
23

Po pierwsze, należy pamiętać, że CPUID zdecydowanie nie jest powszechnie dostępnym, jednoznacznie identyfikującym markerem dla jakiegokolwiek systemu późniejszego niż Intel Pentium III. Chociaż mieszanie go z adresami MAC może z pewnością prowadzić do unikalnych znaczników, jest to spowodowane jedynie unikalnymi cechami samych MAC, a CPUID w tym przypadku jest niczym więcej jak tylko poszlakami. Co więcej, wynikowy skrót nie jest bardziej unikalny niż UUID płyty głównej, i jest to znacznie łatwiejsze do odzyskania, a proces jest znacznie mniej podatny na błędy. Z wikipedia.org/wiki/cpuid :

EAX = 3 : Numer seryjny procesora

Zobacz też: Pentium III § Kontrowersje dotyczące kwestii prywatności

Zwraca numer seryjny procesora. Numer seryjny procesora został wprowadzony na Intel Pentium III, ale ze względu na obawy dotyczące prywatności ta funkcja nie jest już implementowana w późniejszych modelach (bit funkcji PSN jest zawsze czyszczony). Procesory Efficeon i Crusoe firmy Transmeta również zapewniają tę funkcję. Jednak procesory AMD nie implementują tej funkcji w żadnym modelu procesora.

Możesz zobaczyć sparsowany cpuid sam, robiąc cat /proc/cpuinfolub nawet po prostu lscpu.

To daje ci wszystkie adresy MAC interfejsów sieciowych rozpoznawanych przez jądro Linuksa, tak myślę:

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

Może być konieczne odfiltrowanie tej listy, jeśli może ona zawierać wirtualne karty sieciowe z losowo generowanymi adresami MAC. Możesz to zrobić bezpośrednio z flagami w wywołaniu ip. Zobacz, ip a helpjak to zrobić.

Należy również pamiętać, że ten problem nie jest unikalny ipi należy go rozwiązać, jeśli go używasz ifconfig, ale że można go bardziej pewnie rozwiązać ip- który jest częścią iproute2pakietu sieciowego i jest aktywnie utrzymywany - niż może ifconfig- który jest członkiem z net-toolsopakowania i ostatni zobaczył Linux kin w 2001 roku . Ze względu na zmieniające się funkcje jądra od czasu jego ostatniego wydania, ifconfigjest to znane misreport jakieś flagi funkcji sieci i jej stosowanie należy unikać, jeśli to w ogóle możliwe.

Zrozum jednak, że filtrowanie za pomocą nazw interfejsów jądra, takich jak, eth[0-9]nie jest niezawodnym sposobem, aby to zrobić, ponieważ mogą się one zmieniać w zależności od kolejności równoległego wykrywania udevpodczas procesu rozruchu. Więcej informacji na ten temat można znaleźć w części Przewidywalne nazwy sieciowe .

Ponieważ dmidecodenie jest zainstalowany w moim systemie, na początku pomyślałem o utworzeniu listy numerów seryjnych dysków twardych, takich jak:

lsblk -nro SERIAL

Zrób lsblk --helpkilka wskazówek na temat dopracowywania tej listy - powiedzmy według typu dysku. Weź również pod uwagęlspci i / lub lsusbmoże.

Łączenie ich jest łatwe:

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

Jak już poinformowałeś mnie, że kluczujesz zasoby użytkownika na jego unikalne identyfikatory, a na dyskach twardych nie można polegać, że istnieją, pomyślałem o zmianie halsu.

Biorąc to pod uwagę, ponownie spojrzałem na system plików i znalazłem /sys/class/dmi/idfolder. Sprawdziłem kilka plików:

cat ./board_serial ./product_serial

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

Jednak ten wydaje się być całkiem dobry, ale nie opublikuję wyniku:

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

Spodziewam się, że i tak dmidecodedostaje większość swoich informacji i tak naprawdę to wygląda . Według man dmidecodeCiebie możesz również znacznie uprościć korzystanie z tego narzędzia, podając argument:

dmidecode -s system-uuid

Jeszcze prościej, możesz po prostu odczytać plik. Pamiętaj, że ten konkretny plik konkretnie identyfikuje płytę główną. Oto fragment poprawki do jądra z 2007 r., Która pierwotnie implementowała te eksporty do /sysfswirtualnego systemu plików:

+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);

Możesz użyć tych danych samodzielnie do identyfikacji systemu - jeśli płyta główna jest wystarczająca. Ale możesz połączyć te informacje z MAC systemu w taki sam sposób, jak pokazałem, że możesz zrobić z dyskami twardymi:

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

Jądro Linux może również generować dla Ciebie UUID:

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

Lub:

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

To prawda, to generowany losowo i trzeba będzie przemyśleć cesji osobistego, ale tu chodzi o tak proste, jak to robi się dostać przynajmniej. I powinno być całkiem solidne, jeśli możesz znaleźć sposób, aby to kluczować.

Wreszcie w systemach UEFI jest to o wiele łatwiejsze - ponieważ każda zmienna środowiskowa oprogramowania układowego EFI zawiera własny identyfikator UUID. Zmienna środowiskowa {Platform,}LangCodes-${UUID}powinna być obecna w każdym systemie UEFI, powinna trwać ponowne uruchamianie, a nawet większość aktualizacji i modyfikacji oprogramowania układowego, a każdy system Linux z efivarfszaładowanym modułem może wyświetlać jedną lub obie nazwy tak po prostu:

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

Starsza forma - LangCodes-${UUID}najwyraźniej jest teraz przestarzała i na nowszych systemach powinna być, PlatformLangCodes-${UUID}ale zgodnie ze specyfikacją, jedno lub drugie powinno być obecne w każdym systemie UEFI. Przy niewielkim wysiłku możesz zdefiniować własne zmienne trwałe przy ponownym uruchomieniu komputera i być może w ten sposób lepiej wykorzystać generator UUID jądra. W razie zainteresowania zajrzyj do efitools .

mikeserv
źródło
nie ma nawet uruchomionego twardego dysku ani żadnego dysku, jego urządzenie górnicze, jeśli nie wiesz, co to takiego, diit.cz/sites/default/files/images/3988/... maszyna wirtualna nie może uruchomić 6 GPU na jednym płyta główna
uray
w każdym razie nigdy nie powinien używać żadnej przypadkowej liczby, ponieważ jest to cel konsekwentnego nadawania nazwy maszynie, ponieważ podczas uruchamiania systemu identyfikator nie powinien się zmienić
uray
@ user77710 - Cholera, stary, to jest fajne. Czy to jedna maszyna? Prawdopodobnie masz rację, ale może to być możliwe przy użyciu kombinacji XDMX i Chromium - niektórych rozproszonych elementów graficznych. W każdym razie nie miałoby to znaczenia - miałem to do tyłu. Kto chciałby pobić się z pieniędzy? Myślałem o jakiejś licencji na oprogramowanie lub coś - robisz konta bankowe.
mikeserv
Są tam jakieś fajne sztuczki, które masz tam, +1.
terdon
@terdon - komplement jest bardzo doceniany, ale w większości nie są to sztuczki. ip2jest specjalnie zaprojektowany do analizowania i być może nie robię tego wystarczająco dobrze - podejrzewam, że to samo można zrobić prawie bez grep/sed. Prawdopodobnie to samo można zrobić tak łatwo udevadm. Każda nazwa zmiennej środowiskowej EFI została zaprojektowana w taki sposób, aby była jednoznacznie identyfikowana właśnie w tego rodzaju sytuacjach.
mikeserv
19

Wiele współczesnych dystrybucji dostarcza plik /etc/machine-idzawierający najprawdopodobniej unikalny szesnastkowy ciąg 32 znaków. Pochodzi z systemd, gdzie strona man ma więcej informacji i może być odpowiednia do twojego celu.

XZS
źródło
+1, @XZS, możesz również dodać odpowiednie informacje z adresu URL tutaj.
Ramesh
1
To dobrze, znalazłem podobne informacje i prawie z nich skorzystałem ... ale już byłem zaangażowany w inną trasę. Jednak należy zauważyć, że jest to dbusspecyficzne, jak sądzę, i zmienia się, jeśli system operacyjny zostanie wyczyszczony / ponownie zainstalowany.
mikeserv
To jest cholernie niesamowite.
GeneCode,
5

Na wielu komputerach z systemem Linux plik /var/lib/dbus/machine-idzawiera unikatowy identyfikator dla każdej dystrybucji systemu Linux i można uzyskać do niego dostęp, wywołując polecenie dbus_get_local_machine_id(). Jest to prawdopodobnie to samo, co /etc/machine-idwspomniane powyżej. Działa również w wirtualnych instalacjach Linuksa. Sprawdziłem to w obecnych dystrybucjach Ubuntu, SuSE i CentOS.

rankeney
źródło
1
W Fedorze 19 + 20 ten plik nie istnieje. To tutaj: /etc/machine-id.
slm
Być może nie byłem wystarczająco jasny. Chodzi mi o to, że jeśli nie znajdziesz tego jednego miejsca, spójrz na drugie. Lub napisz własny program za pomocą wywołania funkcji.
rankeney
0

Czy potrzebujesz identyfikatora komputera, aby zmienić, gdy zmienia się sprzęt? Czy identyfikator maszyny jest używany do ochrony czegoś? Uważam, że najlepszym sposobem na uzyskanie „spójnego” identyfikatora maszyny jest przechowywanie losowego ciągu znaków w systemie. W ten sposób, jeśli którykolwiek z elementów sprzętu ulegnie zmianie, identyfikator komputera również się nie zmieni. Jest to również dobre w przypadku systemów zwirtualizowanych, w których dostęp sprzętowy jest ograniczony, a identyfikator MAC to 00: 00: 00: 00

Spróbuj czegoś takiego jak ten skrypt sh, aby utworzyć i uzyskać identyfikator:

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

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

cat $FILE;
ub3rst4r
źródło
Ponieważ i /dev/urandomtak wskazuje Linux, możesz po prostu zrobić, cat /proc/sys/kernel/random/uuid >$FILEco losowo generuje poprawnie sformatowany UUID przy każdym czytaniu. Mimo to utrwalanie zaimplementowane na dysku podlega usunięciu, a pod warunkiem, że jest to dopuszczalne, a pod warunkiem dbus, że jest zainstalowane, prawdopodobnie powinieneś zrobić tak, jak sugerował @XZS.
mikeserv
0

Pozostałe odpowiedzi podają wiele sposobów wydobywania identyfikatorów ze sprzętu. Możesz zdecydować się na użycie jednego elementu sprzętu jako identyfikatora lub wielu. Jest to problematyczne, jeśli trzeba dowolnie zamieniać lub wymieniać sprzęt.

Niektóre osoby mogą zamiast tego przechowywać identyfikator wygenerowanego identyfikatora na dysku twardym (lub użyć identyfikatora UUID), ale dyski twarde można klonować.

Moduły TPM i bezpieczny rozruch mogą zapewnić sposób wiązania płyty głównej i innego sprzętu z instalacją na dysku twardym.

W takich przypadkach zawsze jest trochę łatwiej, jeśli podasz więcej informacji o tym, co chcesz osiągnąć.

jgmjgm
źródło