Консольное приложение, перенесенное с .net core 2.2 на .net core 3.1, перестало разрешать внешние HTTP-вызовы

У меня есть консольное приложение с размещенной службой, упакованной в контейнер докеров в netcore 2.2:

FROM microsoft/dotnet:2.2-sdk AS builder
WORKDIR /service
# copy csproj and restore as distinct layers
COPY . .
RUN dotnet restore ./Project.sln
# copy everything else and build
COPY . .
RUN dotnet publish ./Project/Project.csproj -c Release -o /service/out

# build runtime image
FROM microsoft/dotnet:2.2.0-aspnetcore-runtime
WORKDIR /service
COPY --from=builder /service/out ./
ENV ASPNETCORE_ENVIRONMENT Production
ENTRYPOINT ["dotnet", "Project.dll"]

Я без проблем использую RestSharp 106.6. Затем сегодня я решил перейти на net core 3.1, поэтому, помимо успешного изменения версии сборки во всех проектах и ​​успешного запуска консольного приложения, я изменил свой Dockerfile:

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS builder
WORKDIR /service
# copy csproj and restore as distinct layers
COPY . .
RUN dotnet restore ./Project.sln
# copy everything else and build
COPY . .
RUN dotnet publish ./Project/Project.csproj -c Release -o /service/out

# build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS runtime
WORKDIR /service
COPY --from=builder /service/out ./
ENV ASPNETCORE_ENVIRONMENT Production
ENTRYPOINT ["dotnet", "Project.dll"]

Затем я начал получать следующую ошибку при использовании клиента restsharp:

The SSL connection could not be established, see inner exception. Authentication failed

Но внутреннее исключение говорит то же самое. Я предполагаю, что в образе докера чего-то не хватает, что мешает работе клиента, потому что он работает локально - я не думаю, что отсутствует какая-то конфигурация, иначе локальная версия тоже не будет работать.

Ребята, вы сталкивались с этой проблемой раньше?

Спасибо

ОБНОВЛЕНИЕ

