A TLS handshake requires asymmetric computation: the server performs significantly more cryptographic work than the client. For TLS 1.3 with X25519 key exchange, the server performs a Diffie-Hellman computation for every new handshake. At 1,000 new TLS connections per second, a single CPU core is fully occupied processing handshakes and has no capacity left for actual request handling. This is a TLS handshake flood, and it operates entirely below the HTTP layer -- WAF rules that inspect HTTP requests provide no protection against it.
Most web servers and load balancers do not limit the rate at which new TLS handshakes can be initiated from a single source IP. The default Nginx configuration has no such limit. The default HAProxy configuration has no such limit. An attacker with a single server can flood TLS connections at a rate that exhausts the target's handshake processing capacity while generating negligible HTTP traffic for WAF inspection.
The CPU Asymmetry
TLS 1.3 handshake computational cost on the server side is approximately 0.5-1ms per handshake, depending on key exchange algorithm and hardware acceleration availability. A server with a 4-core CPU can complete approximately 4,000-8,000 TLS handshakes per second at 100% CPU utilization. An attacker initiating 10,000 new connections per second from a single IP with a 1 Gbps uplink can saturate the TLS processing capacity of a mid-tier server with no HTTP traffic reaching the WAF at all.
TLS session resumption (via session tickets or session IDs) reduces this asymmetry by allowing clients to resume a previous session without a full handshake. Legitimate browsers and API clients implement session resumption. Attack tools typically do not, which means the proportion of full handshakes versus resumed sessions can be used as a signal for TLS flood detection -- but this signal is heuristic and can be bypassed by an attacker who implements session resumption.
Configuring TLS Reconnect Rate Limits
TLS handshake rate limits are configured at the TCP or TLS layer, not the HTTP layer. In Nginx, the limit_conn directive limits the number of simultaneous connections from a single IP, and limit_conn_zone tracks the count. This does not directly limit the rate of new handshakes, but it limits the number of active TLS sessions per IP, which constrains the sustained handshake rate. HAProxy implements per-IP connection limits via the stick-table mechanism with src_conn_cur and src_conn_rate counters.
# Nginx: limit simultaneous connections per IP
# Add to http block:
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# Add to server block:
limit_conn conn_limit 20; # max 20 simultaneous connections per IP
# HAProxy: rate-limit new connections per IP (more granular)
# frontend section:
stick-table type ip size 100k expire 30s store conn_cur,conn_rate(10s)
tcp-request connection track-sc0 src
tcp-request connection reject if { sc_conn_rate(0) gt 50 }
# Blocks IPs initiating more than 50 new connections in 10 seconds
CDN-Level TLS Protection
If traffic reaches your server through a CDN, the CDN terminates TLS connections and forwards requests to your origin over its own persistent connections. In this architecture, your origin server is protected from TLS handshake floods by design -- the CDN absorbs all new TLS connections from clients. The origin only maintains TLS sessions with CDN edge nodes, which are long-lived and limited in number. Organizations that are CDN-protected do not need per-IP TLS rate limits on the origin, but they do need to ensure that direct-to-origin access is blocked (origin IP is not discoverable).
Verify CDN protection actually covers your origin IP
TLS protection from a CDN only works if the origin IP is not reachable directly. DDactic consistently finds organizations where the origin IP is discoverable via historical DNS records, CT logs, or non-CDN subdomains. A discoverable origin IP nullifies the CDN's TLS protection.
Test Your TLS Layer
DDactic's assessment includes TLS reconnect rate limit checks and origin IP discoverability tests to verify your TLS protection is actually in place.
Run a Free Scan