Doing fuser -v /dev/urandom
сообщает мне, какие процессы в данный момент /dev/urandom
открыты, но и только это. Есть ли способ определить, сколько энтропии каждый из них использует с течением времени? Например, может быть, что один процесс использует около 1 бит энтропии каждую минуту, а другой использует около 8 бит в секунду; мне бы хотелось каким-то образом определить это.
решение1
Короткий ответ — 0, поскольку энтропия не расходуется.
Eстьраспространенное заблуждениечто энтропия потребляется — что каждый раз, когда вы читаете случайный бит, это удаляет некоторую энтропию из случайного источника. Это неверно.Вы не «потребляете» энтропию. Да,в документации 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
Есть несколько способов решения проблемы, если вы не знаете (или не подозреваете), какой процесс может истощать 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...
Мы можем повторить это и с настроенным... (на этот раз добавив несколько временных меток и фильтр 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для примера.