Как определить, какие процессы используют сколько энтропии из /dev/urandom

Как определить, какие процессы используют сколько энтропии из /dev/urandom

Doing fuser -v /dev/urandomсообщает мне, какие процессы в данный момент /dev/urandomоткрыты, но и только это. Есть ли способ определить, сколько энтропии каждый из них использует с течением времени? Например, может быть, что один процесс использует около 1 бит энтропии каждую минуту, а другой использует около 8 бит в секунду; мне бы хотелось каким-то образом определить это.

решение1

Короткий ответ — 0, поскольку энтропия не расходуется.

Eстьраспространенное заблуждениечто энтропия потребляется — что каждый раз, когда вы читаете случайный бит, это удаляет некоторую энтропию из случайного источника. Это неверно.Вы не «потребляете» энтропию. Да,в документации 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

Есть несколько способов решения проблемы, если вы не знаете (или не подозреваете), какой процесс может истощать entropy_available в Linux.

Как уже упоминалось, вы можете использовать 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), что я все еще вижу пилообразную картину, при которой виртуальная машина (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 с течением времени с описаниями

Мы можем повторить это и с настроенным... (на этот раз добавив несколько временных меток и фильтр grep только для файлового дескриптора 5 (вызовы read и т. д. будут иметь это в качестве первого аргумента)

[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(), что не должно было стать сюрпризом, поскольку ранее мы видели его с использованием API /dev/urandom.

Итак, пытаясь объяснить провалы на графике, ничто не открывает /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 и stack (и т. д.), он также включит рандомизацию кучи. Что произойдет, если мы отключим это

[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-take-a-long-time-to-startдля примера.

Связанный контент