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
相关产品推荐
相关产品推荐