Я выхожу из фактического сообщения об исключении, которое я получаю при использовании RestSharp:

 ---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
 ---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
 ---> Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL.
 ---> Interop+Crypto+OpenSslCryptographicException: error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol
   --- End of inner exception stack trace ---
   at Interop.OpenSsl.DoSslHandshake(SafeSslHandle context, Byte[] recvBuf, Int32 recvOffset, Int32 recvCount, Byte[]& sendBuf, Int32& sendCount)
   at System.Net.Security.SslStreamPal.HandshakeInternal(SafeFreeCredentials credential, SafeDeleteContext& context, ArraySegment`1 inputBuffer, Byte[]& outputBuffer, SslAuthenticationOptions sslAuthenticationOptions)
   --- End of inner exception stack trace ---
   at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
   at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.ReadFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Security.SslStream.ThrowIfExceptional()
   at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)
   at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
   at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__65_1(IAsyncResult iar)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.DecompressionHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at System.Net.HttpWebRequest.SendRequest()
   at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
   at RestSharp.Http.GetRawResponseAsync(IAsyncResult result, Action`1 callback)
   at RestSharp.Http.ResponseCallback(IAsyncResult result, Action`1 callback)

Вот только я снова откатываю проект, использующий .NET Core 3.1. Если это останется в .NET Core 2.2, он просто работает. Код для выполнения HTTP-вызова:

public async Task<MyResponse> GetAsync()
        {
            MyResponse myResponse = null;

            var stopWatch = new Stopwatch();

            stopWatch.Start();

            try
            {
                var request = new RestRequest(Method.GET);

                request.AddHeader("Accept", "application/json");

                var restResponse = await _restClient.ExecuteGetAsync(request);

                if(restResponse.IsSuccessful)
                {
                    gobResponse = JsonConvert.DeserializeObject<MyResponse>(restResponse.Content, DateTimeConverter);

                    Logger.Info($"Retrieved my response. Took: {stopWatch.ElapsedMilliseconds}ms. StatusCode={restResponse.StatusCode.ToString()}");
                }
                else
                {
                    Logger.Error(restResponse.ErrorException.ToString(), "Error performing request");
                }
            }
            catch(Exception ex)
            {
                Logger.Error(ex.ToString(), $"Error executing HTTP client");
            }

            return myResponse;                
        }

person Carlos Torrecillas    schedule 24.01.2020    source источник
comment
Ошибка не имеет отношения к .NET Core 3, жалуется на SSL и аутентификацию. Вопрос не содержит кода, поэтому невозможно сказать, что не так или что делает код. Возможно, вы пытаетесь использовать SSL с недействительным или самоподписанным сертификатом? Даже текст исключения отсутствует. Разместите полный текст, а не только сообщение. В сообщении четко сказано, что детали находятся во внутреннем исключении. Вы можете легко получить полный текст с помощью Exception.ToString()   -  person Panagiotis Kanavos    schedule 24.01.2020
comment
Хорошо, верни код, я добавлю его, но вопрос остается в силе. Каким образом обновление версии ядра .NET может повлиять на это? Это актуальный вопрос. Никаких изменений кода, просто обновление версии в файлах проекта + изменения в dockerfile   -  person Carlos Torrecillas    schedule 24.01.2020
comment
А может сертификат недействителен? Возможно, срок его действия истек? Или вы использовали код для отключения проверки сертификата, который больше не работает? Вы просите людей угадать, что делает ваш код, как вы используете SSL. Речь идет не о Docker, поэтому размещенная здесь информация совершенно не помогает. Единственная важная вещь - это одна строка из текста исключения   -  person Panagiotis Kanavos    schedule 24.01.2020
comment
просто вставил и исключение, и код, выполняющий запрос. Тот же код, только смена версии. Один работает, другой не работает. И оба работают на моем локальном компьютере, но когда я упаковываю их в контейнер, это результат, который я получаю в версии 3.1.   -  person Carlos Torrecillas    schedule 24.01.2020
comment
Это определенно не то же самое - SSL Handshake failed with OpenSSL error - SSL. Итак, это Linux, что означает, что на самом деле используется еще одна зависимость - OpenSSL. Эта внешняя зависимость говорит error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol. Вы звоните в службу, которая не использует TLS1.2? Если вы погуглите эту ошибку error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol, вы увидите, что различные дистрибутивы Linux теперь по умолчанию требуют TLS1.2. Версия OpenSSL в вашем образе Docker, вероятно, была недавно обновлена   -  person Panagiotis Kanavos    schedule 24.01.2020
comment
Отвечает ли это на ваш вопрос? OpenSSL v1.1.1 ssl_choose_client_version неподдерживаемый протокол   -  person Panagiotis Kanavos    schedule 24.01.2020
comment
Предпочтительным решением было бы обновить вызываемую вами службу до TLS1.2 или связаться с владельцем, чтобы изменить ее так, чтобы она действительно использовала TLS1.2. Основные сервисы, такие как банки, авиалинии и т. Д., Перешли на TLS1.2 как минимум 4 года назад. Облачные провайдеры сделали то же самое пару лет назад. Нет причин иметь службу, которая использует что-либо меньшее, чем TLS1.2.   -  person Panagiotis Kanavos    schedule 24.01.2020
comment
Неоптимальное решение, как показывает возможный дубликат, - настроить OpenSSL на прием более низких версий TLS. Это определенно не лучшая идея, и рано или поздно ее придется отключить.   -  person Panagiotis Kanavos    schedule 24.01.2020
comment
Или, возможно, удаленная служба по ошибке начала использовать более низкую версию TLS?   -  person Panagiotis Kanavos    schedule 24.01.2020
comment
Просто быть чистым. Я нацелен на ту же конечную точку (HTTPS). Я использую того же хостинг-провайдера. Я использую тот же код. При использовании v.2.2 работает. Когда я использую v3.1, ничего не получается. Если я запускаю на своей машине и 2.2, и 3.1, все работает. Я думаю, что это либо несовместимость между RestSharp и NC3.1, либо сам образ ядра .net 3.1 имеет что-то другое с точки зрения конфигурации TLS ОС.   -  person Carlos Torrecillas    schedule 24.01.2020
comment
Опубликованная вами ошибка ясно показывает, что жалуется OpenSSL. И если вы просто загуглите соответствующую ошибку, вы увидите, что она вызвана тем, что теперь и OpenSSL, и дистрибутивы требуют TLS1.2. Ваш хостинг-провайдер не имеет значения, в какую службу вы звоните? Что использует it? Это не то, что настраивается хостером.   -  person Panagiotis Kanavos    schedule 24.01.2020
comment
Вы можете увидеть, какая версия TLS используется, просто перейдя по URL-адресу службы и щелкнув значок щита слева от адресной строки браузера. Типичный способ устранения таких проблем - использовать прокси-сервер отладки, такой как Fiddler, и проверять запросы и ответы, включая туннельные вызовы.   -  person Panagiotis Kanavos    schedule 24.01.2020
comment
Я думаю, вы указали мне правильное направление. Я получил почтальона и перешел к отключенным протоколам во время рукопожатия. Отключить TLS v1 тогда не удастся. Я предполагаю, что новый образ .NET Core 3.1 по умолчанию устанавливает другую версию TLS или отключает TLS v1, поэтому он не работает.   -  person Carlos Torrecillas    schedule 24.01.2020
comment
Нет, это не так. Повторяющийся вопрос объясняет, что это делают дистрибутивы и OpenSSL. 2.2 была выпущена более года назад. новые образы содержат исправления Linux за год. Собственно, вам повезло - TLS v1 считается сломанным. TLS 1.1 - это минимум. Если бы что-нибудь случилось, ты понес бы ответственность. Например, PCI предложила организациям отказаться от TLS 1 для платежей по кредитным картам с Срок сдачи декабрь 2018 г.   -  person Panagiotis Kanavos    schedule 24.01.2020
comment
Я понимаю. Спасибо. Вы будете удивлены, но эта конечная точка, которую я использую, принадлежит испанскому правительству ... возможно, мне стоит с ними связаться. В любом случае я заставил его работать, добавив ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; на моем Program.cs   -  person Carlos Torrecillas    schedule 24.01.2020
comment
В этом случае вы даже не сможете посетить его с помощью веб-браузера через 1 месяц. Опубликованная мною ссылка показывает, что все браузеры прекратят поддержку TLS1.0 к марту.   -  person Panagiotis Kanavos    schedule 24.01.2020
comment
Что касается правительств, то даже греческое правительство запретило TLS1.1 пару лет назад. Вы можете ожидать, что испанское агентство, ответственное за эту неправильную конфигурацию (пока не будем называть это провалом), попытается исправить ее, как только люди поймут, что теперь она недоступна.   -  person Panagiotis Kanavos    schedule 24.01.2020


Ответы (2)


Вы можете попробовать понизить версию TLS с 1.2 до 1.0, добавив эту строку в свой Dockerfile (образ времени выполнения)

RUN sed -i "s|TLSv1.2|TLSv1.0|g" /etc/ssl/openssl.cnf
person hkarask    schedule 12.05.2020
comment
Это неплохая идея. Спасибо за совет - person Carlos Torrecillas; 21.05.2020
comment
Это решило мою проблему. Хорошая работа для справки, у меня был AWS RDS Mysql и docker container .net app 3.1, работающие в кластере Kubernetes. - person Boncho Valkov; 01.12.2020
comment
К сожалению, это не работает для базовых образов .net5, которые отправляются OpenSSL 1.1.1d 10 Sep 2019, если мы можем доверять openssl version. - person mbx; 02.12.2020

При использовании net5 и недавней библиотеки Data.SqlClient только установка TLS на 1.0 может вызвать взаимоблокировку при выполнении запрос.

# downgrade min TLS version to support older unpatched SQL Server (i.e. SQL Server 2008R2)
# you should patch those machines to support TLSv1.2 though
# see: https://support.microsoft.com/en-us/help/3135244/kb3135244-tls-1-2-support-for-microsoft-sql-server
RUN sed -i "s|MinProtocol = TLSv1.2|MinProtocol = TLSv1|g" /etc/ssl/openssl.cnf && \
    sed -i 's|CipherString = DEFAULT@SECLEVEL=2|CipherString = DEFAULT@SECLEVEL=1|g' /etc/ssl/openssl.cnf

Хотя этот обходной путь, вероятно, вам понадобится немедленно, применив исправление для SQL Server - это то, что вы (или ваша команда операторов) должны сделать в ближайшем будущем.

person mbx    schedule 02.12.2020
comment
Спасибо за это. У меня нет базы данных SQL, так что все должно быть в порядке - person Carlos Torrecillas; 02.12.2020
comment
@CarlosTorrecillas Недавно я столкнулся с той же проблемой со старым непропатченным 2008R2, поэтому я хотел, чтобы другие знали, как заставить его снова работать и как исправить это навсегда, поскольку этот вопрос имеет ту же основную проблему и занимает место в Google. подключиться к SQL серверу, это, конечно, не проблема для вас. - person mbx; 02.12.2020
comment
Хороший. Спасибо за это! - person Carlos Torrecillas; 02.12.2020
comment
@mbx у вас есть образец файла докера, в котором вы это использовали? - person Greg Balajewicz; 29.04.2021
comment
@GregBalajewicz Тот, о котором я думаю, не является общедоступным (и, кстати, больше не находится в производстве, поскольку патч был применен и вскоре после того, как 2008R2 был прекращен), он в основном сводился к это - person mbx; 04.05.2021