일관된 머신 고유 ID 생성


20

우리는 uuuidgen과 같은 각 PC에 대해 고유 한 ID를 생성 할 수 있지만 하드웨어 변경이없는 한 절대 변경되지 않습니까? CPUID와 MACADDR을 병합하고 해시하여 일관된 ID를 생성하는 것에 대해 생각하고 있었지만 bash 스크립트를 사용하여 구문 분석하는 방법을 모르겠습니다.

dmidecode -t 4 | grep ID

ifconfig | grep ether

그런 다음 16 진수 문자열을 결합하고 고정 길이 16 진수 문자열을 만들려면 sha1 또는 md5를 사용하여 해시해야합니다.
그 출력을 어떻게 파싱 할 수 있습니까?


4
이 방법을 사용하여 해결하려는 문제는 정확히 무엇입니까?
Darkhogg

1
나는 Darkhogg와 함께 있습니다. 오늘날 이런 종류의 일을 시도하는 것은 일반적으로 나쁜 생각입니다. 가상화는 소프트웨어를 물리적 하드웨어에 무의미한 방식으로 바인딩하는 관행을 만들었습니다. 요구 사항 (Darkhogg가 추진하고있는 사항)을 면밀히 검토하면 일반적으로 더 나은 답변이 있습니다.
Calphool

4
내가 기계에 소프트웨어를 결합하려면이 옵션을 사용 해달라고, 그것은 필요, 내가 유일하게 자신의 하드웨어 ID를 사용하여 식별해야하는 대신 수동으로 장비의 수천 이름의 클라우드 제어 및 모니터링 서비스에 자신을 식별하는 것을 리눅스 광산 장비입니다
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를 생성 하는 데 응용 프로그램이 필요하지 않습니다 . 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 일 수 있음을 의미하므로 grep 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 주소를 모두 가져 와서 전달하면 sha256sumNIC가 무엇인지에 관계없이 고유하고 안정적인 이름을 얻을 수 있습니다.

    $ 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가 더 나쁜 것
같아

@ mikeserv 아, 그래, 당신의 요점을 참조하십시오. 감사합니다. 답변이 수정되었습니다.
terdon

동일한 호스트에서 모든 게스트 OS에 대해 동일한 ID를 생성합니다.
Nitinkumar Ambekar

23

첫째, CPUID는 Intel Pentium III 이후의 시스템에서 일반적으로 액세스 가능한 고유 식별 마커가 아닙니다 . MAC 주소로 해시하는 것은 확실히 고유 한 마커로 이어질 수 있지만, 이는 MAC 자체의 고유 한 특성 때문이며,이 경우 CPUID는 정황에 지나지 않습니다. 또한 결과로 생성되는 해시는 마더 보드의 UUID보다 더 독창적이지 않으며 검색하기가 훨씬 쉽고 프로세스 오류가 훨씬 적습니다. 에서 wikipedia.org/wiki/cpuid :

EAX = 3 : 프로세서 일련 번호

참고 : Pentium III § 개인 정보 보호 문제에 대한 논쟁

프로세서의 일련 번호를 반환합니다. 프로세서 일련 번호는 Intel Pentium III에 도입되었지만 개인 정보 보호 문제로 인해이 기능은 이후 모델에서 더 이상 구현되지 않습니다 (PSN 기능 비트는 항상 지워짐). Transmeta의 Efficeon 및 Crusoe 프로세서도이 기능을 제공합니다. 그러나 AMD CPU는 CPU 모델에서이 기능을 구현하지 않습니다.

구문 분석 된 CPU를 직접 cat /proc/cpuinfo또는 심지어 수행하여 볼 수도 있습니다 lscpu.

이것은 리눅스 커널이 인식하는 네트워크 인터페이스에 대한 모든 MAC 주소를 얻는다.

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

임의로 생성 된 MAC을 가진 가상 nic를 포함 할 수있는 경우이 목록을 필터링해야합니다. ip직접 호출 할 때 플래그를 사용하여이 작업을 수행 할 수 있습니다 . ip a help그렇게하는 방법에 대한 정보는 참조하십시오 .

또한이 문제는 고유하지 않으며 , ip사용하는 경우에도 처리해야 ifconfig하지만 ip, iproute2네트워크 제품군의 일부이며 ifconfig구성원 인 경우보다 더 안정적으로 처리 할 수 있습니다. 의 net-tools패키지 리눅스와 마지막 톱 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

당신이 나에게 당신이 그들의 고유 한 ID에 당신의 자원을 키우고 있다고 나에게 알려 주었고, 하드 디스크는 존재를 믿을 수 없어 내 압정을 바꿀 것으로 생각했다.

그 점을 고려하여 파일 시스템을 다시 살펴보고 /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

물론, 그것은 무작위로 생성되며 ID 할당을 다시 생각해야하지만 최소한 쉽게 얻을 수 있습니다. 그리고 키를 넣을 방법을 찾을 수 있다면 상당히 견고해야합니다.

마지막으로, UEFI 시스템에서는 모든 EFI 펌웨어 환경 변수에 자체 UUID가 포함되어 있으므로 훨씬 쉽게 수행 할 수 있습니다. 환경 변수 {Platform,}LangCodes-${UUID}는 모든 UEFI 시스템에 존재해야하며 재부팅 및 대부분의 펌웨어 업그레이드 및 수정을 유지해야 하며, efivarfs모듈이로드 된 Linux 시스템은 다음과 같이 간단하게 하나 또는 둘 모두의 이름을 나열 할 수 있습니다.

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

