如何配置Curl以延长SSL握手阶段的等待时间?
如何配置Curl以延长SSL握手阶段的等待时间?
我太懂你这种憋屈的感觉了——明明等够时间服务器就会响应,但Curl在TCP连接阶段(还没到SSL握手呢!)就提前超时撂挑子了,常规的--max-time、--connect-timeout完全不管用,简直气人!
先给你捋明白为啥会这样:你遇到的根本不是SSL握手超时,是TCP连接建立阶段的SYN包重传逻辑被系统内核限制了。你看抓包里的SYN包没收到ACK,这时候内核会自动重传SYN包,但默认的重传次数/间隔很短,比如Linux默认的tcp_syn_retries是5次,总等待时间大概127秒,刚好和你报错的134秒左右对应。Curl的用户态超时参数管不了内核这层的逻辑,所以就算你设了300秒,内核先放弃了,Curl也只能跟着报错。
那该怎么解决?分两步来:
第一步:调整系统内核的TCP SYN重传参数(以Linux为例)
这是最关键的一步,得让内核愿意等够5分钟:
- 先看看你当前的参数值:
sysctl net.ipv4.tcp_syn_retries - 临时改成更大的数值(比如8,对应总等待时间约255秒,接近5分钟):
sysctl -w net.ipv4.tcp_syn_retries=8 - 如果要永久生效,编辑
/etc/sysctl.conf文件,添加一行:
然后执行net.ipv4.tcp_syn_retries = 8sysctl -p让配置生效。
要是你用的是Windows系统,得改注册表:
- 打开注册表编辑器(
regedit),找到路径HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters - 新建或修改
TcpMaxConnectRetransmissions的DWORD值,设置为8(十进制) - 重启系统生效。
第二步:配合Curl的超时参数
调整完内核参数后,再用Curl的时候,设置足够长的超时时间,确保覆盖内核的等待时长:
time curl --max-time 300 --connect-timeout 300 \ https://certificacioninternacional.mijp.gob.ve/paginas/CU_registrarUsuario/
这时候内核会负责反复发送SYN包直到超时,Curl就会一直等到TCP连接建立,再进入SSL握手阶段。
额外说明
你之前用的--connect-timeout之所以没效果,是因为它是Curl在用户态等待连接完成的总时间,但内核的SYN重传逻辑是独立的——如果内核的超时时间比Curl设置的短,内核先放弃连接,Curl自然就报错了。所以必须让内核的等待时间足够长,同时Curl的超时参数要比内核的总等待时间更久。
备注:内容来源于stack exchange,提问作者e-info128




