どのプロセスが /dev/urandom からどれだけのエントロピーを使用しているかを判断する方法

どのプロセスが /dev/urandom からどれだけのエントロピーを使用しているかを判断する方法

すると、fuser -v /dev/urandom現在/dev/urandom開いているプロセスがどれかがわかりますが、それだけです。時間の経過とともに各プロセスがどれだけのエントロピーを消費しているかを判断する方法はありますか? たとえば、あるプロセスが毎分約 1 ビットのエントロピーを消費しているのに対し、別のプロセスは毎秒約 8 ビットを消費している可能性があります。それを判断する方法が必要です。

答え1

簡単に答えると、エントロピーは消費されないので 0 です。

そこにはよくある誤解エントロピーが消費される、つまりランダム ビットを読み取るたびに、ランダム ソースからエントロピーがいくらか削除される、という考え方です。これは誤りです。エントロピーを「消費」するわけではない。 はい、Linuxのドキュメントは間違っている

Linux システムのライフサイクルには、次の 2 つの段階があります。

  1. 最初は、エントロピーが十分ではありません。/dev/random十分なエントロピーが蓄積されたと判断されるまでブロックし、/dev/urandom低エントロピーのデータを提供します。
  2. しばらくすると、乱数生成器プールに十分なエントロピーが存在するようになります。/dev/random「エントロピー リーク」という偽のレートを割り当てて時々ブロックし、/dev/urandom暗号品質のランダム データを問題なく提供します。

FreeBSD では、/dev/random(または/dev/urandom同じ意味の) はエントロピーが十分でない場合はブロックし、十分なエントロピーがあればランダムなデータを吐き出し続けます。Linux では、どちらも役に立ちません/dev/random/dev/urandom

実際には、 を使用し/dev/urandom、システムをプロビジョニングするときに、エントロピー プールにエントロピーが供給されるようにします (ディスク、ネットワーク、マウスのアクティビティ、ハードウェア ソース、外部マシンなどから)。

から何バイト読み取られるかを読み取ることもできますが/dev/urandom、これはまったく意味がありません。 からの読み取りでは/dev/urandomエントロピー プールが枯渇することはありません。各コンシューマーは、任意の時間単位ごとに 0 ビットのエントロピーを消費します。

答え2

自動化はされていませんが、strace などのツールを使用して、urandom に関連するファイル記述子からの読み取りを監視することができます。次に、特定の期間に読み取られたデータの量を確認して、読み取り速度を取得します。

答え3

Linux 上で entropy_available を枯渇させているプロセスがわからない (または疑って​​いない) 場合は、問題に対処する方法がいくつかあります。

前述したように、strace を使用できます。これは、どのプロセスを調べたいかについての有用な洞察を得るのに最適です。

監査dを使用して、どのプロセスを監査するか開ける/dev/random または /dev/urandom ですが、どれだけのデータが読み込まれたかはわかりません (ログの問題を防ぐため)。ルールをリストし、2 つのウォッチを追加するコマンドをいくつか紹介します。

auditctl -l
auditctl -w /dev/random
auditctl -w /dev/urandom
auditctl -l

次に、ボックスに SSH で接続します (または、dd など、/dev/urandom を開くことになるはずの他の操作を実行します)。

ausearch -ts 最近 | aureport -f

私の場合は、次のようになります。

[root@metrics-d02 vagrant]# ausearch -ts recent | aureport -f

File Report
===============================================
# date time file syscall success exe auid event
===============================================
1. 07/01/20 01:13:36 /dev/urandom 2 yes /usr/bin/dd 1000 6383
2. 07/01/20 01:16:43 /dev/urandom 2 yes /usr/sbin/sshd -1 6389
3. 07/01/20 01:16:43 /dev/urandom 2 yes /usr/sbin/sshd -1 6388
4. 07/01/20 01:16:43 /dev/urandom 2 yes /usr/sbin/sshd -1 6390
5. 07/01/20 01:16:44 /dev/urandom 2 yes /usr/sbin/sshd 1000 6408

これらの時計を無効にしてください

auditctl -W /dev/random
auditctl -W /dev/urandom

ただし、これは読み取り/書き込みなどではないシステム コールのデータのみをキャプチャすることに注意してください。そのため、すでに開いているものがある場合は、読み取られることはありません。

しかし、私は (Prometheus と node_exporter を使用して)、VM (エントロピーを収集するものが何もない CentOS 7) が entropy_available が 200 近くまで上昇し、その後 0 まで急落するという鋸歯状のパターンがまだ見られることに気付きました。

lsof (または fuser) は何か提供していますか?

[root@metrics-d02 vagrant]# lsof /dev/random /dev/urandom
COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
chronyd 2184 chrony    3r   CHR    1,9      0t0 5339 /dev/urandom
tuned   2525   root    5r   CHR    1,9      0t0 5339 /dev/urandom

ただし、キャラクタ デバイスのメジャー番号とマイナー番号に注意してください。別の方法でテストします... (これが役立つかどうかはわかりませんが、この VM では実行されていない Docker のようなものについて考えています)

[root@metrics-d02 vagrant]# ls -l /dev/*random
crw-rw-rw-. 1 root root 1, 8 Dec 19 01:24 /dev/random
crw-rw-rw-. 1 root root 1, 9 Dec 19 01:24 /dev/urandom

[root@metrics-d02 vagrant]# lsof | grep '1,[89]'
chronyd    2184           chrony    3r      CHR                1,9      0t0       5339 /dev/urandom
tuned      2525             root    5r      CHR                1,9      0t0       5339 /dev/urandom
gmain      2525  2714       root    5r      CHR                1,9      0t0       5339 /dev/urandom
tuned      2525  2715       root    5r      CHR                1,9      0t0       5339 /dev/urandom
tuned      2525  2717       root    5r      CHR                1,9      0t0       5339 /dev/urandom
tuned      2525  2754       root    5r      CHR                1,9      0t0       5339 /dev/urandom

