generar una identificación única de máquina consistente

20

¿Podemos generar una identificación única para cada PC, algo así como uuuidgen, pero nunca cambiará a menos que haya cambios de hardware? Estaba pensando en fusionar CPUID y MACADDR y hacerlos hash para generar una ID coherente, pero no tengo idea de cómo analizarlos usando el script bash, lo que sé es cómo puedo obtener CPUID de

dmidecode -t 4 | grep ID

y

ifconfig | grep ether

entonces necesito combinar esas cadenas hexadecimales y hacerlas hash usando sha1 o md5 para crear una cadena hexadecimal de longitud fija.
¿Cómo puedo analizar esa salida?

uray
fuente
44
¿Cuál es exactamente el problema que estás tratando de resolver usando este método?
Darkhogg
1
Estoy con Darkhogg. Generalmente es una mala idea tratar de hacer este tipo de cosas hoy en día. La virtualización ha hecho que la práctica de vincular el software al hardware físico sea algo inútil. Por lo general, hay una mejor respuesta si examina de cerca sus requisitos (que es a lo que Darkhogg está conduciendo).
Calphool
44
No uso esto para vincular un software a una máquina, es una plataforma de minería de Linux que necesita identificarse para el servicio de control y monitoreo en la nube, en lugar de nombrar miles de plataformas manualmente, necesito identificarlas de manera única utilizando su ID de hardware
uray
1
@ user77710: Si ese es el caso, ¿realmente le importa el hardware? ¿Por qué no solo generar un UUID en la máquina si no existe? Ese es el punto de un UUID: son universalmente únicos (sus probabilidades de superposición son astronómicamente improbables). serverfault.com/questions/103359/how-to-create-a-uuid-in-bash
Calphool
1
@JoeRounceville: no quise decir que SecureBoot en sí era la solución, aunque admite certificados autofirmados, sino su método . Pero utiliza una API ofrecida por el firmware del sistema, y cualquier sistema UEFI tendrá tantos UUID como pueda necesitar ya configurados en el nombre de cada variable de firmware. Vea mi respuesta. Además, no necesita ninguna aplicación - o bash- para generarle un UUID en ningún linux. cat /proc/sys/kernel/random/uuid.
mikeserv

Respuestas:

21

¿Qué tal estos dos:

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

Luego puede combinarlos y hacerlos hash con:

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

Para eliminar el guión final, agregue una tubería más:

$ 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

Como @mikeserv señala en su respuesta , el nombre de la interfaz puede cambiar entre las botas. Esto significa que lo que es eth0 hoy podría ser eth1 mañana, por lo que si lo eth0desea puede obtener una dirección MAC diferente en diferentes botas. Mi sistema no se comporta de esta manera, así que realmente no puedo probar, pero las posibles soluciones son:

  1. Busque HWaddren la salida de, ifconfigpero conserve todos ellos, no solo el correspondiente a una NIC específica. Por ejemplo, en mi sistema tengo:

    $ 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  

    Al tomar ambas direcciones MAC y pasarlas sha256sum, debería poder obtener un nombre único y estable, independientemente de qué NIC se llame qué:

    $ 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    

    Tenga en cuenta que el hash es diferente de los anteriores porque estoy pasando ambas direcciones MAC devueltas ifconfiga sha256sum.

  2. En su lugar, cree un hash basado en los UUID de su (s) disco (s) duro (s):

    $ blkid | grep -oP 'UUID="\K[^"]+' | sha256sum | awk '{print $1}'
    162296a587c45fbf807bb7e43bda08f84c56651737243eb4a1a32ae974d6d7f4
terdon
fuente
es agradable, pero ¿cómo deshacerse del guión final '-'?
uray
@ user77710 ver respuesta actualizada.
terdon
1
Supongo que cpuid es peor ... wikipedia.org/wiki/cpuid
mikeserv
@mikeserv ah, sí, sí, entiendo tu punto. Gracias, respuesta editada.
terdon
Genera la misma ID para todos los SO invitados en el mismo host.
Nitinkumar Ambekar
23

En primer lugar, tenga en cuenta que el CPUID definitivamente no es un marcador de identificación único comúnmente accesible para cualquier sistema posterior a un Intel Pentium III. Si bien el hashing con direcciones MAC puede conducir a marcadores únicos, esto se debe solo a las cualidades únicas de los MAC y el CPUID en ese caso no es más que circunstancial. Además, es probable que el hash resultante no sea más exclusivo que el UUID de la placa base, y eso es mucho más fácil de recuperar y el proceso es mucho menos propenso a errar. Desde wikipedia.org/wiki/cpuid :

