如何確定哪些進程正在使用 /dev/urandom 中的多少熵

如何確定哪些進程正在使用 /dev/urandom 中的多少熵

這樣做fuser -v /dev/urandom告訴我哪些進程目前已/dev/urandom打開,但僅此而已。是否有任何方法可以確定每個人隨著時間的推移消耗了多少熵?例如,一個進程可能每分鐘消耗約 1 位元熵,而另一個進程每秒消耗約 8 位元熵;我想要某種方法來確定這一點。

答案1

簡短的答案是 0,因為熵沒有被消耗。

有一個常見的誤解熵被消耗-每次讀取隨機位元時,都會從隨機來源刪除一些熵。這是錯誤的。你不會「消耗」熵。是的,Linux 文件弄錯了

Linux系統的生命週期分為兩個階段:

  1. 最初,沒有足夠的熵。/dev/random會阻塞,直到它認為已經累積了足夠的熵;/dev/urandom很高興提供低熵數據。
  2. 一段時間後,隨機產生器池中就會出現足夠的熵。/dev/random分配一個虛假的「熵韭菜」率並時不時地進行阻止;/dev/urandom很高興提供加密品質的隨機數據。

FreeBSD 的做法是正確的:在 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,這對於深入了解您可能想要查看的進程非常有用。

您可以使用auditd來審計哪些進程打開/dev/random 或 /dev/urandom,但這不會告訴您讀取了多少資料(以防止記錄問題)。以下是一些命令,列出規則,然後添加兩個手錶

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

現在透過 SSH 進入盒子(或執行其他您知道會導致開啟 /dev/urandom 或類似操作的操作,例如 dd)。

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

請注意字元設備的主設備號碼和次設備號碼;測試另一種方式...(我不確定這是否有用,只是考慮像 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。讓我們使用strace。 lsof 告訴我們 chrony 已開啟 /dev/urandom 以便使用 file-discriptor 3 進行讀取

[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 圖表...

Prometheus 圖表顯示了隨時間變化的 node_entropy_available_bits 以及描述

我們也可以用tuned重複...(這次為檔案描述符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 個隨機位元組一次

雖然 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舉個例子。

相關內容