错误信息
SSL_do_handshake() failed (SSL: error:0A000418:SSL routines::tlsv1 alert unknown ca:SSL alert number 48)
也可能输出为
- SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
- error:0A000418:SSL routines::tlsv1 alert unknown ca
nginx 以 info 级别记录为“SSL_do_handshake() failed (SSL: error:0A000418:SSL routines::tlsv1 alert unknown ca:SSL alert number 48) while SSL handshaking, client: …”。openssl CLI 输出“…:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca:…”。无论证书链不受信任、是自签名的还是不完整,OpenSSL 客户端都会发送这个告警。
nginx error log / OpenSSL — TLS alert 48 (unknown_ca) received from the peer
含义
连接的另一端以 TLS 告警 48(unknown_ca)中止了握手:它无法为收到的证书构建出通向自己所信任 CA 的证书链。出现在服务器日志中时(如本页示例,来自 nginx),它表示某个客户端拒绝了服务器的证书。出现在客户端上时,它表示服务器在双向 TLS 中拒绝了客户端证书。记录这个告警的一方从来不是出问题的一方:原因在于发给对端的那张证书。
原因
服务器日志:客户端不信任服务器的证书
常见自签名证书或私有 CA 签发的证书、缺少中间证书,或者本应内部使用、却提供给公网客户端的证书。每个失败的客户端(curl、API 客户端、监控)都会留下一行这样的日志。
客户端:服务器不信任你的客户端证书
常见在双向 TLS 中,客户端证书的签发 CA 不在服务器配置为可接受的范围内,或者客户端没有附带自己的中间证书。
扫描器和探测程序
偶见全网扫描器连接时不信任任何证书,会以这个告警中止握手;来自陌生地址的零星日志行是无害的。
修复方法
- 1.
确定被拒绝的是哪张证书
如果出现在服务器日志中,就从外部测试服务器的证书链;如果出现在运行双向 TLS 的客户端上,就用服务器要求的 CA 检查客户端证书。
bash # In a SERVER log: a client rejected the server's certificate (e.g. missing intermediate) openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \ | grep -E '^ *[0-9]+ s:|^ *i:|Verify return code' # On a CLIENT: the server rejected your client certificate (mutual TLS) - 2.
服务器:提供完整且公开受信任的证书链
对于公共端点,使用公共 CA 签发的证书,并配置完整的证书链。对于内部端点,确保每个客户端都安装了内部根证书。
text # nginx: the chain clients need, leaf first ssl_certificate /etc/nginx/tls/fullchain.pem; ssl_certificate_key /etc/nginx/tls/privkey.pem; - 3.
双向 TLS:由受信任的 CA 签发客户端证书
用服务器配置的 CA(nginx 中为 ssl_client_certificate)验证客户端证书,并让客户端连同证书一起发送其中间证书。
bash # Mutual TLS: is the client certificate issued by the CA the server trusts? openssl verify -CAfile server-trusted-client-ca.pem -untrusted client-intermediate.pem client.pem # Send the client's intermediate too, if it has one cat client.pem client-intermediate.pem > client-chain.pem curl --cert client-chain.pem --key client.key https://mtls.example.com/
相关错误
SSL routines:ssl3_read_bytes:ssl/tls alert bad certificateOpenSSLSSL routines:ssl3_read_bytes:tlsv13 alert certificate requiredOpenSSL (client side)curl: (60) SSL certificate problem: unable to get local issuer certificatecurl (OpenSSL backend)remote error: tls: unknown certificate authorityGo crypto/tls