Why Does Nginx Reset HTTPS Curl Requests? A Deep Dive and Fix
After adding an HTTPS certificate to a website, browsers load fine but curl requests are reset; this article chronicles the troubleshooting steps—examining network ports, cipher suites, client buffers, SSL session cache settings, and common Nginx error logs—to pinpoint and resolve the underlying cause.
Tip: The first part of the article describes handling a curl request reset under HTTPS on Nginx; you can skip to the end for quick Nginx anomaly location.
Problem Description
After the site went live with an HTTPS certificate, browsers accessed it normally, but a curl request was reset.
A Difficult Journey
First, a curl request to the same domain over HTTP returned normally, confirming port 80 connectivity.
Then a curl request to another HTTPS domain on the same server also succeeded, confirming port 443 connectivity.
Is it a certificate issue? The certificate is valid and shows no problems on myssl.com.
Suspecting the cipher suite configuration, a more compatible suite was added, but the problem persisted.
Compatibility cipher suite:
"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"Using tcpdump and Wireshark, the capture showed that after the handshake, the first ACK packet was reset.
Image of the capture:
Suspecting client buffer limits, the following Nginx client settings were modified:
client_header_buffer_size 64k;
large_client_header_buffers 4 64k;
client_body_buffer_size 20m;
keepalive_timeout 120;After changing the certificate from RSA to ECC (using a Qiniu Cloud ECC certificate), curl returned:
curl: (35) Cannot communicate securely with peer: no common encryption algorithm(s).Investigation revealed that on RedHat/CentOS, curl uses the NSS library, which disables ECC by default, so the client cannot negotiate the ECC cipher suite.
curl --ciphers ecdhe_rsa_aes_128_gcm_sha_256 ...Specifying the cipher suite did not solve the issue, indicating the problem was unrelated to the certificate.
A Ray of Hope
Adding the ssl_session_cache directive finally resolved the reset issue.
Explanation of ssl_session_cache options:
off – Disables session caching entirely.
none – Session caching is prohibited; Nginx tells the client a session may be reused but does not store it.
builtin – Uses OpenSSL’s built‑in cache, limited to a single worker process; default size is 20480 sessions.
shared – Shared cache among all workers; size is specified in bytes (e.g., 1 MiB ≈ 4000 sessions) and requires a name.
In practice, only builtin and shared are useful, with shared generally offering better performance.
Further packet analysis showed that with ssl_session_cache enabled, the reset disappeared, though the exact mechanism remained unclear.
Key observations about the Server Key Exchange step (optional during DH/ECDH negotiation) helped narrow the cause.
RSA encryption used but the server certificate lacks an RSA public key.
DH/ECDH encryption used but the server certificate lacks DH parameters.
Fortezza_kea encryption used but the server certificate lacks required parameters.
Below is a collection of common Nginx error log messages and their meanings:
upstream prematurely closed connection – The upstream closed before sending a response; can be ignored.
recv() failed (104: Connection reset by peer) – May indicate server overload, client closed the connection, or user stopped the request.
(111: Connection refused) while connecting to upstream – Upstream is down or unreachable.
(111: Connection refused) while reading response header from upstream – Upstream died after connection was established.
(111: Connection refused) while sending request to upstream – Failed to send data to upstream.
(110: Connection timed out) while connecting to upstream – Connection timeout.
(110: Connection timed out) while reading upstream – Read timeout from upstream.
(110: Connection timed out) while reading response header from upstream – Header read timeout.
(104: Connection reset by peer) while connecting to upstream – Upstream sent RST.
ngx_slab_alloc() failed: no memory in SSL session shared cache – SSL session cache too small.
could not add new SSL session to the session cache while SSL handshaking – Same as above.
Additional notes:
tcpdump can capture packets, but Wireshark is needed for analysis.
ECC certificates are smaller and faster than RSA certificates and are recommended.
Efficient Ops
This public account is maintained by Xiaotianguo and friends, regularly publishing widely-read original technical articles. We focus on operations transformation and accompany you throughout your operations career, growing together happily.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