さて、chronydとtunedという2つのプロセスがあります。straceを使ってみましょう。lsofはchronyがファイル記述子3を使って読み取り用に/dev/urandomを開いていることを伝えました。

[root@metrics-d02 vagrant]# strace -p 2184 -f
strace: Process 2184 attached
select(6, [1 2 5], NULL, NULL, {98, 516224}
.... (I'm waiting)

したがって、chronyd は、このシステム コールを開始してから 98 秒のタイムアウトで、何らかのアクティビティを待機します。

待っている間に、システムでの私のアクティビティによって、カーネルの利用可能なランダム ビットの推定値が増加する可能性があることを強調しておきます。(entropy_available)... なので、座って Prometheus グラフを見てください...

時間の経過に伴う node_entropy_available_bits と説明を示す Prometheus グラフ

チューニングを使用して繰り返すこともできます... (今回は、ファイル記述子 5 専用のタイムスタンプと grep フィルターを追加します (読み取りなどの呼び出しでは、これが最初の引数になります))

[root@metrics-d02 vagrant]# strace -p 2525 -f -tt -T 2>&1 | grep '(5,'

Red Hatにはさらに詳しく解説したブログがあるCSPRNG (暗号的に安全な疑似乱数ジェネレータ)プロセスが乱数にアクセスできる他の方法についても説明します。

  • getrandom() システムコール <-- RHEL7.4+ に推奨、エントロピープールが初期化された後にブロックせずに高品質
  • /dev/random <-- 簡単にブロックされます
  • /dev/urandom <-- プールが初期化される前に使用すると問題が発生します。 'ブロックされません'。ほとんどのアプリケーションが使用すべきものです。
  • AT_RANDOM <-- 実行時に16バイトのランダムバイトを1回設定します

AT_RANDOM は役に立ちませんが、すべてのプロセスに存在するため、プロセスを開始するという動作だけでも、少なくとも少しは電力を消費するはずです。

lsof を使って上記で示しただけでは不十分で、getrandom() の使用を明らかにしていないことにお気づきでしょう。しかし、getrandom() はシステムコールなので、auditctl を使ってその使用を明らかにすることができるはずです。

[root@metrics-d02 vagrant]# auditctl -a exit,always -F arch=b64 -S getrandom
[root@metrics-d02 vagrant]# auditctl -l
-a always,exit -F arch=b64 -S getrandom
[root@metrics-d02 vagrant]# tail -F -n0 /var/log/audit/audit.log 
... (now we wait)

退屈だったのでボックスに ssh でログインし、興味深いクールな機能がたくさん見つかりましたが、getrandom() はありませんでした。これは、以前に /dev/urandom API を使用して確認したので、驚くべきことではありません。

したがって、グラフのくぼみを説明しようとすると、/dev/*random を開いているものはなく、開いているものは現在使用しておらず、getrandom() を呼び出しているものもないようで... [/dev/random の背後にあるプール] からデータを消費するものは他にあるでしょうか? カーネルはどうでしょうか? アドレス空間レイアウトのランダム化 (ASLR) などの機能を検討してください。

https://access.redhat.com/solutions/44460 [サブスクリプションが必要です]

[root@metrics-d02 vagrant]# cat /proc/sys/kernel/randomize_va_space 
2

ここでの「2」は、mmapやスタックなどがロードされる場所をランダム化するだけでなく、ヒープのランダム化も有効にすることを意味します。これをオフにするとどうなるでしょうか

[root@metrics-d02 vagrant]# echo 0 > /proc/sys/kernel/randomize_va_space
[root@metrics-d02 vagrant]# cat /proc/sys/kernel/randomize_va_space 
0

(答え:同じことです...おそらく他の誰かがこれをさらに説明できるでしょう)

カーネルはAT_RANDOMが設定されている場所でもあります。これは、straceを使用して/dev/*randomまたはgetrandom()を呼び出さないことを観察できる簡単な例です。

[vagrant@metrics-d02 ~]$ cat at_random.c 
#include <stdio.h>
#include <stdint.h>
#include <sys/auxv.h>

#define AT_RANDOM_LEN 16

int main(int argc, char *argv[])
{
    uintptr_t at_random;
    int i;

    at_random = getauxval(AT_RANDOM);

    for (i=0; i<AT_RANDOM_LEN; i++) {
        printf("%02x", ((uint8_t *)at_random)[i]);
    }
    printf("\n");

    /* show that it's a one-time thing */

    for (i=0; i<AT_RANDOM_LEN; i++) {
        printf("%02x", ((uint8_t *)at_random)[i]);
    }
    printf("\n");
}
[vagrant@metrics-d02 ~]$ make at_random
cc     at_random.c   -o at_random
[vagrant@metrics-d02 ~]$ ./at_random 
255f8d5711b9aecf9b5724aa53bc968b
255f8d5711b9aecf9b5724aa53bc968b
[vagrant@metrics-d02 ~]$ ./at_random 
ef4b25faf9f435b3a879a17d0f5c1a62
ef4b25faf9f435b3a879a17d0f5c1a62

役に立つと幸いです。

実際には、まずJavaワークロードに目を向けます。なぜなら、これが私が最もこの問題に悩まされてきた分野だからです。https://blogs.oracle.com/luzmestre/why-does-my-weblogic-server-takes-a-long-time-to-start例えば。

関連情報