gerar ID único consistente da máquina

20

Podemos gerar um ID exclusivo para cada PC, algo como uuuidgen, mas ele nunca será alterado a menos que haja alterações de hardware? Eu estava pensando em mesclar CPUID e MACADDR e misturá-los para gerar uma identificação consistente, mas não tenho idéia de como analisá-los usando o script bash, o que sei é como obter o CPUID de

dmidecode -t 4 | grep ID

e

ifconfig | grep ether

então eu preciso combinar essas seqüências de caracteres hexadecimais e usá-las usando sha1 ou md5 para criar uma sequência hexadecimal de comprimento fixo.
Como posso analisar essa saída?

uray
fonte
4
Qual é exatamente o problema que você está tentando resolver usando esse método?
Darkhogg
1
Estou com Darkhogg. Geralmente, é uma má idéia tentar fazer esse tipo de coisa hoje em dia. A virtualização tornou inútil a prática de vincular software a hardware físico. Geralmente, há uma resposta melhor se você examinar atentamente seus requisitos (é para isso que Darkhogg está conduzindo).
Calphool
4
Eu não uso isso para vincular um software de uma máquina, é equipamento de mineração linux que precisam identificar-se ao controle de nuvem e serviços de monitoramento, em vez de nomear milhares de equipamento manualmente, eu preciso identificá-los exclusivamente usando o seu ID hardware
Uray
1
@ user77710: Se for esse o caso, você realmente se importa com o hardware? Por que não gerar apenas um UUID na máquina, caso não exista. Esse é o objetivo de um UUID - eles são universalmente únicos (suas chances de sobreposição são astronomicamente improváveis). serverfault.com/questions/103359/how-to-create-a-uuid-in-bash
Calphool
1
@JoeRounceville - não quis dizer que o SecureBoot era a solução - embora ele suporte certificados autoassinados -, mas sim o método . Mas ele usa uma API oferecida pelo firmware do sistema - e qualquer sistema UEFI terá quantos UUIDs quantos você precisar já estiver configurado no nome de cada variável de firmware - veja minha resposta. Além disso, você não precisa de nenhum aplicativo - ou bash- para gerar um UUID em qualquer Linux. cat /proc/sys/kernel/random/uuid.
precisa saber é o seguinte

Respostas:

21

Que tal esses dois:

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

Você pode então combiná-los e hash-los com:

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

Para remover o traço à direita, adicione mais um tubo:

$ 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 aponta em sua resposta , o nome da interface pode mudar entre as botas. Isso significa que o que é eth0 hoje pode ser eth1 amanhã, portanto, se você eth0desejar, poderá obter um endereço MAC diferente em botas diferentes. Meu sistema não se comporta dessa maneira, então não posso realmente testar, mas as soluções possíveis são:

  1. Grep for HWaddrna saída de, ifconfigmas mantenha todos eles, não apenas o correspondente a uma NIC específica. Por exemplo, no meu sistema, tenho:

    $ 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  

    Ao pegar os dois endereços MAC e transmiti-los sha256sum, você poderá obter um nome único e estável, independentemente da NIC denominada como:

    $ 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    

    Observe que o hash é diferente dos acima, porque estou passando os dois endereços MAC retornados por ifconfigpara sha256sum.

  2. Crie um hash com base nos UUIDs do (s) seu (s) disco (s) rígido (s):

    $ blkid | grep -oP 'UUID="\K[^"]+' | sha256sum | awk '{print $1}'
    162296a587c45fbf807bb7e43bda08f84c56651737243eb4a1a32ae974d6d7f4
terdon
fonte
é bom, mas como se livrar do traço à direita '-'?
Uray
@ user77710 ver resposta atualizada.
terdon
1
Eu acho que o cpuid é pior ... wikipedia.org/wiki/cpuid #
mikeserv
@ mikeserv ah, sim, de fato, entendo o seu ponto. Obrigado, resposta editada.
terdon
Gera o mesmo ID para todos os SOs convidados no mesmo host.
Nitinkumar Ambekar
23

Em primeiro lugar, observe que o CPUID definitivamente não é um marcador de identificação única comumente acessível para qualquer sistema posterior a um Intel Pentium III. Embora o hash com endereços MAC possa levar a marcadores únicos, certamente, isso se deve apenas às qualidades únicas dos próprios MACs e o CPUID, nesse caso, nada mais é do que circunstancial. Além disso, o hash resultante provavelmente não será mais exclusivo que o UUID da placa-mãe, e isso é muito mais fácil de recuperar e o processo é muito menos propenso a erros. Em wikipedia.org/wiki/cpuid :

