¿Qué sigue drenando la entropía?

21

Si lo hago watch cat /proc/sys/kernel/random/entropy_avail, veo que la entropía de mis sistemas aumenta lentamente con el tiempo, hasta que alcanza el rango de 180-190, momento en el que cae a alrededor de 120-130. Las caídas en la entropía parecen ocurrir aproximadamente cada veinte segundos. Observo esto incluso cuando lsofdice que ningún proceso tiene /dev/randomo /dev/urandomabierto. ¿Qué está drenando la entropía? ¿El núcleo necesita también entropía, o tal vez está reprocesando el grupo más grande en un grupo más pequeño y de mejor calidad?

Esto está en una máquina de metal desnudo, sin conexiones SSL / SSH / WPA.

Submarino alado
fuente
Buena pregunta, y aunque no puedo darle una respuesta específica, tiene sentido para mí que el "grupo de entropía" no sea simplemente algo que debería aumentar cuando no se usa. /dev/randomdespués de todo, es algo que se usa con fines criptográficos seguros, y la implementación no puede permitirse ser ingenua. En el último punto aquí se puede insinuar una explicación: en.wikipedia.org/wiki/Entropy_pool#Using_observed_events (comenzando con "Mantener un cifrado de flujo con una clave y un vector de inicialización ...") -> el grupo se reemplaza siempre que sea suficiente Se han acumulado datos.
Ricitos de oro
Tenga en cuenta que, en cualquier caso, el cálculo de entropía de Linux /dev/randomes bastante falso : una vez que el grupo de entropía se ha llenado una vez, /dev/urandomes tan bueno como /dev/random.
Gilles 'SO- deja de ser malvado'
1
@techraf Wow, esa respuesta se hizo grande rápidamente. Nunca esperé obtener una respuesta 2.5 años después.
wingedsubmariner

Respuestas:

20

La entropía no solo se pierde a través de /dev/{,u}random, el núcleo también toma algo. Por ejemplo, los nuevos procesos tienen direcciones aleatorias (ASLR) y los paquetes de red necesitan números de secuencia aleatorios. Incluso el módulo del sistema de archivos puede eliminar algo de entropía. Vea los comentarios en drivers / char / random.c . También tenga en cuenta que se entropy_availrefiere al grupo de entrada , no a los grupos de salida (básicamente el no bloqueo /dev/urandomy el bloqueo /dev/random).

Si necesita ver el grupo de entropía, no lo use watch cat, ya que consumirá entropía en cada invocación de cat. En el pasado, también quería ver este grupo, ya que GPG era muy lento en la generación de claves, por lo tanto, escribí un programa en C con el único propósito de ver el grupo de entropía: https://git.lekensteyn.nl/c-files/tree /entropy-watcher.c .

Tenga en cuenta que puede haber procesos en segundo plano que también consumen entropía. Usando puntos de rastreo en un kernel apropiado puede ver los procesos que modifican el grupo de entropía. Ejemplo de uso que registra todos los puntos de rastreo relacionados con el subsistema aleatorio, incluida la cadena de llamada ( -g) en todas las CPU ( -a), comenzando a medir después de 1 segundo para ignorar su propio proceso ( -D 1000) e incluyendo marcas de tiempo ( -T):

sudo perf record -e random:\* -g -a -D 1000 -T sleep 60

Léalo con cualquiera de estos comandos (cambie el propietario de perf.datasegún sea necesario):

perf report  # opens an interactive overview
perf script  # outputs events after each other with traces

El perf scriptresultado ofrece una visión interesante y muestra cuándo se agotan periódicamente alrededor de 8 bytes (64 bits) de entropía en mi máquina:

kworker / 0: 2 193 [000] 3292.235908: random: extract_entropy: ffffffff8173e956 pool: nbytes 8 entropy_count 921 llamador _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 trabajador_proceso (/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: aleatorio: 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 trabajador_proceso (/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: random: credit_entropy_bits: ffffffff8173e956 pool: bits 2 entropy_count 859 entropy_total 2 llamador 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)

Aparentemente, esto sucede para evitar el desperdicio de entropía al transferir la entropía desde el grupo de entrada a los grupos de salida:

/*
 * 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)
{
    ...
}
Lekensteyn
fuente
2
+1 para señalar que incluso las operaciones aparentemente "inocentes", como iniciar un programa, pueden drenar una pequeña cantidad de entropía.
un CVn
Sin embargo, esta explicación es un poco contradictoria con la situación descrita en la pregunta, ¿no? Allí, la entropía (controlada con watch) crece de manera constante y luego cae bruscamente. Si se watchconsume entropía en cada lectura, en realidad debería disminuir constantemente.
techraf
@techraf Buena observación, la invocación periódica catdebería en teoría tener el mismo drenaje de entropía que no debería ser visible. Resulta que la entropía se mueve a un grupo diferente cuando hay entropía "suficiente".
Lekensteyn
4

lsof no es la mejor herramienta para monitorear,/dev/randomya que una lectura de un proceso termina en muy poco tiempo. No conozco un buen método para obtener qué proceso está haciendo una lectura, pero al usarloinotifypuedes monitorear si hay una lectura.

Aquí hay básicamente dos formas:

  1. Obtenga un resumen después de N segundos con:

    inotifywatch -v -t 60 /dev/random 
    
  2. Ver eventos de acceso en vivo :

    inotifywait -m --timefmt '%H:%M:%S' --format '%T: %e' /dev/random
    

Ninguno de los dos le dará el proceso y este último no le dará el tamaño de la lectura. El primero le dará un resumen como en:

total  access  close_nowrite  open  filename
18     16      1              1     /dev/random

Si tienes eso funcionando y haces un dd if=/dev/random of=/tmp/foo bs=1 count=3, tienes la idea.

De todos modos. Esto no le dará ticks cuando el núcleo consume del grupo.


Cuando se trata de verificar el estado de la entropía usando

watch cat /proc/sys/kernel/random/entropy_avail

No es la mejor idea, ya que cada uno catva a consumir entropía. (Ahora veo que apareció otra respuesta que también menciona esto). También tengo un código C para esto e intenté localizarlo ayer. Veré si puedo encontrarlo y actualizaré la respuesta más tarde.

Runium
fuente
auditd puede registrar lecturas de /dev/random(sé que hay ejemplos similares en este sitio).
Gilles 'SO- deja de ser malvado'
1
¿Qué pasa con el uso de la siguiente perl en lugar de watch cat: use Fcntl 'SEEK_SET'; open(my $fh,"<", "/proc/sys/kernel/random/entropy_avail"); while (1) { print <$fh>; sleep(1); seek($fh,0,SEEK_SET); }
gmatht