是什么导致排放熵?


21

如果watch cat /proc/sys/kernel/random/entropy_avail可以,我的系统熵会随着时间的推移缓慢增加,直到达到180-190范围,然后下降到120-130左右。熵的下降似乎大约每二十秒发生一次。即使lsof说没有进程/dev/random或没有进程,我也观察到这一点/dev/urandom。是什么在消散熵?内核是否还需要熵,还是正在将较大的池重新处理为较小的质量更好的池?

这是在没有SSL / SSH / WPA连接的裸机上。


这是一个很好的问题,虽然我不能给您一个具体的答案,但对我来说,“熵池”并不是在不使用时应该增加的简单内容。 /dev/random毕竟,它是用于安全加密目的的东西,并且实现不能过于幼稚。可能在这里的最后一点暗示了一种解释:en.wikipedia.org/wiki/Entropy_pool#Using_observed_events(从“用密钥和初始化向量维护流密码开始”)-> 只要足够,池就会被替换数据已累积。
goldilocks

请注意,无论如何,Linux的熵计算/dev/random几乎是虚假的 -熵池一旦满一次,/dev/urandom就和一样好/dev/random
吉尔(Gilles)'所以

1
@techraf哇,答案很快就到了。我没想到2.5年后会得到答案。
wingedsubmariner 2016年

Answers:


20

熵不仅通过丢失/dev/{,u}random,内核也需要一些熵。例如,新进程具有随机地址(ASLR),网络数据包需要随机序列号。甚至文件系统模块也可以消除一些熵。请参阅drivers / 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:random:extract_entropy:ffffffff8173e956池:nbytes 8 entropy_count 921个调用者_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)
                  293ce8 worker_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:random:debit_entropy:ffffffff8173e956:debit_bits 64
                  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)
                  293ce8 worker_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)

...

swapper 0 [002] 3292.507720:随机:credit_entropy_bits:ffffffff8173e956池:bits 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)
                  2d5729 handle_irq_event_percpu(/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  2d58b9 handle_irq_event(/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  2d8d1b handle_edge_irq(/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  230e6a handle_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
+1表示即使看似“无痛”的操作(如启动程序)也可能消耗少量的熵。
CVn

但是,这种解释与问题中描述的情况有些矛盾,不是吗?那里的熵(由监控watch)稳定增长,然后急剧下降。如果watch每次读取都消耗熵,则它实际上应该稳定地减少。
techraf

@techraf很好的观察,定期调用cat在理论上应该具有相同的熵耗,这是不可见的。事实证明,当存在“足够”的熵时,熵将移动到另一个池中。
Lekensteyn

4

lsof并不是最好的监视工具,/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代码,并试图在昨天找到它。我将查看是否可以找到它并稍后更新答案。


auditd可以记录读取的内容/dev/random(我知道该网站上有类似的示例)。
吉尔(Gilles)'所以

1
如何使用以下perl代替watch catuse Fcntl 'SEEK_SET'; open(my $fh,"<", "/proc/sys/kernel/random/entropy_avail"); while (1) { print <$fh>; sleep(1); seek($fh,0,SEEK_SET); }
gmatht 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.