CentOS에서 .NET Core SSL 연결 문제 해결 방법

OPENSSLDIR 경로 확인 및 최종 해결책

1. OPENSSLDIR 경로 확인

$ openssl version -a

2. 그런 다음 CentOS 기본 openssl CA 인증서를 복사합니다.

$ cp /etc/pki/tls/cert.pem /usr/local/openssl/

참고 링크: https://lamjack.github.io/2018/05/11/centos-compile-openssl-missing-ca-bundle-crt/

다음 내용은 건너뛰어도 됩니다

============================================================

CentOS7에 .NET Core 배포 시 발생하는 예외

환경 변수 정보:

.NET Core SDK (global.json 반영): 버전: 2.2.401 커밋: 729b316c13

런타임 환경: OS 이름: centos OS 버전: 7 OS 플랫폼: Linux RID: centos.7-x64 기본 경로: /usr/share/dotnet/sdk/2.2.401/

호스트(지원용): 버전: 2.2.6 커밋: 7dac9b1b51

설치된 .NET Core SDK: 2.2.401 [/usr/share/dotnet/sdk]

설치된 .NET Core 런타임: Microsoft.AspNetCore.All 2.2.6 [/usr/share/dotnet/shared/Microsoft.AspNetCore.All] Microsoft.AspNetCore.App 2.2.6 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.NETCore.App 2.2.6 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

추가 .NET Core 런타임 또는 SDK를 설치하려면: https://aka.ms/dotnet-download

테스트 코드:

using System;
using System.Diagnostics;
using System.Net.Http;
using System.Net.Http.Headers;

namespace NetworkConnectionTester
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                using (var httpClient = new HttpClient())
                {
                    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));                    

                    string targetUrl = "https://jsonplaceholder.typicode.com/posts/1";
                    var response = httpClient.GetAsync(targetUrl).Result;
                    string jsonResult = response.Content.ReadAsStringAsync().Result;   
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }
    }
}

서버에서 발생한 예외:

System.AggregateException: 하나 이상의 오류가 발생했습니다. (SSL 연결을 설정할 수 없습니다, 내부 예외를 참조하십시오.) ---> System.Net.Http.HttpRequestException: SSL 연결을 설정할 수 없습니다, 내부 예외를 참조하십시오. ---> System.Security.Authentication.AuthenticationException: 원격 인증서가 유효성 검사 절차에 따라 유효하지 않습니다. at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception) at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest) ……………………………………………………

 

또는

원격 인증서가 유효성 검사 절차에 따라 유효하지 않습니다.

해결 방법:

.netcore.runtimeconfig.json 구성 파일에서 System.Net.Http.UseSocketsHttpHandler 스위치를 정의합니다:

"runtimeOptions": {
  "configProperties": {
      "System.Net.Http.UseSocketsHttpHandler": false
  }
}

=====================

위 방법은 문제를 해결할 수 있지만 근본적인 해결책은 아닙니다

문제 분석:

다음 내용을 참고하십시오:

using System;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

namespace CertificateAnalyzer
{
    internal class Program
    {
        private static async Task Main(string[] args)
        {
            try
            {
                //AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
                using (var customHttpHandler = new HttpClientHandler())
                {
                    customHttpHandler.ServerCertificateCustomValidationCallback = (message, certificate, chain, sslPolicyErrors) =>
                    {
                        Console.WriteLine("\r\n\r\n===================메시지==================\r\n\r\n {0}", message.ToString());
                        Console.WriteLine("\r\n\r\n==================인증서==================\r\n\r\n {0}", certificate.ToString());
                        Console.WriteLine("\r\n\r\n==================체인==================\r\n\r\n{0}", chain.ToString());
                        Console.WriteLine("\r\n\r\n==================체인 상태==================\r\n\r\n{0}",
                            chain.ChainStatus.ToString());
                        Console.WriteLine("\r\n\r\n==================오류==================\r\n\r\n{0}", sslPolicyErrors.ToString());


                        Console.WriteLine("\r\n\r\n====================================================\r\n\r\n");
                        Console.WriteLine($"수신된 인증서 주체: {certificate.Subject}");
                        Console.WriteLine("\r\n\r\n====================================================\r\n\r\n");
                        Console.WriteLine($"현재 정책 오류: {sslPolicyErrors}");
                        Console.WriteLine("\r\n\r\n====================================================\r\n\r\n");


                        if (sslPolicyErrors == SslPolicyErrors.None)
                            return true;
                        else
                        {
                            if ((SslPolicyErrors.RemoteCertificateNameMismatch & sslPolicyErrors) == SslPolicyErrors.RemoteCertificateNameMismatch)
                            {
                                Console.WriteLine("인증서 이름 불일치: {0}", sslPolicyErrors);
                            }

                            if ((SslPolicyErrors.RemoteCertificateChainErrors & sslPolicyErrors) == SslPolicyErrors.RemoteCertificateChainErrors)
                            {
                                
                                foreach (X509ChainStatus status in chain.ChainStatus)
                                {
                                    Console.WriteLine("상태 코드 = {0}", status.Status);
                                    Console.WriteLine("상태 정보 = {0}", status.StatusInformation);
                                }

                            }
                            Console.WriteLine("인증서 유효성 검사 실패: {0}", sslPolicyErrors);
                        }

                        return false;
                    };

                    Console.WriteLine("\r\n\r\n====================================================\r\n\r\n");
                    using (var httpClient = new HttpClient(customHttpHandler))
                    {
                        httpClient.DefaultRequestHeaders.Accept.Add(
                            new MediaTypeWithQualityHeaderValue("application/json"));
                        const string testUrl = "https://jsonplaceholder.typicode.com/posts/1";
                        using (var response = await httpClient.GetAsync(testUrl))
                        {
                            var jsonResult = await response.Content.ReadAsStringAsync();
                            Console.WriteLine(jsonResult);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }
}

위 코드를 실행하면 다음과 같은 메시지가 출력됩니다:

<strong>상태 정보 = 로컬 발급자 인증서를 가져올 수 없음 trustasia</strong>

이전에 Nginx를 컴파일할 때 수동으로 OPENSSL을 설치한 것이 문제의 원인이었으며, OPENSSL을 다시 설치한 후 모든 것이 정상적으로 작동했습니다.

태그: .NET Core SSL CentOS OpenSSL 인증서 유효성 검사

7월 2일 02:02에 게시됨