По-перше, зауважте, що 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 .