OpenTelemetry自签名证书TLS配置故障排查
问题:OpenTelemetry Collector启用自签名TLS证书后无日志输出
我们基于OpenTelemetry搭建日志系统,通过Jaeger实现可视化,组件间采用gRPC协议传输。原系统运行正常,但启用TLS(本地部署必须使用自签名证书)后,出现无日志输出且无明确报错的情况。
相关配置与操作
1. 自签名证书生成
使用OpenSSL执行以下命令生成证书:
openssl req -new -nodes -x509 -days 365 -newkey rsa:2048 -keyout domain.key -out domain.crt -config C:/Certs/san.cnf -extensions v3_req
对应的san.cnf配置文件内容:
[req] default_bits = 4096 default_md = sha256 distinguished_name = req_distinguished_name x509_extensions = v3_req prompt = no [req_distinguished_name] C = DE ST = L = Hannover O = DummyCompany OU = MyDivision CN = localhost [v3_req] keyUsage = nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [alt_names] DNS.1 = localhost
2. OpenTelemetry Collector配置(证书部分)
collector-config.yaml中OTLP接收器的TLS配置:
receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:30009 tls: cert_file: domain.crt key_file: domain.key
3. .NET客户端日志生成代码
//Setup tracing var lovTraceProvider = Sdk.CreateTracerProviderBuilder() .AddSource("OpenTelemetryCollector") .SetResourceBuilder( ResourceBuilder.CreateDefault() .AddService(serviceName: "OpenTelemetryCollector")) .AddConsoleExporter() .AddJaegerExporter(test => { test.Endpoint = new Uri("http://localhost:14268"); test.Protocol = JaegerExportProtocol.HttpBinaryThrift; }) .AddOtlpExporter(lovOplt => { lovOplt.Protocol = OtlpExportProtocol.Grpc; lovOplt.Endpoint = new Uri("https://localhost:8866/"); }) .Build();
4. 错误信息
Collector启动正常,但服务器端出现以下错误:
[Server #3] grpc: Server.Serve failed to create ServerTransport: connection error: desc = "ServerHandshake(\"[::1]:64328\") failed: remote error: tls: unknown certificate"
问题分析与解决方案
核心原因
错误提示remote error: tls: unknown certificate,说明客户端未信任Collector使用的自签名证书,导致TLS握手失败。此外注意到Collector监听端口为30009,但客户端连接的是8866,端口不匹配也会导致连接失败。
解决方案步骤
1. 修正端口匹配
先确保客户端连接的端口与Collector监听端口一致,将客户端代码中的端点改为:
lovOplt.Endpoint = new Uri("https://localhost:30009/");
2. 客户端信任自签名证书(推荐生产/测试环境使用)
将生成的domain.crt加载到客户端,并配置证书验证逻辑:
.AddOtlpExporter(lovOplt => { lovOplt.Protocol = OtlpExportProtocol.Grpc; lovOplt.Endpoint = new Uri("https://localhost:30009/"); // 加载自签名证书 var trustedCert = new X509Certificate2("path/to/domain.crt"); var handler = new HttpClientHandler(); handler.ServerCertificateCustomValidationCallback = (sender, certChain, sslPolicyErrors, context) => { // 验证服务器证书是否为我们的自签名证书 return certChain.ChainElements .Cast<X509ChainElement>() .Any(element => element.Certificate.Thumbprint == trustedCert.Thumbprint); }; lovOplt.HttpClientFactory = () => new HttpClient(handler); })
3. 跳过证书验证(仅测试环境临时使用)
如果是测试环境,可临时跳过证书验证:
.AddOtlpExporter(lovOplt => { lovOplt.Protocol = OtlpExportProtocol.Grpc; lovOplt.Endpoint = new Uri("https://localhost:30009/"); var handler = new HttpClientHandler(); // 跳过所有证书验证,仅用于测试 handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; lovOplt.HttpClientFactory = () => new HttpClient(handler); })
内容的提问来源于stack exchange,提问作者TiboVh
相关产品推荐
相关产品推荐

