Whenever I cat /proc/sys/kernel/random/entropy_avail
inside my Docker containers (Linux 5.10 based), I get a double-digit result, which is apparently laughably low. Supposedly anything below 4 digits is bad, and keeping it close to 4096 (the max) is ideal.
I've read about an entropy-gathering daemon called haveged
, but it is supposedly obsolete since Linux kernel 5.6, so I'm not sure that that's the right solution anymore.
Why is my entropy so low inside my Docker containers running the 5.10 kernel, and what can I do to fix it?
I originally discovered this when a Python "quote of the day" script kept choosing the same few quotes. I wasn't manually seeding Python's standard Random module, but according to its documentation and source code, it's supposed to self-seed from system entropy (directly via getentropy(3)
or get getrandom(2)
if available, which I assume they would be on a typical modern Linux environment, or via /dev/random
or /dev/urandom
otherwise, or fall back to using the system time and PID as a last resort). So I guess my entropy was so low that getentropy(3)
was returning poor entropy? Anyway, manually seeding Python's Random module with the system time worked around that problem.
However, now I'm worried that my web servers doing TLS, and my authentication servers, all of which run in similar Docker containers, might not have enough entropy to generate strong keys and one-time-pads and challenges and whatnot. So I want to get to the bottom of how to guarantee that my Docker containers are getting enough entropy to do their jobs well.
This isn't critical national infrastructure or something where installing a hardware RNG module would be appropriate. These are just cloud-hosted Docker containers, so I'm hoping for a solution I can implement within my Docker containers/images.
Since you're talking to the kernel, it's not really related to docker at all:
If you get more entropy on the host, you'll have more entropy in the container.
Anecdotes that you saw the same quote of the day recently is not evidence that your RNG has a problem.
Use Python's Random (not SystemRandom) for everything short of security critical cryptography. Seeds itself by default. Note that any reasonably unique integer would do as seed, extraordinarily unlikely that an RNG's quality can be detected by it seeding another.
What about SystemRandom? This is Python's API for getting at platform specific RNGs that are not deterministic, and so better for cryptographic use.
Random bits are not rare or special on Linux, that's a myth. The kernel's CSPRNG is good, and once initialized, can be used in nonblocking mode (/dev/urandom, getrandom with GRND_NONBLOCK) for large quantities of random bits. Actually since 5.6, that is how it works, Linux no longer has a blocking pool. /dev/random only blocks at boot before kernel rng initialization. Long term this is a real solution, upgrade the kernel and programs can have as many bits as they want.
Problem is, people still think blocking APIs are better, despite the denial of service this causes when a blocking pool is exhausted. Python fixed a problem with exhausting the blocking pool in an early boot script... by making os.urandom() blocking on Linux. Sigh.