跳到主要内容
ecdsa.com
curl (OpenSSL backend)curl

错误信息

curl: (35) TLS connect error: error:0A000410:SSL routines::ssl/tls alert handshake failure

也可能输出为

  • curl: (35) error:0A000410:SSL routines::sslv3 alert handshake failure
  • curl: (35) error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure

OpenSSL 3.3 及更高版本把原因写作“ssl/tls alert handshake failure”;OpenSSL 3.1 及更早版本打印的是“sslv3 alert handshake failure”(1.1.1 还会带上代码 14094410 和函数名 ssl3_read_bytes)。较新的 curl 版本会在前面加上“TLS connect error: ”。

curl (OpenSSL backend) — CURLE_SSL_CONNECT_ERROR, TLS alert 40 (handshake_failure) received from the server

含义

服务器发送了 TLS 告警 40(handshake_failure),结束了握手:它无法与 curl 提供的参数达成一致。这个告警不携带原因,所以真正的原因只能在服务器日志中看到;在客户端只能比较双方各自支持的内容。此时还没有开始检查证书。

原因

修复方法

  1. 1.

    比较双方提供的选项

    枚举服务器支持的套件和协议版本,并与客户端的密码套件列表对比。curl 的详细输出会显示握手进行到了哪一步、尝试的是哪个版本。

    bash
    # What the server accepts (needs nmap) and what this client offers
    nmap --script ssl-enum-ciphers -p 443 api.example.com
    openssl ciphers -v 'DEFAULT' | head -20
    # Full handshake trace from curl's side
    curl -sv https://api.example.com/ -o /dev/null 2>&1 | grep -E '^\* (TLS|SSL)'
  2. 2.

    服务器所有者:使用当前推荐的密码套件配置

    提供 TLS 1.3 和 TLS 1.2,搭配 ECDHE 和 AEAD 套件(AES-GCM、ChaCha20-Poly1305)。过去十年内的所有客户端都支持它们,现代客户端也都不需要 RSA 密钥交换或 CBC。

    text
    # nginx: TLS 1.2 with forward-secret AEAD suites + TLS 1.3
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers off;
  3. 3.

    发送正确的服务器名称

    在 URL 中使用主机名;或者用 --resolve 强制指定地址,同时保留主机名。使用 openssl s_client 通过 IP 连接时,要传入 -servername。

    bash
    # Use the host name in the URL (SNI is sent automatically); for IP targets keep the name:
    curl --resolve api.example.com:443:203.0.113.10 https://api.example.com/
    # openssl s_client sends SNI only with -servername (or a host name in -connect)
    openssl s_client -connect 203.0.113.10:443 -servername api.example.com </dev/null
  4. 4.

    为双向 TLS 出示客户端证书

    如果端点是 mTLS API,就配置客户端证书和密钥;服务器日志会把问题记录为对端证书缺失或无法验证。

    bash
    # Mutual TLS: present the client certificate and key the server expects
    curl --cert client.pem --key client.key https://mtls.example.com/

相关错误

浏览完整的签名错误库