EAX = 3 : Número de série do processador

Veja também: Pentium III § Controvérsia sobre questões de privacidade

Isso retorna o número de série do processador. O número de série do processador foi introduzido no Intel Pentium III, mas devido a questões de privacidade, esse recurso não é mais implementado em modelos posteriores (o bit do recurso PSN é sempre limpo). Os processadores Efficeon e Crusoe da Transmeta também fornecem esse recurso. As CPUs AMD, no entanto, não implementam esse recurso em nenhum modelo de CPU.

Você pode visualizar uma CPU analisada fazendo cat /proc/cpuinfoou apenas isso lscpu.

Isso fornece a você todos os endereços MAC para as interfaces de rede reconhecidas pelo kernel do Linux, eu acho:

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

Pode ser necessário filtrar essa lista se ela incluir redes virtuais com MACs gerados aleatoriamente. Você pode fazer isso com sinalizadores na chamada para ipdiretamente. Veja ip a helppara obter informações sobre como fazer isso.

Observe também que esse problema não é exclusivo ipe também deve ser tratado se você o usar ifconfig, mas que pode ser tratado com mais segurança ip- que faz parte do iproute2conjunto de redes e é mantido ativamente - do que com ifconfigum membro. do net-toolspacote e vi pela última vez um lançamento do Linux em 2001 . Devido à alteração dos recursos no kernel desde seu último lançamento, ifconfigé conhecido por relatar mal alguns sinalizadores de recursos de rede e seu uso deve ser evitado, se possível.

No entanto, entenda que a filtragem com nomes de interface do kernel eth[0-9]não é um meio confiável de fazê-lo, pois eles podem mudar com base na ordem de detecção em paralelo udevdurante o processo de inicialização. Consulte Nomes de rede previsíveis para obter mais informações.

Como dmidecodenão está instalado no meu sistema, pensei inicialmente em um hash de uma lista de séries de disco rígido geradas como:

lsblk -nro SERIAL

Faça lsblk --helpalgumas dicas sobre como refinar essa lista - por tipo de disco, digamos. Considere também lspcie / ou lsusbtalvez.

Combiná-los é fácil:

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

Como você me informou, você está direcionando os recursos do usuário para seus IDs exclusivos, e não é possível confiar nos discos rígidos, pensei em mudar de ideia.

Considerando isso, olhei novamente para o sistema de arquivos e encontrei a /sys/class/dmi/idpasta. Eu verifiquei alguns dos arquivos:

cat ./board_serial ./product_serial

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

No entanto, este parece ser muito bom, mas não publicarei a saída:

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

Espero que seja lá que dmidecodeconsiga grande parte de suas informações e, de fato, pareça . De acordo com man dmidecodevocê, você também pode simplificar bastante o uso dessa ferramenta especificando o argumento:

dmidecode -s system-uuid

Mais simples ainda, você pode apenas ler o arquivo. Observe que esse arquivo específico identifica especificamente uma placa-mãe. Aqui está um trecho do patch do kernel de 2007 que originalmente implementou essas exportações para o /sysfssistema de arquivos 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);

Você pode usar esses dados sozinho para identificar o sistema - se a placa-mãe for suficiente. Mas você pode combinar essas informações com os MACs do sistema da mesma maneira que demonstrei que você pode fazer com discos rígidos:

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

O kernel do Linux também pode gerar UUIDs para você:

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

Ou:

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

Concedido, é gerado aleatoriamente e você terá que repensar a atribuição de ID, mas é tão fácil quanto conseguir pelo menos. E deve ser bastante sólido se você puder encontrar um meio de digitar isso.

Por fim, nos sistemas UEFI, isso se torna muito mais fácil - pois cada variável de ambiente de firmware EFI inclui seu próprio UUID. A variável de ambiente {Platform,}LangCodes-${UUID}deve estar presente em todos os sistemas UEFI, deve persistir reinicializações e até a maioria das atualizações e modificações de firmware, e qualquer sistema Linux com o efivarfsmódulo carregado pode listar um ou ambos os nomes da maneira mais simples:

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

A forma mais antiga - LangCodes-${UUID}é, aparentemente, agora obsoleto , e em sistemas mais recentes deve ser PlatformLangCodes-${UUID}, mas, de acordo com a especificação, um ou o outro deve estar presente em todos os sistemas UEFI. Com pouco esforço, você pode definir suas próprias variáveis ​​persistentes de reinicialização e talvez fazer mais uso do gerador UUID do kernel dessa maneira. Se estiver interessado, procure efitools .

