Это происходит только в ASP.NET Core 5.0, тот же код работает нормально в ASP.NET Core 3.1
Не удалось установить соединение SSL с OpenSSL в Ubuntu 18.04/20.04 с использованием HttpClient и net5.0
Код: Выделить всё
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.IO.IOException: Received an unexpected EOF or 0 bytes from the transport stream.
at System.Net.Security.SslStream.g__InternalFillHandshakeBufferAsync|182_0[TIOAdapter](TIOAdapter adap, ValueTask`1 task, Int32 minSize)
at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](TIOAdapter adapter)
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Boolean async, Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Boolean async, Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.GetHttp2ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.DecompressionHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken)
к сожалению, я не могу поделиться учетными данными приложения и по причинам отсутствия информации ни о поставщике, который потребляет свой API. Наши IP-адреса также занесены в белый список на брандмауэре.
Но я делюсь кодом, чтобы вы могли видеть все, что я пробовал
Код: Выделить всё
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Test
{
class Program
{
static async Task Main(string[] args)
{
var builder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.AddHttpClient("configured-certificate")
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new HttpClientHandler()
{
CheckCertificateRevocationList = false,
UseDefaultCredentials = false,
ClientCertificateOptions = ClientCertificateOption.Manual,
SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11,
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => ServerCertificateCustomValidation(message, cert, chain, errors),
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
//ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator,
//ServerCertificateCustomValidationCallback = delegate { return true; },
CookieContainer = new CookieContainer()
};
});
services.AddTransient();
services.AddLogging((configure) =>
{
configure.AddConsole();
configure.AddDebug();
});
var env = hostContext.HostingEnvironment;
Console.Write($"Environtment: {env.EnvironmentName}\n");
var configurationBuilder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
hostContext.Configuration = configurationBuilder.Build();
})
.UseConsoleLifetime();
var host = builder.Build();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback +=
(sender, certificate, chain, errors) =>
{
return true;
};
try
{
var myService = host.Services.GetRequiredService();
var pageContent = await myService.GetPage();
Console.WriteLine(pageContent);
}
catch (Exception ex)
{
var logger = host.Services.GetRequiredService();
logger.LogError(ex, "An error occurred.");
}
return 0;
}
private static bool ServerCertificateCustomValidation(HttpRequestMessage requestMessage, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslErrors)
{
//It is possible inpect the certificate provided by server
Console.WriteLine($"Requested URI: {requestMessage.RequestUri}");
Console.WriteLine($"Effective date: {certificate.GetEffectiveDateString()}");
Console.WriteLine($"Exp date: {certificate.GetExpirationDateString()}");
Console.WriteLine($"Issuer: {certificate.Issuer}");
Console.WriteLine($"Subject: {certificate.Subject}");
//Based on the custom logic it is possible to decide whether the client considers certificate valid or not
Console.WriteLine($"Errors: {sslErrors}");
return true;
//return sslErrors == SslPolicyErrors.None;
}
}
public interface ITestService
{
Task GetPage();
}
public class TestService : ITestService
{
private readonly IHttpClientFactory _clientFactory;
public TestService(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
public async Task GetPage()
{
var uri = "https://secureuri";
var client = _clientFactory.CreateClient("configured-certificate");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("basic", "fglsdhjgoñisdjfhgoishdfg=");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("br"));
var xml = System.IO.File.ReadAllText("request.xml");
var data = new StringContent(xml, Encoding.UTF8, "application/xml");
var response = await client.PostAsync(uri, data);
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadAsStringAsync();
}
else
{
return $"StatusCode: {response.StatusCode}";
}
}
}
}
Код: Выделить всё
Release
Any CPU
D:\Test
FileSystem
net5.0
linux-x64
false
False
Код: Выделить всё
root@skynet:# curl -u user:passwd -kv https://xmldirect.ehi.com/services30/OTA30SOAP
* Trying 12.43.130.115:443...
* TCP_NODELAY set
* Connected to xmldirect.ehi.com (12.43.130.115) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / AES256-GCM-SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: C=US; postalCode=63105; ST=Missouri; L=St. Louis; street=600 Corporate Park Dr.; O=Enterprise Holdings Inc.; CN=xmldirect.ehi.com
* start date: Mar 12 00:00:00 2020 GMT
* expire date: Mar 12 23:59:59 2022 GMT
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Organization Validation Secure Server CA
* SSL certificate verify ok.
* Server auth using Basic with user 'user'
> GET /services30/OTA30SOAP HTTP/1.1
> Host: xmldirect.ehi.com
> Authorization: Basic fglsdhjgoñisdjfhgoishdfg=
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Mon, 05 Jul 2021 23:58:48 GMT
< Server: Apache
< Content-Length: 0
< Content-Type: application/xml
< Vary: Accept-Encoding
Идентификатор дистрибьютора: Ubuntu
Описание: Ubuntu 18.04.5 LTS
Выпуск: 18.04
Кодовое имя: bionic
Версия OpenSSL>
OpenSSL 1.0.2s, 28 мая 2019 г.
Тестовая среда
Идентификатор дистрибьютора: Ubuntu
Описание: Ubuntu 20.04.2 LTS
Выпуск: 20.04
Кодовое имя: focus
OpenSSL> версия
OpenSSL 1.1.1f 31 марта 2020 г.
Шифрование ASP.NET Core 3.1 на Client Hello (28 пакетов)

Шифрование ASP.NET Core 5.0 на клиенте Hello (9 апартаментов)

https://github.com/dotnet/runtime/issues/55227
В хорошем случае клиент предлагает набор шифров, а сервер выберет набор шифров: TLS_RSA_WITH_AES_256_GCM_SHA384 ( 0x009d) (пакет 6 -> ServerHello)
В версии 5.0 шифры по умолчанию ограничены тем, что в настоящее время считается надежным и безопасным шифром. Того, что выше, нет в списке.
Подробнее здесь: https://stackoverflow.com/questions/682 ... not-with-a