Doing fuser -v /dev/urandom
me diz quais processos estão /dev/urandom
abertos no momento, mas apenas isso. Existe alguma maneira de determinar alguma coisa sobre quanta entropia cada um está consumindo ao longo do tempo? Por exemplo, pode ser que um processo esteja consumindo cerca de 1 bit de entropia a cada minuto, enquanto outro processo esteja consumindo cerca de 8 bits por segundo; Eu gostaria de alguma maneira de determinar isso.
Responder1
A resposta curta é 0, porque a entropia não é consumida.
Existe umequívoco comumque a entropia é consumida – que cada vez que você lê um bit aleatório, isso remove alguma entropia da fonte aleatória. Isto está errado.Você não “consome” entropia. Sim,a documentação do Linux erra.
Durante o ciclo de vida de um sistema Linux, existem dois estágios:
- Inicialmente, não há entropia suficiente.
/dev/random
bloqueará até achar que acumulou entropia suficiente;/dev/urandom
felizmente fornece dados de baixa entropia. - Depois de um tempo, entropia suficiente está presente no conjunto gerador aleatório.
/dev/random
atribui uma taxa falsa de “alho-porro de entropia” e bloqueia de vez em quando;/dev/urandom
felizmente fornece dados aleatórios com qualidade criptográfica.
O FreeBSD acerta: no FreeBSD, /dev/random
(ou /dev/urandom
, que é a mesma coisa) bloqueia se não tiver entropia suficiente e, quando isso acontece, continua vomitando dados aleatórios. No Linux, nem /dev/random
é /dev/urandom
útil.
Na prática, use /dev/urandom
, e certifique-se, ao provisionar seu sistema, de que o pool de entropia seja alimentado (da atividade do disco, da rede e do mouse, de uma fonte de hardware, de uma máquina externa,…).
Embora você possa tentar ler quantos bytes são lidos /dev/urandom
, isso é completamente inútil. A leitura de /dev/urandom
não esgota o conjunto de entropia. Cada consumidor usa até 0 bits de entropia por qualquer unidade de tempo que você queira nomear.
Responder2
Embora não seja automatizado, você pode usar uma ferramenta como strace para observar leituras do(s) descritor(es) de arquivo relacionado(s) ao urandom. Em seguida, veja quantos dados são lidos em um período específico para obter a taxa de leitura.
Responder3
Existem algumas maneiras de abordar o problema se você não souber (ou não suspeitar) qual processo pode estar esgotando o entropy_available no Linux.
Conforme mencionado, você pode usar strace, o que é ótimo para obter informações úteis sobre quais processos você deseja examinar.
Você poderia usar auditd para auditar quais processosabrir/dev/random ou /dev/urandom, mas isso não informa quantos dados são lidos (para evitar problemas de registro). Aqui estão alguns comandos para listar as regras e depois adicionar dois relógios
auditctl -l
auditctl -w /dev/random
auditctl -w /dev/urandom
auditctl -l
Agora faça SSH na caixa (ou faça outra coisa que você sabe que deve resultar na abertura de /dev/urandom ou similar, como dd).
ausearch -ts recente | aureport -f
No meu caso, vejo algo como o seguinte:
[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
Desative esses relógios
auditctl -W /dev/random
auditctl -W /dev/urandom
Lembre-se, porém, de que isso capturará apenas dados para chamadas do sistema que não são de leitura/gravação, etc., portanto, se houver algo que já esteja aberto, você não o verá sendo lido.
No entanto, percebi (usando Prometheus e node_exporter) que ainda estava vendo um padrão dente de serra em que a VM (CentOS 7 sem nada para coletar entropia) relatava entropy_available aumentando para quase 200 e, ao fazer isso, cairia de volta para 0.
O lsof (do fusor, se preferir) oferece alguma coisa?
[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
Observe o dispositivo de caracteres, números maiores e menores; testando de outra forma... (não tenho certeza se isso seria útil, apenas pensando em termos de coisas como o Docker, que não está rodando nesta VM)
[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
Ok, então temos dois processos, chronyd e tuned. Vamos usar strace. lsof nos disse que chrony tinha /dev/urandom aberto para leitura usando o descritor de arquivo 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)
Portanto, o chronyd está aguardando alguma atividade, com um tempo limite de 98 segundos a partir do momento em que iniciou esta chamada de sistema.
Enquanto espero, devo destacar que minha atividade no sistema provavelmente aumentará a estimativa dos kernels de bits aleatórios disponíveis. (entropy_available)... então sente-se e observe o gráfico do Prometheus...
Podemos repetir com tune também... (desta vez adicionando alguns timestamps e um filtro grep apenas para o descritor de arquivo 5 (as chamadas read etc. teriam isso como primeiro argumento)
[root@metrics-d02 vagrant]# strace -p 2525 -f -tt -T 2>&1 | grep '(5,'
A Red Hat tem um blog que discute mais detalhadamenteCSPRNG (gerador de números aleatórios pseudo-aleatórios criptograficamente seguros). Ele discute algumas outras maneiras pelas quais os processos podem obter acesso a números aleatórios:
- chamada de sistema getrandom() <- recomendado para RHEL7.4+, alta qualidade sem bloqueio após a inicialização do pool de entropia
- /dev/random <- bloqueará facilmente
- /dev/urandom <-- problema quando usado antes do pool ser iniciado. 'Nunca bloqueará'; deve ser o que a maioria dos aplicativos deve usar.
- AT_RANDOM <- define 16 bytes aleatórios uma vez no tempo de execução
Embora AT_RANDOM não seja útil, ele está presente em todos os processos, portanto, apenas o ato de iniciar um processo deve esgotar pelo menos um pouco.
Você perceberá agora que o que mostrei acima usando lsof não é suficiente, não revela o uso de getrandom(). Mas como getrandom() é uma chamada de sistema, deveríamos ser capazes de revelar seu uso usando 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)
Fiquei entediado e entrei na caixa e vi muitas coisas interessantes e legais, mas nada de getrandom(), o que não deveria ser uma surpresa, pois vimos isso usando a API /dev/urandom anteriormente.
Então, tentando levar em conta as depressões no gráfico, nada está abrindo /dev/*random, e nada que o tenha aberto está usando-o no momento, e nada parece estar chamando getrandom()... Há mais alguma coisa que poderia consumir dados do [pool atrás de /dev/random]? E o kernel? Considere funcionalidades como ASLR (Address Space Layout Randomisation):
https://access.redhat.com/solutions/44460 [requer assinatura]
[root@metrics-d02 vagrant]# cat /proc/sys/kernel/randomize_va_space
2
'2' aqui significa que além de randomizar onde coisas como mmap e stack (etc.) são carregadas, ele também permitirá a randomização de heap. O que acontece se desligarmos isso
[root@metrics-d02 vagrant]# echo 0 > /proc/sys/kernel/randomize_va_space
[root@metrics-d02 vagrant]# cat /proc/sys/kernel/randomize_va_space
0
(Resposta: a mesma coisa... talvez alguém possa ilustrar isso melhor)
O kernel também estará onde AT_RANDOM está definido. Aqui está um exemplo simples que você pode usar strace para observar que ele não chama /dev/*random ou 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
Espero que seja útil.
Na prática, eu examinaria primeiro as cargas de trabalho Java, pois é onde normalmente sou mais afetado por isso. Verhttps://blogs.oracle.com/luzmestre/why-does-my-weblogic-server-takes-a-long-time-to-startPor exemplo.