Mar*_*eto 5 c# asp.net .net-core asp.net5 .net-5
我在 asp.net core 5.0 和 linux 中遇到 TLS 1.2 问题。\n仅在 asp.net core 5.0 中发生,相同的代码在 asp.net core 3.1 上运行
\n使用 HttpClient 和 net5.0 在 Ubuntu 18.04/20.04 上使用 OpenSSL 进行 SSL 握手失败
\nSystem.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.\n ---> System.IO.IOException: Received an unexpected EOF or 0 bytes from the transport stream.\n at System.Net.Security.SslStream.<FillHandshakeBufferAsync>g__InternalFillHandshakeBufferAsync|182_0[TIOAdapter](TIOAdapter adap, ValueTask`1 task, Int32 minSize)\n at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](TIOAdapter adapter)\n at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)\n at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Boolean async, Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)\n --- End of inner exception stack trace ---\n at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Boolean async, Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)\n at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\n at System.Net.Http.HttpConnectionPool.GetHttp2ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\n at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)\n at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\n at System.Net.Http.DecompressionHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\n at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\n at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\n at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken)\nRun Code Online (Sandbox Code Playgroud)\n我正在分享一个控制台应用程序,您应该了解这个问题。\n不幸的是,我无法共享该应用程序的凭据,并且由于 nda 的原因,也无法共享使用其 api 的提供程序。我们还在防火墙上将 ip 列入白名单。\n但我共享代码,以便您可以看到我尝试过的所有内容
\nusing System;\nusing System.Net;\nusing System.Net.Http;\nusing System.Net.Http.Headers;\nusing System.Net.Security;\nusing System.Security.Cryptography.X509Certificates;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\nusing Microsoft.Extensions.Logging;\n\nnamespace Test\n{\n class Program\n {\n static async Task<int> Main(string[] args)\n {\n var builder = new HostBuilder()\n .ConfigureServices((hostContext, services) =>\n {\n services.AddHttpClient("configured-certificate")\n .ConfigurePrimaryHttpMessageHandler(() =>\n {\n return new HttpClientHandler()\n {\n CheckCertificateRevocationList = false,\n UseDefaultCredentials = false,\n ClientCertificateOptions = ClientCertificateOption.Manual,\n SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11,\n ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => ServerCertificateCustomValidation(message, cert, chain, errors),\n AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,\n //ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator,\n //ServerCertificateCustomValidationCallback = delegate { return true; },\n CookieContainer = new CookieContainer()\n };\n });\n\n services.AddTransient<ITestService, TestService>();\n services.AddLogging((configure) =>\n {\n configure.AddConsole();\n configure.AddDebug();\n });\n var env = hostContext.HostingEnvironment;\n Console.Write($"Environtment: {env.EnvironmentName}\\n");\n var configurationBuilder = new ConfigurationBuilder()\n .SetBasePath(env.ContentRootPath)\n .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)\n .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)\n .AddEnvironmentVariables();\n \n hostContext.Configuration = configurationBuilder.Build();\n })\n .UseConsoleLifetime();\n\n var host = builder.Build();\n\n ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;\n ServicePointManager.ServerCertificateValidationCallback +=\n (sender, certificate, chain, errors) =>\n {\n return true;\n };\n\n try\n {\n var myService = host.Services.GetRequiredService<ITestService>();\n var pageContent = await myService.GetPage();\n\n Console.WriteLine(pageContent);\n }\n catch (Exception ex)\n {\n var logger = host.Services.GetRequiredService<ILogger<Program>>();\n\n logger.LogError(ex, "An error occurred.");\n }\n\n return 0;\n }\n\n private static bool ServerCertificateCustomValidation(HttpRequestMessage requestMessage, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslErrors)\n {\n //It is possible inpect the certificate provided by server\n Console.WriteLine($"Requested URI: {requestMessage.RequestUri}");\n Console.WriteLine($"Effective date: {certificate.GetEffectiveDateString()}");\n Console.WriteLine($"Exp date: {certificate.GetExpirationDateString()}");\n Console.WriteLine($"Issuer: {certificate.Issuer}");\n Console.WriteLine($"Subject: {certificate.Subject}");\n\n //Based on the custom logic it is possible to decide whether the client considers certificate valid or not\n Console.WriteLine($"Errors: {sslErrors}");\n\n return true;\n //return sslErrors == SslPolicyErrors.None;\n }\n }\n\n public interface ITestService\n {\n Task<string> GetPage();\n }\n\n public class TestService : ITestService\n {\n private readonly IHttpClientFactory _clientFactory;\n\n public TestService(IHttpClientFactory clientFactory)\n {\n _clientFactory = clientFactory;\n }\n\n public async Task<string> GetPage()\n {\n var uri = "https://secureuri";\n\n var client = _clientFactory.CreateClient("configured-certificate");\n client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("basic", "fglsdhjgo\xc3\xb1isdjfhgoishdfg=");\n client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));\n client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));\n client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));\n client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("br"));\n\n var xml = System.IO.File.ReadAllText("request.xml");\n var data = new StringContent(xml, Encoding.UTF8, "application/xml");\n\n var response = await client.PostAsync(uri, data);\n\n if (response.IsSuccessStatusCode)\n {\n return await response.Content.ReadAsStringAsync();\n }\n else\n {\n return $"StatusCode: {response.StatusCode}";\n }\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n发布配置文件如下:
\n<?xml version="1.0" encoding="utf-8"?>\n<!--\nhttps://go.microsoft.com/fwlink/?LinkID=208121. \n-->\n<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\n <PropertyGroup>\n <Configuration>Release</Configuration>\n <Platform>Any CPU</Platform>\n <PublishDir>D:\\Test</PublishDir>\n <PublishProtocol>FileSystem</PublishProtocol>\n <TargetFramework>net5.0</TargetFramework>\n <RuntimeIdentifier>linux-x64</RuntimeIdentifier>\n <SelfContained>false</SelfContained>\n <PublishSingleFile>False</PublishSingleFile>\n </PropertyGroup>\n</Project>\nRun Code Online (Sandbox Code Playgroud)\n我在同一服务器上的 asp.net core 3 和curl 上有结果
\nroot@skynet:# curl -u user:passwd -kv https://xmldirect.ehi.com/services30/OTA30SOAP\n* Trying 12.43.130.115:443...\n* TCP_NODELAY set\n* Connected to xmldirect.ehi.com (12.43.130.115) port 443 (#0)\n* ALPN, offering h2\n* ALPN, offering http/1.1\n* successfully set certificate verify locations:\n* CAfile: /etc/ssl/certs/ca-certificates.crt\n CApath: /etc/ssl/certs\n* TLSv1.3 (OUT), TLS handshake, Client hello (1):\n* TLSv1.3 (IN), TLS handshake, Server hello (2):\n* TLSv1.2 (IN), TLS handshake, Certificate (11):\n* TLSv1.2 (IN), TLS handshake, Server finished (14):\n* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):\n* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):\n* TLSv1.2 (OUT), TLS handshake, Finished (20):\n* TLSv1.2 (IN), TLS handshake, Finished (20):\n* SSL connection using TLSv1.2 / AES256-GCM-SHA384\n* ALPN, server accepted to use http/1.1\n* Server certificate:\n* subject: C=US; postalCode=63105; ST=Missouri; L=St. Louis; street=600 Corporate Park Dr.; O=Enterprise Holdings Inc.; CN=xmldirect.ehi.com\n* start date: Mar 12 00:00:00 2020 GMT\n* expire date: Mar 12 23:59:59 2022 GMT\n* issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Organization Validation Secure Server CA\n* SSL certificate verify ok.\n* Server auth using Basic with user \'user\'\n> GET /services30/OTA30SOAP HTTP/1.1\n> Host: xmldirect.ehi.com\n> Authorization: Basic fglsdhjgo\xc3\xb1isdjfhgoishdfg=\n> User-Agent: curl/7.68.0\n> Accept: */*\n>\n* Mark bundle as not supporting multiuse\n< HTTP/1.1 200 OK\n< Date: Mon, 05 Jul 2021 23:58:48 GMT\n< Server: Apache\n< Content-Length: 0\n< Content-Type: application/xml\n< Vary: Accept-Encoding\nRun Code Online (Sandbox Code Playgroud)\n现场环境
\nDistributor ID: Ubuntu\nDescription: Ubuntu 18.04.5 LTS\nRelease: 18.04\nCodename: bionic\n\nOpenSSL> version\nOpenSSL 1.0.2s 28 May 2019\nRun Code Online (Sandbox Code Playgroud)\n测试环境
\nDistributor ID: Ubuntu\nDescription: Ubuntu 20.04.2 LTS\nRelease: 20.04\nCodename: focal\n\nOpenSSL> version\nOpenSSL 1.1.1f 31 Mar 2020\nRun Code Online (Sandbox Code Playgroud)\nAsp.net core 3.1 Client Hello 上的密码(28 套件)
\n\nAsp.net core 5.0 Client Hello 上的 Cipher(9 套件)
\n\nhttps://github.com/dotnet/runtime/issues/55227
\n在良好的情况下,客户端提供一堆密码,服务器将选择密码套件:TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)(数据包 6 -> ServerHello)\n在 5.0 中,默认密码仅限于当前被认为是强大且安全的密码。上面的那个不在列表中
\n我在这篇文章之后解决了问题https://askubuntu.com/questions/1233186/ubuntu-20-04-how-to-set-lower-ssl-security-level和https://github.com/dotnet/runtime /问题/45244
我在 /etc/ssl/openssl.cnf 中修改了以下内容
# Extra OBJECT IDENTIFIER info:
#oid_file = $ENV::HOME/.oid
oid_section = new_oids
# System default
openssl_conf = default_conf
Run Code Online (Sandbox Code Playgroud)
[default_conf]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
MinProtocol = TLSv1.2
CipherString = DEFAULT:@SECLEVEL=1
#CipherString = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-S>
#CipherString = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-S>
Run Code Online (Sandbox Code Playgroud)
从https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=old&openssl=1.1.1d&guideline=5.6生成的 CipherString对我不起作用
但以下工作正常 CipherString = DEFAULT:@SECLEVEL=1
最后要检查的是 openssl.cnf 的路径,因为在我的情况下 Ubuntu 18.04 当我输入:
openssl 版本 -d OPENSSLDIR: "/usr/lib/ssl"
这条路径中有另一个 openssl.cnf https://learn.microsoft.com/en-us/dotnet/core/compatibility/cryptography/5.0/default-cipher-suites-for-tls-on-linux
mv /usr/local/ssl/openssl.cnf /usr/local/ssl/openssl.cnf.bak ln -s /usr/local/ssl/openssl.cnf /etc/ssl/openssl.cnf
重新启动 api 或应用程序以查看更改非常重要
| 归档时间: |
|
| 查看次数: |
5925 次 |
| 最近记录: |