是什么在不断消耗熵?

是什么在不断消耗熵?

如果我这样做,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您可以监视如果有读。

这里基本上有两种方法:

  1. N 秒后获取摘要:

    inotifywatch -v -t 60 /dev/random 
    
  2. 看法居住访问事件:

    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 代码,并试图昨天找到它。我会看看是否能找到它并稍后更新答案。

相关内容