SSL-TLS(이하 TLS)보안 인증된 서버 Application의 API 호출 할때, An existing connection was forcibly closed by the remote host에러가 발생하는 경우가 있다.
이런 경우는 서버의 TLS 버전을 기본값인 1.0을 사용하지 않고 상위 버전인 1.1이나 1.2를 사용하고 있기 때문이다. (TLS 버전은 2018년 4월 기준으로 1.0부터 1.3까지 있으나 1.3은 아직 정식으로 발표되지 않았다.)
각 버전에 따라 네트워크 전송계층에서 사용하는 암호와 알고리즘이 달라지기 때문에 Server-Client 간에 사용 버전이 다르면 바로 An existing connection was forcibly closed by the remote host오류가 발생한다.
.NET에서는 별도의 설정이 없으면 TLS 버전을 기본값 1.0으로 셋팅하여 HTTP 요청을 하도록 되어 있기 때문에 상위 TLS 버전을 사용하는 서버를 그냥 호출하면 위와 같은 오류가 나온다. 이런경우, 상위 TLS 버전을 사용하여 통신 할수 있도록 System.Net.Security DLL을 이용하여 Security Protocol을 다음과 같이 설정해 주어야 한다.
(ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;)
using (HttpClient client = new HttpClient())
{
string jsonString = "data list";
client.BaseAddress = new Uri("https://<Your App Name>.azurewebsites.net");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
var response = client.PostAsync("/api/getYourData", new StringContent(jsonString, Encoding.UTF8, "application/json")).Result;
if (response.IsSuccessStatusCode)
{
result = response.Content.ReadAsStringAsync().Result;
}
}
호출 대상 서버의 TLS 제공 버전을 정확하게 알고 있으면 좋겠지만, 그렇지 않은 경우, 위 예시 코드처럼 지원하는 TLS버전 리스트를 Or(‘|’)로 묶어서 설정 하면 Client에서 요청 할때 알아서 알맞는 TLS Protocol 버전으로 통신(Handshake)을 하도록 되어 있어서 크게 신경 쓰지 않아도 된다.
단지, 너무 오래된(취약점이 있는)버전의 경우 보안 이슈가 될 수 있으니 적당한 지원 버전 영역을 관리 하는 것을 권장한다.