генерувати послідовний унікальний ідентифікатор машини


20

Чи можемо ми створити унікальний ідентифікатор для кожного ПК, щось на зразок uuuidgen, але він ніколи не зміниться, якщо не відбудеться апаратних змін? Я думав про об'єднання CPUID і MACADDR і хеш для їх генерування послідовного ідентифікатора, але я не маю уявлення, як розібрати їх за допомогою bash script, що я знаю, як я можу отримати CPUID від

dmidecode -t 4 | grep ID

і

ifconfig | grep ether

то мені потрібно поєднувати ці шістнадцяткові рядки та хеш-файли їх за допомогою sha1 або md5 для створення шестигранної строки фіксованої довжини.
Як я можу проаналізувати цей вихід?


4
Яку саме проблему ви намагаєтеся вирішити за допомогою цього методу?
Darkhogg

1
Я з Darkhogg. Взагалі погана ідея намагатися робити ці речі сьогодні і в цей час. Віртуалізація зробила безпричинною прив'язку програмного забезпечення до фізичного обладнання. Зазвичай є краща відповідь, якщо ви уважно вивчаєте свої вимоги (саме до чого рухається Даркхогг).
Calphool

4
я не використовую це для прив'язки програмного забезпечення до машини, саме майнінг-установка Linux повинна ідентифікувати себе в хмарному сервісі управління та моніторингу, замість того, щоб називати тисячі такелажів вручну, мені потрібно однозначно ідентифікувати їх за допомогою їх ідентифікатора обладнання
uray

1
@ user77710: Якщо це так, то чи справді ви взагалі дбаєте про обладнання? Чому б просто не створити UUID на апараті, якщо такого не існує. У цьому суть UUID - вони універсально унікальні (їх шанси на перекриття є астрономічно малоймовірними). serverfault.com/questions/103359/how-to-create-a-uuid-in-bash
Calphool

1
@JoeRounceville - Я не мав на увазі, що рішенням було саме SecureBoot - хоча він підтримує сертифікати, що підписуються самостійно, - а його метод . Але він використовує API, запропонований прошивкою системи - і будь-яка система UEFI матиме стільки UUID, скільки вам може знадобитися вже налаштування в назві кожної змінної прошивки - дивіться мою відповідь. Крім того, вам не потрібно жодної програми - або bash- для створення UUID на будь-якому Linux. cat /proc/sys/kernel/random/uuid.
mikeserv

Відповіді:


21

Як щодо цих двох:

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

Потім ви можете комбінувати їх і хешировать їх:

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

Щоб видалити штрих, додайте ще одну трубу:

$ 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

Як в своїй відповіді вказує @mikeserv , назва інтерфейсу може змінюватися між черевиками. Це означає, що те, що є eth0 сьогодні, може бути eth1 завтра, тож якщо ви привітаєтесь, eth0ви можете отримати іншу MAC-адресу на різних черевиках. Моя система не так поводиться, тому я не можу реально перевірити, але можливі рішення:

  1. Хваляйте HWaddrна виході, ifconfigале зберігайте їх усі, а не лише той, що відповідає конкретному NIC. Наприклад, у мене в системі:

    $ 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  

    Захопивши обидва MAC-адреси та передавши їх sha256sum, ви маєте змогу отримати унікальне та стабільне ім’я, незалежно від того, який NIC називається:

    $ 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    

    Зауважте, що хеш відрізняється від наведеного вище, оскільки я передаю обидві MAC адреси, повернуті ifconfigдо sha256sum.

  2. Натомість створіть хеш на основі UUID ваших жорстких дисків:

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

приємно, але як позбутися задніх тире '-'?
uray

@ user77710 див. оновлену відповідь.
terdon

1
Я думаю, що cpuid гірший ... wikipedia.org/wiki/cpuid
mikeserv

@mikeserv ах, так, справді, я бачу ваш погляд. Спасибі, відповідь відредаговано.
terdon

Створює однаковий ідентифікатор для всіх гостьових ОС на одному хості.
Nitinkumar Ambekar

23

По-перше, зауважте, що CPUID, безумовно, не є загальнодоступним однозначним ідентифікаційним маркером для будь-якої системи пізніше, ніж Intel Pentium III. Хоча хеширование його з MAC-адресами, безумовно, може призвести до унікальних маркерів, це пов’язано лише з унікальними якостями самих MAC, а CPUID - у цьому випадку не що інше, як випадкове. Більше того, отриманий хеш, швидше за все, не буде більш унікальним, ніж UUID материнської плати, і це набагато простіше отримати, і процес набагато менше схильний до помилок. З wikipedia.org/wiki/cpuid :

EAX = 3 : Серійний номер процесора

