Во-первых, обратите внимание, что CPUID определенно не является общедоступным маркером однозначной идентификации для любой системы, более поздней, чем Intel Pentium III. Хотя хэширование его с MAC-адресами, безусловно, может привести к уникальным маркерам, это связано только с уникальными качествами самих MAC, и CPUID в этом случае является не чем иным, как косвенным. Более того, результирующий хеш, скорее всего, не будет более уникальным, чем UUID материнской платы, и его гораздо проще получить, а процесс менее подвержен ошибкам. Из wikipedia.org/wiki/cpuid :
EAX = 3 : серийный номер процессора
Смотрите также: Pentium III § Спор о проблемах конфиденциальности
Это возвращает серийный номер процессора. Серийный номер процессора был введен на Intel Pentium III, но из-за соображений конфиденциальности эта функция больше не реализована на более поздних моделях (бит функции PSN всегда сбрасывается). Процессоры Transmeta Efficeon и Crusoe также предоставляют эту функцию. Процессоры AMD, однако, не реализуют эту функцию ни в каких моделях процессоров.
Вы можете просмотреть разобранный процессор самостоятельно, выполнив 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}
но, согласно спецификации, одна или другая должна присутствовать в каждой системе UEFI. Без особых усилий вы можете определить свои собственные постоянные переменные перезагрузки и, возможно, более активно использовать генератор UUID ядра таким образом. Если интересно, загляните в efitools .