오래된 형태는 - LangCodes-${UUID}분명히되어 지금은 사용되지 않는 , 그리고 새로운 시스템에 있어야 PlatformLangCodes-${UUID}사양, 하나 또는 다른 모든 UEFI 시스템에 존재해야한다에 따라,하지만. 약간의 노력만으로도 재부팅 영속 변수를 직접 정의하고 커널 UUID 생성기를 더 많이 활용할 수 있습니다. 관심이 있다면 efitools를 살펴 보십시오 .


diit.cz/sites/default/files/images/3988 / ... 가상 머신은 단일 GPU에서 6 개의 GPU를 실행할 수 없습니다. 마더 보드
Uray

어쨌든 ID를 변경하지 않아야 부팅 할 때 시스템 이름을 구성하는 목적을 능가하는 임의의 숫자를 절대 사용해서는 안됩니다.
uray

@ user77710-댕, 그거 멋지다. 하나의 기계입니까? 아마도 당신이 옳을 수도 있지만, 일부 분산 그래픽 자료 인 XDMX와 Chromium의 일부 조합으로 가능할 수 있습니다. 어쨌든, 그것은 중요하지 않습니다-나는 그것을 뒤로 가지고있었습니다. 누가 그들의 돈을 이기고 싶어할까요? 소프트웨어 라이센스 또는 무언가를 생각하고있었습니다. 은행 계좌를 사용하고 있습니다.
mikeserv

그들은 당신이 거기에있어 몇 가지 멋진 트릭입니다 +1.
terdon

@ terdon-칭찬은 대단히 높이 평가되지만, 대부분 트릭은 아닙니다. ip2특히 구문 분석되도록 설계되었으며 충분히 잘 수행하지 않았을 수 있습니다 grep/sed. 거의 없이도 동일한 작업을 수행 할 수 있다고 생각합니다 . 아마 같은 방법으로 쉽게 수행 할 수 있습니다 udevadm. 또한 각 EFI 환경 변수 이름은 이러한 상황에 맞게 고유하게 식별되도록 설계되었습니다.
mikeserv

19

많은 현대 배포판에는 /etc/machine-id아마도 가장 고유 한 16 진 32 자 문자열이 포함 된 파일 이 제공됩니다. 맨 페이지에 자세한 정보가 있는 systemd에서 시작되었으며 사용자의 목적에 적합 할 수 있습니다.


+1, @XZS, 여기 URL에서도 관련 정보를 추가 할 수 있습니다.
Ramesh

1
이것은 좋으며 비슷한 정보를 발견하고 거의 사용했습니다 ...하지만 이미 다른 경로에 헌신했습니다. 그럼에도 불구하고 이것은 dbus운영 체제를 지우거나 다시 설치하면 구체적이며 변경됩니다.
mikeserv

이것은 정말 대단합니다.
GeneCode

5

많은 Linux 시스템에서 파일 /var/lib/dbus/machine-id은 각 Linux 배포에 대한 고유 ID를 포함하며에 대한 호출을 통해 액세스 할 수 있습니다 dbus_get_local_machine_id(). 이것은 아마도 /etc/machine-id위에서 언급 한 것과 같습니다. 가상 Linux 설치에서도 작동합니다. 현재 Ubuntu, SuSE 및 CentOS 배포판에서 확인했습니다.


1
Fedora 19 + 20에는 해당 파일이 없습니다. 여기 있습니다 : /etc/machine-id.
slm

아마도 나는 충분히 명확하지 않았다. 내 요점은 당신이 한 곳을 찾지 못하면 다른 곳을 보라는 것입니다. 또는 함수 호출을 사용하여 자신의 프로그램을 작성하십시오.
rankeney

0

하드웨어가 변경 될 때 변경하려면 머신 ID가 필요합니까? 컴퓨터 ID를 사용하여 무언가를 보호하고 있습니까? "일관된"컴퓨터 ID를 갖는 가장 좋은 방법은 시스템 어딘가에 임의의 문자열을 저장하는 것이며 하드웨어가 변경되면 컴퓨터 ID도 변경되지 않습니다. 하드웨어 액세스가 제한되고 MAC ID가 00 : 00 : 00 : 00 인 가상화 시스템에도 좋습니다.

이 sh 스크립트와 같은 것을 시도하여 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;

/dev/urandom어쨌든 Linux를 나타내 므로 cat /proc/sys/kernel/random/uuid >$FILE모든 읽기에서 올바르게 형식이 지정된 UUID를 임의로 생성 할 수 있습니다 . 그래도 디스크 구현 지속성은 삭제 될 수 있으며, 허용되고 설치 dbus되어 있다면 @XZS가 제안한대로 수행해야합니다.
mikeserv

0

다른 답변은 하드웨어에서 ID를 추출하는 여러 가지 방법을 제공합니다. 하나의 하드웨어를 식별자 또는 다수로 사용하기로 결정할 수 있습니다. 하드웨어를 임의로 교체하거나 교체해야하는 경우 문제가됩니다.

일부 사람들은 대신 생성 된 ID를 하드 드라이브에 저장하거나 UUID를 사용하지만 하드 드라이브를 복제 할 수 있습니다.

TPM 모듈 및 보안 부팅은 마더 보드 및 기타 하드웨어를 하드 드라이브에 설치하여 바인딩하는 수단을 제공 할 수 있습니다.

당신이 달성하고자하는 것에 대해 더 많은 정보를 제공하면이 경우에는 항상 조금 더 쉽습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.