Дивіться також: Pentium III § Суперечка з питань конфіденційності

Це повертає серійний номер процесора. Серійний номер процесора був представлений на Intel Pentium III, але через проблеми конфіденційності ця функція більше не застосовується на більш пізніх моделях (біт функції PSN завжди очищається). Ця функція також забезпечує процесори Efficeon і Crusoe Transmeta. Однак процесори AMD не застосовують цю функцію в жодних моделях процесорів.

Ви можете переглянути розібраний cpuid самостійно, зробивши cat /proc/cpuinfoчи навіть просто lscpu.

Ви отримуєте всі MAC-адреси мережевих інтерфейсів, розпізнаваних ядром Linux, я думаю:

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

Цей список може бути необхідним відфільтрувати, якщо він може містити віртуальні мікросхеми із випадково генерованими MAC. Ви можете зробити це за допомогою прапорів у виклику ipбезпосередньо. Дивіться ip a helpінформацію про те, як це зробити.

Також зауважте, що ця проблема не є унікальною, ipі її також слід вирішувати, якщо ви користуєтесь ifconfig, але з нею можна надійніше впоратися ip- що є частиною iproute2мережевого набору і активно підтримується - ніж воно може ifconfig- з членом з net-toolsпакета і останнього побачила Linux релізу в 2001 році . Зважаючи на зміну особливостей ядра з моменту останнього випуску, ifconfigвідомо, що неправильно повідомляють про деякі прапори мережевих функцій, і його використання слід уникати, якщо це можливо.

Зрозумійте, однак, що фільтрування за назвою інтерфейсу ядра eth[0-9]не є надійним засобом цього, оскільки вони можуть змінюватися, виходячи з порядку їх паралельного виявлення в udevпроцесі завантаження. Докладніше про це див. У передбачуваних мережевих іменах .

Оскільки dmidecodeце не встановлено в моїй системі, я спершу думав хешувати список серіалів на жорсткому диску, створених на зразок:

lsblk -nro SERIAL

Зробіть lsblk --helpпевні підказки щодо уточнення цього списку - скажімо, за типом диска. Також врахуйте lspciта / або lsusbможливо.

Поєднувати їх легко:

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

Після того, як ви повідомили мені, що ви керуєте ресурсами користувача на своєму кінці їх унікальних ідентифікаторів, і на жорсткі диски не можна покластися на існування, я подумав змінити свій кейс.

Зважаючи на це, я знову заглянув у файлову систему і знайшов /sys/class/dmi/idпапку. Я перевірив кілька файлів:

cat ./board_serial ./product_serial

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

Однак це здається досить непоганим, але результат не публікую:

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

Я очікую, що там dmidecodeвсе одно потрапляє значна частина його інформації, і насправді це виглядає так . Відповідно, man dmidecodeви також можете значно спростити використання цього інструменту, вказавши аргумент:

dmidecode -s system-uuid

Але ще простіше, але ви можете просто прочитати файл. Зауважте, що саме цей файл спеціально ідентифікує материнську плату. Ось уривок з виправлення ядра 2007 року, який спочатку реалізував цей експорт у /sysfsвіртуальну файлову систему:

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

Ви можете використовувати ці дані самостійно для ідентифікації системи - якщо материнської плати достатньо. Але ви можете комбінувати цю інформацію з MAC системи так само, як я продемонстрував, що ви можете робити з жорсткими дисками:

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

Ядро Linux також може генерувати UUID для вас:

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

Або:

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

Звичайно, це генерується випадковим чином , і ви повинні переосмислити присвоєння ідентифікаційного номера , але це приблизно так само просто , як він отримує , щоб отримати по крайней мере. І це повинно бути досить солідно, якщо ви зможете знайти засіб, щоб зафіксувати його.

Нарешті, в системах UEFI це зробити набагато простіше - оскільки кожна змінна середовище програмного забезпечення EFI включає свій власний UUID. Змінна середовища {Platform,}LangCodes-${UUID}повинна бути присутнім у кожній системі UEFI, повинна зберігати перезавантаження та навіть більшість оновлень та модифікацій мікропрограмного забезпечення, а будь-яка система Linux із efivarfsзавантаженим модулем може перелічувати будь-які або обидва імена просто так:

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

Старіша форма - LangCodes-${UUID}мабуть, тепер застаріла , а в нових системах має бути, PlatformLangCodes-${UUID}але, згідно з специфікаціями, те чи інше повинно бути присутнім у кожній системі УЄФІ. Не доклавши зусиль, ви можете визначити власні постійні перезавантаження стійких змінних і, можливо, більше використовувати таким чином генератор UUID ядра. Якщо вам цікаво, загляньте в efitools .


