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을 다시 설치한 후 모든 것이 정상적으로 작동했습니다.