![是什么在不断消耗熵?](https://linux22.com/image/51400/%E6%98%AF%E4%BB%80%E4%B9%88%E5%9C%A8%E4%B8%8D%E6%96%AD%E6%B6%88%E8%80%97%E7%86%B5%EF%BC%9F.png)
如果我这样做,watch cat /proc/sys/kernel/random/entropy_avail
我会发现我的系统熵会随着时间的推移慢慢增加,直到达到 180-190 范围,然后下降到 120-130 左右。熵的下降似乎大约每二十秒发生一次。即使lsof
说没有进程/dev/random
或/dev/urandom
打开,我也会观察到这一点。是什么在消耗熵?内核是否也需要熵,或者它可能正在将较大的池重新处理成更小、质量更好的池?
这是在裸机机器上,没有 SSL/SSH/WPA 连接。
答案1
熵不仅会通过 丢失/dev/{,u}random
,内核也会丢失一些。例如,新进程具有随机地址(ASLR),网络数据包需要随机序列号。甚至文件系统模块也可能会删除一些熵。请参阅中的评论驱动程序/char/random.c。另请注意entropy_avail
指的是输入池,而不是输出池(基本上是非阻塞/dev/urandom
和阻塞/dev/random
)。
如果您需要监视熵池,请不要使用watch cat
,这会在每次调用 时消耗熵cat
。过去我也想观察这个池,因为 GPG 生成密钥非常慢,因此我编写了一个 C 程序,其唯一目的是观察熵池:https://git.lekensteyn.nl/c-files/tree/entropy-watcher.c。
请注意,可能存在也会消耗熵的后台进程。使用适当内核上的跟踪点,您可以看到修改熵池的进程。记录与随机子系统相关的所有跟踪点的示例用法,包括-g
所有 CPU ( -a
) 上的调用链 (),在 1 秒后开始测量以忽略其自己的进程 ( -D 1000
) 并包括时间戳 ( -T
):
sudo perf record -e random:\* -g -a -D 1000 -T sleep 60
使用以下命令之一读取它(perf.data
根据需要更改所有者):
perf report # opens an interactive overview
perf script # outputs events after each other with traces
输出perf script
给出了一个有趣的见解,并显示了我的机器上大约 8 字节(64 位)的熵何时被定期耗尽:
kworker/0:2 193 [000] 3292.235908: 随机:extract_entropy: ffffffff8173e956 池: nbytes 8 entropy_count921调用者_xfer_secondary_pool 5eb857 extract_entropy (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 5eb984 _xfer_secondary_pool (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 5ebae6 Push_to_pool (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 293a05 process_one_work (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 293ce8worker_thread(/lib/modules/4.6.2-1-ARCH/build/vmlinux) 299998 kthread (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 7c7482 ret_from_fork (/lib/modules/4.6.2-1-ARCH/build/vmlinux) kworker/0:2 193 [000] 3292.235911: 随机:debit_entropy: ffffffff8173e956: debit_bits64 5eb3e8 account.part.12 (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 5eb770 extract_entropy (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 5eb984 _xfer_secondary_pool (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 5ebae6 Push_to_pool (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 293a05 process_one_work (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 293ce8worker_thread(/lib/modules/4.6.2-1-ARCH/build/vmlinux) 299998 kthread (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 7c7482 ret_from_fork (/lib/modules/4.6.2-1-ARCH/build/vmlinux) ... 交换器 0 [002] 3292.507720:随机:credit_entropy_bits:ffffffff8173e956 池:位 2 entropy_count第859章entropy_total 2 调用者 add_interrupt_randomness 5eaab6 Credit_entropy_bits (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 5ec644 add_interrupt_randomness (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 2d5729handle_irq_event_percpu(/lib/modules/4.6.2-1-ARCH/build/vmlinux) 2d58b9handle_irq_event(/lib/modules/4.6.2-1-ARCH/build/vmlinux) 2d8d1b handle_edge_irq (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 230e6ahandle_irq(/lib/modules/4.6.2-1-ARCH/build/vmlinux) 7c9abb do_IRQ (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 7c7bc2 ret_from_intr (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 6756c7 cpuidle_enter (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 2bd9fa call_cpuidle (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 2bde18 cpu_startup_entry (/lib/modules/4.6.2-1-ARCH/build/vmlinux) 2510e5 start_secondary (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
显然,这是为了通过将熵从输入池转移到输出池来防止熵的浪费:
/*
* Credit (or debit) the entropy store with n bits of entropy.
* Use credit_entropy_bits_safe() if the value comes from userspace
* or otherwise should be checked for extreme values.
*/
static void credit_entropy_bits(struct entropy_store *r, int nbits)
{
...
/* If the input pool is getting full, send some
* entropy to the two output pools, flipping back and
* forth between them, until the output pools are 75%
* full.
*/
...
schedule_work(&last->push_work);
}
/*
* Used as a workqueue function so that when the input pool is getting
* full, we can "spill over" some entropy to the output pools. That
* way the output pools can store some of the excess entropy instead
* of letting it go to waste.
*/
static void push_to_pool(struct work_struct *work)
{
...
}
答案2
拉索夫不是最好的监控工具,/dev/random
因为进程读取的内容在一段时间后就结束了非常时间很短。我不知道有什么好方法来获取正在读取的进程,但是使用inotify
您可以监视如果有读。
这里基本上有两种方法:
N 秒后获取摘要:
inotifywatch -v -t 60 /dev/random
看法居住访问事件:
inotifywait -m --timefmt '%H:%M:%S' --format '%T: %e' /dev/random
两者都不会给你进程,后者也不会给你阅读的大小。第一个将为您提供如下摘要:
total access close_nowrite open filename
18 16 1 1 /dev/random
如果您运行并执行了该操作dd if=/dev/random of=/tmp/foo bs=1 count=3
,您就会明白了。
无论如何。当内核从池中消耗数据时,这不会给您带来蜱虫。
当涉及到使用以下方法检查熵的状态时
watch cat /proc/sys/kernel/random/entropy_avail
这不是最好的主意,因为每个cat
都会消耗熵。 (我现在看到它弹出了另一个答案,也提到了这一点。)我也有一些这方面的 C 代码,并试图昨天找到它。我会看看是否能找到它并稍后更新答案。