You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift-NIO-SSL TLS握手失败求助:客户端证书未生效

排查TLS握手失败及客户端证书未生效问题

正在排查TLS握手失败问题,不清楚报错代码含义,请求解析上下文并协助定位客户端证书未生效的原因。


核心报错日志

2000-00-00T00:00:00-0000 error [[GRPC-LOGG]] : error=handshakeFailed(NIOSSL.BoringSSLError.sslError([Error: 268436496 error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE at /Users/username/Library/Developer/Xcode/DerivedData/ios-dc-bocetydygnmhxsdxqxaivnvasghk/SourcePackages/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/ssl/tls_record.cc:592])) grpc.conn.addr_local=10.220.93.246 grpc.conn.addr_remote=23.98.156.101 grpc_connection_id=C1C6376D-9F74-48AF-9D7A-D903BB68D716/0 [GRPC] grpc client error

该报错为TLS握手阶段的致命错误,服务器返回了SSLV3_ALERT_HANDSHAKE_FAILURE告警。

关联TLS源码片段

tls_record.cc 中处理致命告警的代码:

if (alert_level == SSL3_AL_FATAL) {
    OPENSSL_PUT_ERROR(SSL, SSL_AD_REASON_OFFSET + alert_descr); // 报错指向该行
    ERR_add_error_dataf("SSL alert number %d", alert_descr);
    *out_alert = 0;  // No alert to send back to the peer.
    return ssl_open_record_error;
}

gRPC-Swift 客户端配置

初始连接配置代码:

var clientConnection: ClientConnection.Builder

var tlsConfig = TLSConfiguration.makeClientConfiguration()
tlsConfig.certificateVerification = .noHostnameVerification
tlsConfig.trustRoots = .certificates([nioCert!])

let clientConfig = GRPCTLSConfiguration.makeClientConfigurationBackedByNIOSSL(configuration: tlsConfig, hostnameOverride: sniName)

clientConnection = ClientConnection.usingTLS(with: clientConfig, on: eventLoopGroup)
        .withTLSCustomVerificationCallback({ ... })

clientConnection.connect(host: hostName, port: port)

curl 测试结果

执行curl -v https://hostname:port/foo返回:

*   Trying 12.43.425.642:443...
* Connected to q003.ed14.ws.samplecloud.dogi (12.43.425.642) port 443 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (OUT), TLS handshake, Client hello (1):
* LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to q003.ed14.ws.samplecloud.dogi:443 
* Closing connection 0
curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to q003.ed14.ws.samplecloud.dogi:443

进一步错误日志

为gRPC连接添加客户端错误日志后,得到证书校验失败报错:

[!! GRPC-CLIENT-ERROR]: handshakeFailed(NIOSSL.BoringSSLError.sslError([Error: 268435581 error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED at /Users/username/Library/Developer/Xcode/DerivedData/ios-dc-bocetydygnmhxsdxqxaivnvasghk/SourcePackages/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/ssl/handshake.cc:393])) file:[<unknown>] line:[0]]

证书配置排查与调整

抓包发现TLS握手阶段客户端未发送证书:

Client Certificates: -
Server Certificates: 3

调整客户端证书配置,添加证书链与私钥:

tlsConfig.certificateChain = [NIOSSLCertificateSource.certificate(nioCert!)]
let privateKeyNIO = try? NIOSSLPrivateKey.init(bytes: privateKeyByteAry, format: .der)
tlsConfig.privateKey = NIOSSLPrivateKeySource.privateKey(privateKeyNIO!)

更新:调整配置后,抓包仍显示客户端未携带证书,报错问题依旧。


排查方向建议

  • 验证私钥与证书匹配性:确认privateKeyByteAry是DER格式的私钥,且与nioCert属于同一证书对,可通过OpenSSL命令验证:
    openssl x509 -in cert.pem -text
    openssl rsa -in key.der -inform der -text
    
  • 检查服务器证书校验规则:确认服务器是否要求客户端证书,以及客户端证书是否在服务器信任列表中。
  • 验证TLS版本与加密套件兼容性:测试客户端与服务器支持的TLS版本、加密套件是否一致,例如:
    openssl s_client -connect hostname:port -tls1_3
    
  • 排查自定义验证回调:尝试移除.withTLSCustomVerificationCallback({ ... })后测试,确认回调逻辑未干扰证书发送或校验流程。
  • 确认证书加载有效性:检查nioCert是否成功加载,避免因加载失败导致证书链为空。

内容的提问来源于stack exchange,提问作者wizeOnes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 15:05:33