[제목] Docker를 이용한 TLS 테스트 방법에 대하여
HTTPS는 SSL/TLS 프로토콜을 기반으로 하고 있는데, 낮은 버전의 SSL/TLS는 Man-in-the-middle 공격에 노출되기 쉽기 때문에, 최근들어 금융권을 비롯한 엔터프라이즈에서 TLS 1.2로 업그레이드하는 추세이다. 이에 맞춰, C# /.NET 응용프로그램에서도 TLS 1.2를 지원하도록 수정할 필요성이 생기고 있다.
.NET Framework 4.5 이전에서는 TLS 1.0 까지만 지원하였고, .NET 4.5 이상에서 TLS 1.1, TLS 1.2 등을 지원하고 있다. 다만, .NET 에서 디폴트로 TLS 1.0 을 사용하고 있기 때문에, .NET 4.5 이상에서 TLS 1.2를 Enable 하기 위해서는 System.Net.ServicePointManager.SecurityProtocol 에 SecurityProtocolType.Tls12를 추가로 지정해 주어야 한다.
예를 들어, 웹 클라이언트에서 TLS 1.0 ~ TLS 1.2를 모두 지원하기 위해서는 아래 예제와 같이 OR (|)로 각 TLS 타입을 지정해 주면 된다. (C# / .NET의 TLS 설정에 대한 자세한 내용은 여기 TLS 관련 아티클을 참고)
아래 예제는 C#으로 SQL CLR 어셈블리를 작성한 아주 단순화한 샘플로서, sp_HttpGet() 메서드가 웹 URL을 호출하여 HTML 결과를 가져온다고 가정한 것이다. 여기서 주목할 것은 MyHttp 클래스안의 MyHttp 정적 생성자를 정의하고 그 안에 ServicePointManager.SecurityProtocol 을 여러 TLS 버전을 지원하도록 설정한 점이다. 이렇게 함으로써 해당 클래스에서 사용되는 모든 메서드들이 웹 클라이언트로서 TLS 1.0 ~ TLS 1.2를 모두 지원하게 된다.
// Build: MyCLR.dll using System.Net; namespace MyUtil { public class MyHttp { static MyHttp() { // 허용되는 TLS 버전 지정 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | // TLS 1.0 SecurityProtocolType.Tls11 | // TLS 1.1 SecurityProtocolType.Tls12; // TLS 1.2 } [SqlProcedure] public static void sp_HttpGet(SqlString Uri, out SqlString result) { var webRequest = WebRequest.Create(uri); webRequest.Method = "GET"; //... } //... } }
위의 C# 코드를 컴파일하여 MyCLR.dll 이 생성된다고 가정했을 때, 아래와 같은 SQL Stored Procedure를 정의할 수 있다. 즉, SQL Server에서 이 Stored Procedure를 호출하여 SQL에서 웹사이트를 호출하게 되는 것이다.
CREATE PROCEDURE dbo.sp_HttpGet( @Uri NVARCHAR(1000), @Result NVARCHAR(4000) OUTPUT ) WITH EXECUTE AS CALLER AS EXTERNAL NAME [MyCLR].[MyUtil.MyHttp].[sp_HttpGet] GO
그런데, 위와 같은 SQLCLR을 웹클라이언트로 사용할 때, SQLCLR이 어떤 TLS 버전을 사용하는지 테스트하기 어려운 면이 있다. 통상 웹클라이언트와 웹서버간의 TLS 통신을 체크할 때, Fiddler 같은 유틸러티 프로그램을 사용하는데, SQL Server 안의 SQLCLR에서 직접 호출되는 웹 호출은 Fiddler로 잡을 수 없는 문제점이 있다.
이러한 문제를 해결하는 하나의 방식으로 Docker를 사용하여 OpenSSL로 간단한 https 서버를 설치하고, SQLCLR에서 이 Docker 서버를 호출하여 TLS 버전을 체크하는 방법을 소개한다. 아래는 Docker의 설치부터 HTTPS 서버의 설치, 그리고 SQLCLR 에서 TLS를 테스트하는 과정을 스텝별로 정리한 것이다.
1) Windows 10에 [Docker for Windows] 설치한다.
- (a) Hyper-V 설치: Control Panel / Turn Windows features on or off / Check [Hyper-V].
- (b) Restart Windows
- (c) Docker for Windows 설치
2) Docker 명령을 실행하기 위해 Cmd.exe 를 [Run as administrator]로 실행한다.
3) Docker에서 Ubuntu 이미지를 가져온다.
C> docker pull ubuntu
4) Docker에서 Ubuntu 실행한다. 아래 명령은 ubuntu 컨테이너를 새로 생성하며, Interactive Terminal을 사용할 수 있게하고(-it),
BASH 쉘을 실행한다. 또한, -p 옵션으로 Windows 로컬포트 44300을 Docker의 Ubuntu 포트 44300에 연결한다.
아래 명령을 실행하면 root로 우분투 터미널에 들어가게 된다.
C> docker run -it -p 44300:44300 ubuntu bash
5) Docker Ubuntu에서 OpenSSL을 이용하여 간단한 HTTPS 서버를 구축한다.
-
(a) openssl을 설치한다.
# apt-get update # apt-get install openssl
-
(b) HTTPS를 사용하기 위해서 Self-signed server certificate을 생성한다.
# openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
-
(c) OpenSSL을 사용하여 HTTPS 서버를 실행한다. (b)에서 생성한 certificate 파일을 지정하고,
https 포트는 임의로 44300 으로 설정하였다. 이 포트는 Step#4에서 -p로 지정된 포트이다.
# openssl s_server -key key.pem -cert cert.pem -accept 44300 -www
만약 HTTPS 서버가 TLS 1.2만을 지원하도록 한다면, -tls1_2 옵션을 지정한다.# openssl s_server -key key.pem -cert cert.pem -accept 44300 -www -tls1_2
마찬가지로, TLS 1.1만을 지원하도록 한다면 -tls1_1 옵션을 지정하고, TLS 1.0만을 지원하도록 한다면 -tls1 옵션을 지정하면 된다.# openssl s_server -key key.pem -cert cert.pem -accept 44300 -www -tls1_1 # openssl s_server -key key.pem -cert cert.pem -accept 44300 -www -tls1
6) Windows에서 Docker에 있는 Ubuntu의 openssl https 서버에 엑세스하기 위해서는 웹브라우져에서 https://localhost:44300 을 방문하면 된다.
7) Step#6과 비슷하게, SQL Server의 SQLCLR 으로부터 Docker에 있는 Ubuntu의 openssl https 서버에 엑세스하기 위해서는
Stored Procedure에서 https://localhost:44300 을 호출한다. 예를 들어,
DECLARE @result NVARCHAR(4000) EXEC sp_HttpGet 'https://localhost:44300', @result=@result OUTPUT SELECT @result
localhost:44300 의 결과를 출력하면 중간에 어떤 TLS version이 사용되었는지 알 수 있다. 아래 출력 결과는 https 통신이 TLS 1.2을 사용하여 이루어졌음을 나타낸다.
본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.