EAX = 3 : Número de serie del procesador

Ver también: Pentium III § Controversia sobre cuestiones de privacidad

Esto devuelve el número de serie del procesador. El número de serie del procesador se introdujo en Intel Pentium III, pero debido a problemas de privacidad, esta característica ya no se implementa en modelos posteriores (el bit de la función PSN siempre se borra). Los procesadores Efficeon y Crusoe de Transmeta también proporcionan esta característica. Sin embargo, las CPU AMD no implementan esta característica en ningún modelo de CPU.

Puede ver un cpuid analizado usted mismo haciendo cat /proc/cpuinfoo incluso simplemente lscpu.

Creo que esto le proporciona todas las direcciones MAC para las interfaces de red reconocidas por el kernel de Linux:

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

Puede ser necesario filtrar esa lista si puede incluir nics virtuales con MAC generados aleatoriamente. Puede hacer esto con banderas en la llamada a ipdirectamente. Consulte ip a helppara obtener información sobre cómo hacerlo.

También tenga en cuenta que este problema no es exclusivo ipy también debe abordarse si lo usa ifconfig, pero que puede manejarse de manera más confiable ip, que es parte del iproute2conjunto de redes y se mantiene activamente, de lo que puede hacerlo ifconfig, que es un miembro del net-toolspaquete y vimos por última vez un lanzamiento de Linux en 2001 . Debido a las características cambiantes en el núcleo desde su última versión, ifconfigse sabe que informa erróneamente algunos indicadores de características de red y su uso debe evitarse si es posible.

Sin embargo, comprenda que filtrar con nombres de interfaz de kernel como eth[0-9]no es un medio confiable para hacerlo, ya que estos pueden cambiar según su orden de detección en paralelo udevdurante el proceso de arranque. Consulte los nombres de red predecibles para obtener más información al respecto.

Como dmidecodeno está instalado en mi sistema, al principio pensé en hacer un hash de una lista de seriales de disco duro generados como:

lsblk -nro SERIAL

Haga lsblk --helpalgunas pistas para refinar esa lista, por tipo de disco, por ejemplo. También considere lspciy / o lsusbtal vez.

Combinarlos es fácil:

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

Como me ha informado, está poniendo los recursos del usuario de su lado en sus identificadores únicos, y no se puede confiar en que existan los discos duros, pensé que cambiaría mi táctica.

Dicho esto, busqué nuevamente en el sistema de archivos y encontré la /sys/class/dmi/idcarpeta. Revisé algunos de los archivos:

cat ./board_serial ./product_serial

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

Sin embargo, este parece ser bastante bueno, pero no publicaré el resultado:

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

Supongo que de ahí es donde dmidecodeobtiene gran parte de su información de todos modos y, de hecho, se parece . Según man dmidecodeusted, también puede simplificar mucho el uso de esa herramienta especificando el argumento:

dmidecode -s system-uuid

Sin embargo, aún más simple, solo puede leer el archivo. Tenga en cuenta que este archivo en particular identifica específicamente una placa base. Aquí hay un extracto del parche del kernel de 2007 que implementó originalmente estas exportaciones al /sysfssistema de archivos virtual:

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

Es posible que pueda usar esos datos solo para identificar el sistema, si la placa base es suficiente. Pero puede combinar esta información con los MAC del sistema de la misma manera que demostré que podría hacerlo con los discos duros:

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

El kernel de Linux también puede generar UUID para usted:

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

De acuerdo, es generado de forma aleatoria y se tendrá que replantear asignación de ID, pero es casi tan fácil como se pone a conseguir por lo menos. Y debería ser bastante sólido si puedes encontrar un medio para teclearlo.

Por último, en los sistemas UEFI esto es mucho más fácil de hacer, ya que cada variable de entorno de firmware EFI incluye su propio UUID. La variable de entorno {Platform,}LangCodes-${UUID}debe estar presente en todos los sistemas UEFI, debe persistir los reinicios e incluso la mayoría de las actualizaciones y modificaciones de firmware, y cualquier sistema Linux con el efivarfsmódulo cargado puede enumerar uno o ambos nombres simplemente como:

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

La forma más antigua, LangCodes-${UUID}aparentemente ahora está en desuso , y en los sistemas más nuevos debería estar PlatformLangCodes-${UUID}, pero, según las especificaciones, uno u otro debería estar presente en cada sistema UEFI. Con poco esfuerzo, puede definir sus propias variables persistentes de reinicio, y tal vez hacer más uso del generador de UUID del núcleo de esa manera. Si está interesado, busque efitools .