mikeserv
fonte
ele nem tem disco rígido ou nenhum disco em execução, seu equipamento de mineração, se você não sabe o que é essa máquina virtual diit.cz/sites/default/files/images/3988/…, a máquina virtual não pode executar 6 GPU em uma única placa
uray
de qualquer forma, nunca deve usar qualquer número aleatório como bater o propósito de consistenly nomeando a máquina, como eles arrancar o ID não deve mudar
Uray
@ user77710 - Caramba, cara, isso é legal. Essa é uma máquina? Provavelmente você está certo, mas pode ser possível com alguma combinação de XDMX e Chromium - algumas coisas de gráficos distribuídos. Enfim, não importava - eu tinha isso ao contrário. Quem iria querer se livrar de seu dinheiro? Eu estava pensando em alguma coisa de licenciamento de software ou algo assim - você está fazendo contas bancárias.
Mikeerv
São alguns truques bacanas que você chegou lá, +1.
terdon
@terdon - o elogio é muito apreciado, mas, na maioria das vezes, não são truques. ip2foi projetado especificamente para ser analisado e pode ser que eu não esteja fazendo o suficiente - suspeito que a mesma coisa possa ser feita quase sem grep/sed. Provavelmente o mesmo poderia ser feito com a mesma facilidade udevadm. E cada nome de variável de ambiente EFI foi projetado para ser identificado exclusivamente para esse tipo de situação.
mikeserv
19

Muitas distribuições modernas enviam um arquivo /etc/machine-idcontendo uma sequência hexadecimal de 32 caracteres provavelmente mais exclusiva. É originário do systemd, onde uma página de manual possui mais informações e pode ser apropriada para o seu propósito.

XZS
fonte
+1, @XZS, você também pode adicionar as informações relevantes a partir do URL.
Ramsh
1
Isso é bom, encontrei informações semelhantes e quase as usei ... mas eu já estava comprometido com uma rota diferente. Ainda assim, deve-se notar que isso é dbusespecífico, eu acho, e muda se um sistema operacional for limpo / reinstalado.
mikeserv
Isso é incrível demais.
GeneCode 20/08/18
5

Em muitas máquinas Linux, o arquivo /var/lib/dbus/machine-idcontém um ID exclusivo para cada distribuição Linux e pode ser acessado por uma chamada para dbus_get_local_machine_id(). Provavelmente é o mesmo que o /etc/machine-idmencionado acima. Também funciona em instalações virtuais do Linux. Eu verifiquei nas distribuições atuais do Ubuntu, SuSE e CentOS.

Rankeney
fonte
1
No Fedora 19 + 20, esse arquivo não existe. É aqui: /etc/machine-id.
slm
Talvez eu não tenha sido claro o suficiente. Meu argumento era que, se você não encontrar um lugar, procure no outro. Ou escreva seu próprio programa usando a chamada de função.
rankeney
0

Você precisa que o ID da máquina mude quando o hardware muda? O ID da máquina está sendo usado para proteger alguma coisa? A melhor maneira que acredito ter um ID de máquina "consistente" é armazenando uma sequência aleatória em algum lugar do sistema e, se algum hardware mudar, o ID da máquina também não será alterado. Isso também é bom para sistemas virtualizados nos quais o acesso ao hardware é restrito e o ID MAC é 00: 00: 00: 00

Tente algo como este script sh para criar e obter o 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
fonte
Como seu /dev/urandomindica o Linux de qualquer maneira, você pode fazer o cat /proc/sys/kernel/random/uuid >$FILEque gera aleatoriamente um UUID formatado corretamente em cada leitura. Ainda assim, qualquer persistência implementada em disco está sujeita a exclusão e, desde que aceitável e dbusinstalado, você provavelmente deve fazer o que o @XZS sugeriu.
Mikeerv
0

As outras respostas fornecem várias maneiras de extrair IDs do hardware. Você pode optar por usar um pedaço de hardware como identificador ou muitos. Isso é problemático se você precisar trocar ou substituir peças de hardware arbitrariamente.

Algumas pessoas podem armazenar uma identificação gerada em seu disco rígido (ou usar o UUID), mas os discos rígidos podem ser clonados.

Os módulos TPM e a inicialização segura podem fornecer um meio de vincular a placa-mãe e outro hardware com uma instalação em um disco rígido.

É sempre um pouco mais fácil nesses casos, se você fornecer mais informações sobre o que deseja realizar.

jgmjgm
fonte