Limit concurrent connections per IP in Tengine
2026-09-30
Rate limiting (limit_req) stops request floods, but a single client can still open hundreds of simultaneous connections — which is exactly how slowloris-style attacks and scraper storms eat your connection pool. limit_conn caps the number of concurrent connections per IP, and it pairs perfectly with rate limiting.
Step 1 — Declare the zone
In the http block:
limit_conn_zone $binary_remote_addr zone=perip:10m;
Step 2 — Apply it to a server or location
server {
limit_conn perip 20;
limit_conn_log_level warn;
}
This allows at most 20 concurrent connections per IP. Excess connections are rejected immediately with 503.
Choosing a sane limit
- Browsers open several connections per page (typically 6–10 per host).
20is comfortable for real users. - If you run heavy polling/WebSocket clients, see my WebSocket proxy guide — sockets count as connections and need headroom.
- Behind a proxy or CDN, all users share one visible IP, so per-IP limits can misfire — key the zone on a real client identifier (e.g.
$http_x_forwarded_forparsing) in those setups.
Verify
for i in $(seq 1 40); do curl -s -o /dev/null -w "%{http_code}\n" https://yourdomain.com/ & done | sort | uniq -c
With a limit of 20 you should see roughly 20 200s and the rest 503s.
Summary
limit_conn caps simultaneous connections per IP while limit_req caps request rate — together they close both attack angles. Tune the number to your real traffic so legitimate users never notice.