mikeserv
fuente
ni siquiera tiene disco duro o ningún disco en ejecución, su plataforma de minería, si no sabe lo que es, vea este diit.cz/sites/default/files/images/3988/… la máquina virtual no puede ejecutar 6 GPU en un solo motherboard
uray
De todos modos nunca debe usar cualquier número al azar, ya que venció el propósito de nombrar consistentemente la máquina, ya que arrancan el ID no debe cambiar
uray
@ user77710 - Dang, hombre, eso es genial. ¿Esa es una máquina? Probablemente tenga razón, pero podría ser posible con algún combo de XDMX y Chromium, algunas cosas de gráficos distribuidos. De todos modos, no importaría, lo tenía al revés. ¿Quién querría ganarse su dinero? Estaba pensando en algo de licencias de software o algo así: estás haciendo cuentas bancarias.
mikeserv
Son algunos trucos ingeniosos que tienes allí, +1.
terdon
@terdon: el cumplido es muy apreciado, pero, en su mayor parte, no son trucos. ip2está específicamente diseñado para ser analizado, y puede ser que no lo estoy haciendo lo suficientemente bien; sospecho que se puede hacer lo mismo casi sin él grep/sed. Probablemente lo mismo podría hacerse tan fácilmente con udevadm. Y cada nombre de variable de entorno EFI está diseñado para ser identificado de manera única para exactamente este tipo de situaciones.
mikeserv
19

Muchas distribuciones modernas envían un archivo que /etc/machine-idcontiene una cadena hexadecimal de 32 caracteres muy probablemente única. Se origina en systemd, donde una página de manual tiene más información , y puede ser apropiada para su propósito.

XZS
fuente
+1, @XZS, también puede agregar la información relevante de la URL aquí.
Ramesh
1
Esto es bueno, y encontré información similar y casi la usé ... pero ya estaba comprometido con una ruta diferente. Aún así, debe tenerse en cuenta que esto es dbusespecífico, creo, y cambia si se borra / reinstala un sistema operativo.
mikeserv
Esto es bastante increíble.
GeneCode
5

En muchas máquinas Linux, el archivo /var/lib/dbus/machine-idcontiene una identificación única para cada distribución de Linux y se puede acceder mediante una llamada a dbus_get_local_machine_id(). Esto es probablemente lo mismo que lo /etc/machine-idmencionado anteriormente. Funciona también en instalaciones virtuales de Linux. Lo he comprobado en las distribuciones actuales de Ubuntu, SuSE y CentOS.

Rankeney
fuente
1
En Fedora 19 + 20 ese archivo no existe. Es aquí: /etc/machine-id.
slm
Quizás no fui lo suficientemente claro. Mi punto era que si no lo encuentras en un lugar, busca en el otro. O escriba su propio programa usando la llamada de función.
Rankeney
0

¿Necesita cambiar la ID de la máquina cuando cambia el hardware? ¿Se está utilizando la identificación de la máquina para proteger algo? Creo que la mejor manera de tener una ID de máquina "consistente" es almacenando una cadena aleatoria en algún lugar del sistema y de esa manera si alguno de los cambios de hardware, entonces la ID de la máquina tampoco cambiará. Esto también es bueno para sistemas virtualizados donde el acceso de hardware está restringido y la ID de MAC es 00: 00: 00: 00

Pruebe algo como este script sh para crear y obtener la 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;
ub3rst4r
fuente
Como /dev/urandomindica Linux de todos modos, puede hacer lo cat /proc/sys/kernel/random/uuid >$FILEque genera aleatoriamente un UUID formateado correctamente en cada lectura. Aún así, cualquier persistencia implementada en el disco está sujeta a eliminación y, siempre que sea aceptable y dbusesté instalado, probablemente debería hacer lo que @XZS ha sugerido.
mikeserv
0

Las otras respuestas ofrecen varias formas de extraer identificadores del hardware. Podría decidir usar una pieza de hardware como identificador o muchas. Esto es problemático si necesita intercambiar o reemplazar piezas de hardware arbitrariamente.

En cambio, algunas personas pueden almacenar una identificación generada en su disco duro (o usar el UUID), pero los discos duros pueden ser clonados.

Los módulos TPM y el arranque seguro pueden proporcionar un medio para unir la placa base y otro hardware con una instalación en un disco duro.

Siempre es un poco más fácil en estos casos si proporciona más información sobre lo que desea lograr.

jgmjgm
fuente