у нього навіть немає жорсткого диска або будь-якого диска, що працює, його майнінг, якщо ви не знаєте, що це таке, дивіться. Ця віртуальна машина diit.cz/sites/default/files/images/3988/… віртуальна машина не може запускати 6 GPU на одному материнська плата
uray

так чи інакше, він ніколи не повинен використовувати будь-яке випадкове число, оскільки воно перемагає цілі послідовного іменування машини, оскільки вони завантажують ідентифікатор не повинні змінюватися
uray

@ user77710 - Данг, чоловіче, ця річ класна. Це одна машина? Напевно, ти маєш рацію, але це може бути можливим за допомогою комбінації XDMX та Chromium - деяких розповсюджених графічних матеріалів. У всякому разі, це не мало значення - у мене це було назад. Хто б хотів вибити себе з своїх грошей? Я думав про щось, що стосується ліцензування програмного забезпечення, чи щось таке - ти робиш банківські рахунки.
mikeserv

У них кілька хитромудрих хитрощів, які ви потрапили туди, +1.
terdon

@terdon - комплімент дуже цінується, але, здебільшого, це не хитрощі. ip2спеціально розроблений для розбору, і, можливо, я не роблю це досить добре - я підозрюю, що те саме можна зробити майже без нього grep/sed. Напевно, те саме можна було б зробити так само легко udevadm. І кожне ім'я змінної середовища EFI створене для унікального визначення саме таких ситуацій.
mikeserv

19

Багато сучасних дистрибутивів надсилають файл, /etc/machine-idщо містить, мабуть, унікальну шістнадцяткову рядок з 32 символами. Він походить із systemd, де на сторінці розміщено більше інформації та може відповідати вашим цілям.


+1, @XZS, ви також можете додати відповідну інформацію з URL-адреси тут.
Рамеш

1
Це добре, і я знайшов подібну інформацію і майже її використав ... але я вже був прихильний до іншого маршруту. Проте слід зазначити, що це dbus, на мій погляд, є специфічним і змінюється, якщо операційна система буде стерта / перевстановлена.
mikeserv

Це дуже дивовижно.
GeneCode

5

На багатьох машинах Linux файл /var/lib/dbus/machine-idмістить унікальний ідентифікатор для кожного дистрибутива Linux і до нього можна отримати доступ за допомогою виклику dbus_get_local_machine_id(). Це, мабуть, те саме, що було /etc/machine-idсказано вище. Він працює і на віртуальних установках Linux. Я перевірив це на поточних дистрибутивах Ubuntu, SuSE та CentOS.


1
У Fedora 19 + 20 цей файл не існує. Це тут : /etc/machine-id.
slm

Можливо, я був недостатньо зрозумілий. Моя думка полягала в тому, що якщо ви не знайдете його в одному місці, подивіться в інше. Або написати власну програму за допомогою виклику функції.
ранкені

0

Вам потрібен ідентифікатор машини, щоб змінити його при зміні обладнання? Чи використовується ідентифікатор машини, щоб захистити щось? Найкращий спосіб, на який я вважаю, мати "послідовний" ідентифікатор машини - це зберігати випадкову рядок десь у системі, і таким чином, якщо зміниться будь-яке обладнання, то ідентифікатор машини також не зміниться. Це також добре для віртуалізованих систем, де апаратний доступ обмежений, а ідентифікатор MAC 00: 00: 00: 00

Спробуйте щось на зразок цього сценарію sh, щоб створити та отримати ідентифікатор:

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

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

cat $FILE;

Оскільки ваш /dev/urandomLinux так чи інакше вказує, ви можете просто робити те, cat /proc/sys/kernel/random/uuid >$FILEщо випадковим чином генерує правильно відформатований UUID при кожному прочитаному. Проте будь-яке збереження, застосоване на диску, підлягає видаленню, і, якщо це прийнятно та dbusвстановлено, ви, мабуть, зробите так, як запропонував @XZS.
mikeserv

0

Інші відповіді дають ряд способів вилучення ідентифікаторів із апаратного забезпечення. Ви можете вирішити використовувати один апарат в якості ідентифікатора або кілька. Це проблематично, якщо вам потрібно довільно поміняти або замінити частини обладнання.

Деякі люди замість цього можуть зберігати створений ідентифікатор id на своєму жорсткому диску (або використовувати UUID), але жорсткі диски можуть бути клоновані.

Модулі TPM та захищена завантажувальна система можуть забезпечити прив'язку материнської плати та іншого обладнання до встановлення на жорсткий диск.

У цих випадках завжди трохи простіше, якщо ви даєте більше інформації про те, що ви хочете досягти.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.