elastic / apm-agent-dotnet

https://www.elastic.co/guide/en/apm/agent/dotnet/current/index.html
Apache License 2.0
579 stars 207 forks source link

[BUG] Cannot connect to APM server which supports only TLSv1.3 #2031

Open VMelnalksnis opened 1 year ago

VMelnalksnis commented 1 year ago

APM Agent version

1.20.0

Environment

Operating system and version: Ubuntu 20.04.5 LTS

.NET Framework/Core name and version (e.g. .NET 4.6.1, NET Core 3.1.100) : .NET SDK 7.0.102

Application Target Framework(s) (e.g. net461, netcoreapp3.1): net7.0

Describe the bug

After upgrading to 1.20.0 nothing is sent to APM server, because it fails the TLS handshake:

{"log.level":"error","@timestamp":"2023-03-05T11:03:29.598+0200","log.logger":"beater.http","log.origin":{"file.name":"http/server.go","file.line":3195},"message":"http: TLS handshake error from 10.10.12.162:33834: tls: client offered only unsupported versions: [303 302 301]","service.name":"apm-server","ecs.version":"1.6.0"}

To Reproduce

Steps to reproduce the behavior:

  1. APM server configuration:
    ssl:
    enabled: true
    certificate: '/path/to/certificate.crt'
    key: '/path/to/key.key'
    key_passphrase: '${KEY_PASSPHRASE}'
    supported_protocols: [TLSv1.3]
  2. appsettings.json
        "ElasticApm": {
                "Enabled": true,
                "CentralConfig": false,
                "ServiceName": "Foo",
                "ServerUrl": "https://apm.some.fully.qualified.name.com:8200"
        }
  3. Startup.cs
    application.UseElasticApm(
    _configuration,
    new AspNetCoreDiagnosticSubscriber(),
    new HttpDiagnosticsSubscriber(),
    new EfCoreDiagnosticsSubscriber(),
    new ElasticsearchDiagnosticsSubscriber());

After switching supported_protocols: [TLSv1.3] to supported_protocols: [TLSv1.3,TLSv1.2] the connection is established successfully and the APM agent works as expected. I'm guessing this is related to #1926.

Expected behavior

TLSv1.3 works same as it did in 1.19.0

Actual behavior

TLSv1.3 does not work

kuanpak commented 1 year ago

I have the same issue after upgraded Elastic.Apm to 1.20+

monty241 commented 2 months ago

A possible solution might be to change in BackendCommUtils.cs from:

#if !NET462
            httpClientHandler.ServerCertificateCustomValidationCallback = serverCertificateCustomValidationCallback;
            logger.Info()?.Log("CreateHttpClientHandler - Setting ServerCertificateCustomValidationCallback");

            httpClientHandler.SslProtocols |= SslProtocols.Tls12;
            logger.Info()?.Log("CreateHttpClientHandler - SslProtocols: {SslProtocols}", httpClientHandler.SslProtocols);
#else
            // We don't set the ServerCertificateCustomValidationCallback on ServicePointManager here as it would
            // apply to the whole AppDomain and that may not be desired. A consumer can set this themselves if they
            // need custom validation behaviour.
            ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
            logger.Info()?.Log("CreateHttpClientHandler - SslProtocols: {SslProtocols}", ServicePointManager.SecurityProtocol);
#endif

to something like:

#if NET6_0_OR_GREATER
            httpClientHandler.SslProtocols |= SslProtocols.Tls12;
            httpClientHandler.SslProtocols |= SslProtocols.Tls13;
            logger.Info()?.Log("CreateHttpClientHandler - SslProtocols: {SslProtocols}", httpClientHandler.SslProtocols);
#elif NETFRAMEWORK
            ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
            logger.Info()?.Log("CreateHttpClientHandler - SslProtocols: {SslProtocols}", ServicePointManager.SecurityProtocol);
#else
            httpClientHandler.SslProtocols |= SslProtocols.Tls12;
            logger.Info()?.Log("CreateHttpClientHandler - SslProtocols: {SslProtocols}", httpClientHandler.SslProtocols);
#endif

#if !NET462
            httpClientHandler.ServerCertificateCustomValidationCallback = serverCertificateCustomValidationCallback;
            logger.Info()?.Log("CreateHttpClientHandler - Setting ServerCertificateCustomValidationCallback");
#else
            // We don't set the ServerCertificateCustomValidationCallback on ServicePointManager here as it would
            // apply to the whole AppDomain and that may not be desired. A consumer can set this themselves if they
            // need custom validation behaviour.
#endif