How to disable keepalive in curl
I'm trying to figure out how to consistently turn off keepalive across various client machines which are issuing HTTP requests via curl
.
This is my target server:
- Ubuntu 18.04.2 LTS
- 4.15.0-47-generic
- HA-Proxy version 1.8.19-1ppa1~bionic 2019/02/12
This is client 1 where from I'm issuing curl
(vanilla installation):
- Ubuntu 16.04.3 LTS
- 4.4.0-62-generic
- curl 7.47.0 (x86_64-pc-linux-gnu) libcurl/7.47.0 GnuTLS/3.4.10 zlib/1.2.8 libidn/1.32 librtmp/2.3
This is client 2 where from I'm issuing curl
(vanilla installation):
- Ubuntu 18.04 LTS
- 4.15.0-20-generic
- curl 7.58.0 (x86_64-pc-linux-gnu) libcurl/7.58.0 OpenSSL/1.1.0g zlib/1.2.11 libidn2/2.0.4 libpsl/0.19.1 (+libidn2/2.0.4) nghttp2/1.30.0 librtmp/2.3
To turn off keepalive I've tried using -H "Connection: close"
, --no-keepalive
and --keepalive-time 1
and only the first option seems to work but only from client 1.
On client 1 (Ubuntu 16) the connection is not left open but from client 2 (Ubuntu 18) the connection is left open until it times out. I confirm that either by looking at the target server's watch -n 0.1 "netstat -na | fgrep CLIENT_IP_ADDRESS"
or by using -vvv
on both clients, which on client 1 is always * Closing connection 0
and on client 2 is always * Connection #0 to host www.example.com left intact
.
The difference between client 1 and 2 are obviously the Ubuntu version and curl version. What is it that causes the the connection to be closed in client 1 but not in client 2?
I've also found out that if I change my target server to another machine running an old distro with an old apache httpd, whether I send out Connection: close
or not doesn't make any difference and keepalive is always used from either of my 2 clients. So I suppose that the target server configuration also plays some role in that.
Edit:
To complicate things even further, if from client 1 and 2 I issue requests to the target server via ab
then the connection is killed instantly. That is expected because ab
uses HTTP/1.0
and not HTTP/1.1
. But then, if I target the old distro with apache then in both cases the connection remains open. Which means that, indeed, the receiving end plays a role as well.
Edit 2:
I grabbed all /proc/sys/net/ipv4/
settings of both clients via:
for file in /proc/sys/net/ipv4/*
do
echo "$file $(cat $file)"
done
and these can be found here:
- U16: https://pastebin.com/GcuuqhvA
- U18: https://pastebin.com/a2QWReFZ
- diff: https://pastebin.com/25Ccyz9h
The --no-keepalive option is only useful for TCP keepalive packets, as mentioned in this archived thread on the curl website: https://curl.haxx.se/mail/archive-2013-04/0037.html
Sounds like you'll need to disable HTTP keepalive packets specifically, which would be done on your servers using keepalive_timeout 0; as mentioned in this stackoverflow thread https://stackoverflow.com/questions/24924237/linux-curlnginx-cant-request-with-no-keepalive.
Sorry if the formatting is off, this is my first post :)
Hope that helps!
Per https://everything.curl.dev/usingcurl/persist
curl will always try to keep connections alive and reuse existing connections as far as it can.
Therefore, you cannot use it using the tools as they are.
As @pl-nowlan mentioned in their answer, the only way to do that would be on the server side.