這樣做fuser -v /dev/urandom
告訴我哪些進程目前已/dev/urandom
打開,但僅此而已。是否有任何方法可以確定每個人隨著時間的推移消耗了多少熵?例如,一個進程可能每分鐘消耗約 1 位元熵,而另一個進程每秒消耗約 8 位元熵;我想要某種方法來確定這一點。
答案1
簡短的答案是 0,因為熵沒有被消耗。
有一個常見的誤解熵被消耗-每次讀取隨機位元時,都會從隨機來源刪除一些熵。這是錯誤的。你不會「消耗」熵。是的,Linux 文件弄錯了。
Linux系統的生命週期分為兩個階段:
- 最初,沒有足夠的熵。
/dev/random
會阻塞,直到它認為已經累積了足夠的熵;/dev/urandom
很高興提供低熵數據。 - 一段時間後,隨機產生器池中就會出現足夠的熵。
/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 圖表...
我們也可以用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舉個例子。