温馨提示×

openssl为何握手失败

小樊
45
2026-07-01 15:46:04
栏目: 云计算

OpenSSL 握手失败(TLS/SSL handshake failure)是常见但原因很多的问题。下面按最常见 → 较少见的顺序给你一个排查思路,并配合常见错误信息。


一、最常见原因(80% 的问题在这里)

1️⃣ 协议版本不匹配(最常见)

客户端和服务端支持的 TLS 版本不一致。

示例错误

no protocols available
protocol version mismatch
handshake failure

原因

  • 服务端只支持 TLS 1.2 / 1.3
  • 客户端使用旧 OpenSSL(如 1.0.2)
  • 强制使用 SSLv3 / TLS 1.0

排查

openssl s_client -connect host:443 -tls1_2
openssl s_client -connect host:443 -tls1_3

建议

  • 禁用 SSLv3 / TLS 1.0 / 1.1
  • 客户端和服务端至少共同支持 TLS 1.2

2️⃣ 证书问题

证书无效或不可信。

常见错误

verify error:num=18:self signed certificate
verify error:num=20:unable to get local issuer certificate
verify error:num=21:unable to verify the first certificate

可能原因

  • 自签名证书
  • 中间证书缺失
  • CA 证书不存在或路径错误
  • 证书过期

排查

openssl s_client -connect host:443 -showcerts

解决

# 指定 CA
openssl s_client -connect host:443 -CAfile ca.crt

或:

# 跳过验证(仅调试)
openssl s_client -connect host:443 -verify 0

3️⃣ 加密套件(Cipher Suite)不匹配

两边协商不到共同算法。

示例错误

no shared cipher
handshake failure

排查

openssl ciphers -v
openssl s_client -connect host:443 -cipher 'ECDHE-RSA-AES128-GCM-SHA256'

建议

  • 服务端至少启用:
    • ECDHE
    • AES-GCM
    • TLS 1.2+

4️⃣ SNI(Server Name Indication)问题

虚拟主机场景非常常见。

现象

  • 直接连 IP 正常
  • 用域名失败
  • 返回默认证书或握手失败

解决

openssl s_client -connect host:443 -servername example.com

必须带上 -servername


二、中级原因

5️⃣ 证书与域名不匹配

Common Name mismatch

✅ 证书中的:

  • CN 或 SAN 必须匹配访问域名

6️⃣ 私钥与证书不匹配

错误示例

SSL_CTX_use_PrivateKey_file failed

验证:

openssl x509 -in cert.pem -noout -modulus
openssl rsa -in key.pem -noout -modulus

✅ modulus 必须一致


7️⃣ 服务端要求客户端证书(双向 TLS)

tlsv1 alert certificate required

✅ 客户端必须提供:

openssl s_client \
  -connect host:443 \
  -cert client.crt \
  -key client.key \
  -CAfile ca.crt

三、较少见但容易忽略

8️⃣ OpenSSL 版本太老

openssl version
  • OpenSSL 1.0.2 → 不支持 TLS 1.3
  • OpenSSL 3.x → 很多老程序不兼容

9️⃣ 中间设备干扰

  • 防火墙
  • 负载均衡
  • SSL 卸载设备

✅ 用:

curl -v https://host

或抓包:

tcpdump / wireshark

四、推荐的快速排查命令(黄金组合)

openssl s_client -connect host:443 \
  -servername example.com \
  -showcerts \
  -tls1_2

五、我可以进一步帮你

如果你愿意,可以把以下信息贴出来(可打码):

  1. 完整错误输出
  2. OpenSSL 版本
  3. 服务端类型(Nginx / Java / Python / C++)
  4. 是否启用双向 TLS

我可以一步步帮你定位是哪一类握手失败。

0