web-dev-qa-db-ja.com

一貫したマシン固有IDを生成する

各PCにuuuidgenのような一意のIDを生成できますが、ハードウェアの変更がない限り変更されません。 CPUIDとMACADDRをマージして、それらをハッシュして一貫したIDを生成することを考えていましたが、bashスクリプトを使用してそれらを解析する方法がわかりません。CPUIDを取得するにはどうすればよいですか。

dmidecode -t 4 | grep ID

そして

ifconfig | grep ether

次に、これらの16進文字列を組み合わせ、sha1またはmd5を使用してハッシュして、固定長の16進文字列を作成する必要があります。
どのようにしてその出力を解析できますか?

21
uray

これらの2つはどうですか:

$ 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  -

末尾のダッシュを削除するには、パイプをもう1つ追加します。

$ 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になる可能性があるため、eth0をgrepすると、異なるブートで異なるMACアドレスを取得する可能性があります。私のシステムはこのように動作しないため、実際にはテストできませんが、可能な解決策は次のとおりです。

  1. HWaddrの出力でifconfigのGrepを実行しますが、特定の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アドレスを取得してsha256sumを介して渡すことにより、どのNICが何と呼ばれるかに関係なく)一意で安定した名前を取得できるはずです。

    $ 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    
    

    ifconfigから返された両方のMACアドレスをsha256sumに渡すため、ハッシュは上記のものとは異なります。

  2. 代わりに、ハードドライブのUUIDに基づいてハッシュを作成します。

    $ blkid | grep -oP 'UUID="\K[^"]+' | sha256sum | awk '{print $1}'
    162296a587c45fbf807bb7e43bda08f84c56651737243eb4a1a32ae974d6d7f4
    
22
terdon

まず、CPUIDは間違いなくnotであり、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モデルにもこの機能を実装していません。

cat /proc/cpuinfoまたはlscpuを実行するだけで、解析済みのcpuidを自分で表示できます。

これにより、Linuxカーネルによって認識されるネットワークインターフェイスのすべてのMACアドレスが得られます。

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

ランダムに生成されたMACを持つ仮想NICが含まれている可能性がある場合は、そのリストをフィルタリングする必要がある場合があります。これは、ipへの呼び出しのフラグで直接行うことができます。その方法については、ip a helpを参照してください。

また、この問題はipに固有のものではなく、ifconfigを使用する場合にも対処する必要がありますが、ipでより確実に処理できることに注意してください。 iproute2ネットワークスイート であり、アクティブに維持されます。これは、_ net-toolsパッケージのメンバーであるifconfigを使用する場合よりも =そして最後にLinuxを見た 2001年のリリース 。前回のリリース以降のカーネルの機能の変更により、ifconfig一部のネットワーク機能フラグを誤報告 であることがわかっており、可能であればその使用は避けてください。

ただし、eth[0-9]のようなカーネルインターフェイス名でのフィルタリングは、ブートプロセス中にudevによる並列検出の順序に基づいて変更される可能性があるため、信頼できる方法ではありません。詳しくは 予測可能なネットワーク名 をご覧ください。

dmidecodeがシステムにインストールされていないため、最初に次のように生成されたハードディスクシリアルのリストをハッシュすることを考えました。

lsblk -nro SERIAL

そのリストを調整するための手がかりを得るためにlsblk --helpを実行します-たとえば、ディスクの種類ごとに。また、lspcilsusbを検討してください。

それらを組み合わせるのは簡単です:

{ 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

ただし、もっと単純ですが、ファイルを読み取るだけです。この特定のファイルはマザーボードを特定することに注意してください。以下は、これらのエクスポートを/sysfs仮想ファイルシステムに最初に実装した 2007カーネルパッチ からの抜粋です。

+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の割り当てを再考する必要がありますが、少なくともgetと同じくらい簡単です。そして、それをキーイングする手段を見つけることができれば、それはかなりしっかりしているはずです。

最後に、UEFIシステムでは、すべてのEFIファームウェア環境変数に独自のUUIDが含まれているため、これがはるかに簡単になります。環境変数{Platform,}LangCodes-${UUID}は、すべてのUEFIシステムに存在し、再起動を維持し、さらにmostファームウェアのアップグレードと変更を保持する必要があります。また、efivarfsモジュールがロードされているLinuxシステムは、どちらか一方または両方の名前を次のように単純に:

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

古い形式-LangCodes-${UUID}は明らかに 現在非推奨 であり、新しいシステムではPlatformLangCodes-${UUID}である必要がありますが、仕様によると、いずれかのUEFIシステムにどちらか一方が存在する必要があります。少しの労力で、独自の再起動永続変数を定義できます。そのようにして、カーネルのUUIDジェネレーターをさらに活用できます。興味がある場合は、 efitools を調べてください。

24
mikeserv

最新のディストリビューションの多くはファイルを出荷しています/etc/machine-idは、おそらく一意の16進数の32文字の文字列を含みます。 マンページに詳細情報がある であるsystemdに由来し、目的に適している可能性があります。

21
XZS

多くのLinuxマシンでは、ファイル_/var/lib/dbus/machine-id_には各Linuxディストリビューションの一意のIDが含まれており、dbus_get_local_machine_id()の呼び出しによってアクセスできます。これは、おそらく上記の_/etc/machine-id_と同じです。仮想Linuxインストールでも機能します。現在のUbuntu、SuSE、CentOSディストリビューションで確認しました。

6
rankeney

ハードウェアが変更されたときにマシン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;
0
ub3rst4r

他の答えは、ハードウェアからIDを抽出する多くの方法を提供します。 1つまたは複数のハードウェアを識別子として使用することもできます。これは、ハードウェアの一部を任意に交換または交換する必要がある場合に問題になります。

代わりに、生成されたIDをハードドライブに保存(またはUUIDを使用)する人もいますが、ハードドライブは複製できます。

TPMモジュールとセキュアブートは、マザーボードとその他のハードウェアをハードドライブにインストールしてバインドする手段を提供する場合があります。

あなたが達成したいことについてより多くの情報を提供する場合、これらのケースでは常に少し簡単です。

0
jgmjgm