Article View

Scroll down to read the full article.

The Silent Killer: Node.js TLS `ECONNRESET` on RHEL 7 & Entropy Starvation

calendar_month July 27, 2026 |
Quick Summary: Node.js apps on RHEL 7 frequently hit ECONNRESET during TLS handshakes. This guide exposes entropy starvation as the root cause and provides an im...

Alright, listen up. You've got a Node.js service on RHEL 7. It's making outbound HTTPS calls. Intermittently, under load, you're slammed with ECONNRESET. No useful stack trace, no explicit TLS error. Just a dead connection, usually right after the ClientHello. You’ve probably torn your hair out, blamed the network, blamed the remote API. Stop. It’s almost certainly not them.

This isn't your typical networking hiccup. This is a subtle, insidious interaction between an older Linux kernel, specific OpenSSL versions, and the fundamental need for true randomness in secure communications. It’s an entropy starvation issue, pure and simple. And it’s a pain in the ass to debug because the symptoms are so generic.

A chaotic
Visual representation

The Problem: Intermittent ECONNRESET on Outbound HTTPS

Your Node.js application, usually something using axios, node-fetch, or the native https module, attempts to establish a TLS connection. Most of the time, it works. But every now and then, especially when your service is under heavy load, or shortly after a server reboot, a connection fails. The error message is usually ECONNRESET, and packet captures show the remote server sending a RST packet almost immediately after your client sends its ClientHello.

You've checked firewall rules. You've checked proxy configurations. You've verified network routes. Everything looks fine. Yet, the problem persists, often leading to retry logic thrashing and degraded service performance. If you've ever dealt with issues like stale DNS lookups on RHEL 7, you know how frustratingly specific these environment-dependent quirks can be.

Affected Environments

This specific issue usually manifests in environments where the kernel's entropy pool is either slow to fill or frequently depleted. This is particularly common in virtualized environments or new bare-metal installs lacking immediate hardware randomness sources.

Operating System Kernel Version Node.js Version OpenSSL Version Symptoms
Red Hat Enterprise Linux 7.x 3.10.0-x.el7.x86_64 Any 10.x, 12.x, 14.x 1.0.2k (or similar) Intermittent ECONNRESET on outbound TLS connections under load, especially at startup or in VMs.
CentOS 7.x 3.10.0-x.el7.x86_64 Any 10.x, 12.x, 14.x 1.0.2k (or similar) Same as RHEL 7.x; often seen with older Node.js LTS versions.

The Root Cause

Here’s the deal: Node.js, specifically its underlying OpenSSL library, needs high-quality random numbers for TLS key generation during the handshake. Think ephemeral Diffie-Hellman keys, session IDs, etc. On RHEL 7 and similar older Linux distributions, the default source for cryptographic randomness is often /dev/random.

/dev/random is designed to provide 'true' random numbers, drawing from environmental noise. It blocks until sufficient entropy is gathered. In virtual machines, especially those without a dedicated hardware random number generator (HRNG) or a virtio-rng device, the entropy pool can quickly become depleted. When OpenSSL tries to draw from /dev/random for a TLS handshake and the pool is empty, it blocks. If this blocking takes too long, the remote server, waiting for a timely response to its ClientHello, will simply send a RST (reset) packet, killing the connection.

Newer Linux kernels (RHEL 8+, Ubuntu 18.04+) often default to /dev/urandom for non-critical cryptographic operations (like those required for a TLS handshake where blocking isn't acceptable), or they have improved entropy sources. Node.js itself also gained better fallback mechanisms in later versions, but the problem persists in older environments. This isn't just a Node.js problem; any application heavily relying on TLS and older OpenSSL/kernel versions can hit this.

A glowing
Visual representation

The Solution: Prioritize /dev/urandom

The fix is surprisingly simple. We need to tell the kernel to use /dev/urandom as its primary source for non-blocking random data when /dev/random would block. While /dev/random aims for 'true' randomness, /dev/urandom provides cryptographically secure pseudo-random numbers, which are more than sufficient for TLS handshakes and don't block. This is a battle-hardened solution for ensuring your services remain performant and available, much like the precision needed for microsecond warfare in algorithmic execution.

You can achieve this by modifying a kernel parameter or installing an entropy-gathering daemon. The quickest, most direct fix is setting random.entropy_avail as a boot parameter or via sysctl on the fly.

Step-by-Step Fix

  1. Verify Current Entropy: Before you do anything, check your current entropy level.
  2. cat /proc/sys/kernel/random/entropy_avail

    If this number is consistently low (e.g., below 200-300), you're likely facing entropy starvation.

  3. Install rngd (Recommended for Persistent Fix): The rngd daemon collects entropy from hardware random number generators (if available) or other system sources and feeds it into the kernel's entropy pool, making /dev/random more robust and less prone to blocking.
  4. sudo yum install rng-tools
    sudo systemctl start rngd
    sudo systemctl enable rngd

    After starting rngd, re-check /proc/sys/kernel/random/entropy_avail. It should rise significantly.

  5. Force /dev/urandom with sysctl (Immediate, Less Ideal for Production): For immediate relief or testing, you can modify the kernel's behavior directly. This tells the kernel to prefer /dev/urandom data when /dev/random is asked for but is blocking.
  6. sudo sysctl -w kernel.random.read_wakeup_threshold=256
    sudo sysctl -w kernel.random.write_wakeup_threshold=256

    While not strictly telling /dev/random to use /dev/urandom, these thresholds influence when /dev/random blocks, making it less aggressive and indirectly helping. The best, most robust solution is often ensuring rngd is running.

  7. Persist Configuration (If using sysctl directly): To make the sysctl changes permanent across reboots, add them to /etc/sysctl.conf:
  8. echo "kernel.random.read_wakeup_threshold=256" | sudo tee -a /etc/sysctl.conf
    echo "kernel.random.write_wakeup_threshold=256" | sudo tee -a /etc/sysctl.conf
    sudo sysctl -p

Final Thoughts

This ECONNRESET issue stemming from entropy starvation can cost you hours, days, even weeks of fruitless debugging. It’s a classic example of an obscure, environment-specific problem that only veteran SREs encounter after countless production fires. Install rngd, keep an eye on your entropy pool, and save yourself the headache. Your Node.js applications will thank you for the smooth, unblocked TLS handshakes.

Discussion

Comments

Read Next