본문 바로가기

서버운영 (TA, ADMIN)/정보보안

[정보보안] SSL 방식 보안서버 구축하기

1. 소개 및 보안서버 구축 절차



가. 개요

SSL은 Secure Sockets Layer의 머리글이며, 1994년 Netscape에 의해 전세계적인 표준 보안 기술이 개발되었습니다.


SSL 방식은 웹브라우저와 서버간의 통신에서 정보를 암호화함으로써 도중에 해킹을 통해 정보가 유출되더라도 정보의 내용을 보호할 수 있는 기능을 갖춘 보안 솔루션으로 전세계적으로 수 백 만개의 웹사이트에서 사용하고 있습니다.


아래는 SSL 보안에 대해 그림으로 간단하게 설명해 놓은 것입니다.



인증기관(Certification Authorities)에서 제공하는 SSL 인증서를 발급받아 웹서버에 설치하게 되면 웹사이트 이용자들의 거래, ID/패스워드, 개인정보 등을 암호화하여 송수힌할 수 있습니다.



나. 보안서버 구축 절차

SSL 방식의 보안서버 구축 절차는 다음과 같습니다.



1) SSL 방식의 보안서버를 사용하기 위해서는 운영하고 있는 웹서버에 보안서버 인증서가 설치되어야 합니다. 보안서버 인증서는 운영중인 웹서버에서 '인증서 만들기'를 이용하여 생성합니다.

※ 발급이 완료된 인증서는 재발급 또는 변경이 불가능하기 때문에 새로 발급받으셔야 하며, 새로 발급받을 시 비용이 발생할 수 있으니 CSR 생성시 절대 주의 바랍니다.


2) 먼저 운영하는 웹서버에서 개인키를 만든 후, CSR 파일을 생성하여 인증기관에 보안서버 인증서 발급을 신청합니다. CSR(Certificate Signing Request)이란 인증서 요청파일의 약어로서 운영하는 URL 및 운영하는 회사의 정보 등이 입력됩니다.


3) 인증기관에 CSR을 이용하여 인증서를 신청할 때 회사의 담당자 정보 등을 입력합니다. 인증서 발급 심사 후에 신청 시 입력한 담당자의 E-mail 주소로 인증서가 발급됩니다.


4) 발급받은 인증서를 운영 중인 웹 서버에 설치하게 되면 SSL 방식의 보안서버 설정을 완료하게 됩니다.


서버호스팅 서비스를 받고 있는 고객의 경우에는 서버에 대한 관리자 권한이 고객에게 있기 때문에 고객이 직접 CSR 생성 및 인증서 발행 후에 설치를 진행해야 하며, 호스팅 서비스 제공업체에게 보안서버 구축 대행을 요청하게 되면 설치대행비가 부과될 수 있습니다.


SSL 방식의 보안서버 구축은 서버의 운영체제에 따라 적용절차가 모두 다르므로 업체의 서버 종류를 파악한 후, 각 서버의 설치과정을 참고해야 합니다. 



2. 설치 과정



가. Apache 서버에 OpenSSL과 mod_ssl의 설치 방법

Apache 서버에 SSL 통신을 가능하게 하기 위해서는 OpenSSL과 mod_ssl이 필요합니다. 우선, 현재 서비스 중인 Apache 서버에 mod_ssl이 설치되어 있는지를 httpd -l  옵션을 사용하여 mod_ssl.c 또는 mod_ssl.so가 있는지 확인하시기 바랍니다. 만일 설치되어 있다면 Apache 서버의 버전에 맞는 개인키 생성 및 CSR 생성을 진행합니다.



mod_ssl

mod_ssl은 SSL의 오픈소스 구현체인 OpenSSL 라이브러리를 이용해 HTTPS를 구현한 확장 모듈입니다. 아파치 웹 서버 버전1에서는 mod_ssl이 외부 모듈이라 별도로 설치해야 했지만 2.x 버전부터는 기본 모듈에 포함돼 있습니다. 이제 mod_ssl을 설치하고 HTTPS 서비스를 구축해 웹에 강력한 암호화 방식을 적용하면 됩니다.



설치

mod_ssl은 httpd와 openssl 패키지에 의존하지만 두 패키지는 이미 설치했으므로 설치하지 않아도 됩니다. 게다가 만약 시스템에 설치돼 있지 않더라도 yum을 mod_ssl을 설치할 때 의존성 관계에 의해 아파치 httpd도 자동으로 설치됩니다. 그러므로 다음 명령어로 mod_ssl 모듈을 설치하면 됩니다.


yum install mod_ssl


아파치 모듈 파일인 mod_ssl.so는 /etc/httpd/modules/에, 설정 파일인 ssl.conf는 /etc/httpd/conf.d/에 설치됩니다.



설정

이제 conf.d/ssl.conf 설정 파일의 내용을 살펴보면, mod_ssl의 지시자 중 전역적으로 설정하는 지시자는 변경할 일이 없으므로 가상 호스트별로 설정해야 하는 지시자 위주로 알아보겠습니다.


<VirtualHost *:443>

ServerName example.com

ServerAlias www.example.com

SSLEngine on

SSLProtocol all -SSLv2

SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW

SSLCertificateFile /etc/pki/tls/certs/localhost.crt

SSLCertificateKeyFile /etc/pki/tls/private/localhost.key

ErrorLog logs/www-ssl-error_log

TransferLog logs/www-ssl-access_log

CustomLog logs/ssl_request_logs \

"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

</VirtualHost>



SSLEngine

SSL 엔진의 구동 여부를 설정합니다. off로 설정하면 동작하지 않습니다.


SSLProtocol

클라이언트와 통신할 때 사용할 프로토콜 버전을 지정합니다. 사용 가능한 버전 문자열은 SSLv2, SSLv3, TLSv1, TLSv1.1, TLSv1.2입니다. all로 지정하면 모든 버전을 사용하게 되며, 제외할 프로토콜이 있을 경우 - 부호를 붙이면 됩니다. 기본 설정인 all -SSLv2는 모든 버전을 사용하지만 보안에 취약한 SSLv2는 사용하지 않겠다는 의미입니다.


TLS 프로토콜 1.1 이상을 사용하려면 OpenSSL 버전이 1.0.1 이어야 합니다. 현재 CentOS 6에 탑재된 아파치 웹 서버는 TLS 1.2까지 지원하지만 SSLProtocol 지시자에 명시적으로 TLSv1.1, TLSv1.2는 사용할 수 없습니다. 이는 아파치 2.2.22 이상에서만 사용 가능한 지시자인데 탑재된 버전은 2.2.15이기 때문입니다.


다음과 같이 설정하면 SSL 대신 TLS만 사용하게 되며, 세부적인 TLS 버전은 브라우저와 협상해 결정합니다.


SSLProtocol TLSv1



SSLCipherSuite

사용할 암호 알고리즘을 설정합니다. 특별히 선호하는 알고리즘이 있지 않은 이상 수정할 일이 많지 않습니다.


SSLCertificateFile

PEM 형식으로 저장된 인증서 파일의 경로를 설정합니다. 이 인증서는 웹 서비스를 제공하는 서버가 사용하는 인증서로, 보통 VeriSign, Comodo, thawte 등 해외 인증기관에서 발급받습니다. 인증기관에서 발급받으면 비용이 발생하지만 이 인증기관들은 웹 브라우저의 신뢰하는 인증기관 정보에 포함돼 있으므로 브라우저가 HTTPS로 연결할 경우 아래와 같은 경고가 발생하지는 않는다는 장점이 있습니다.



내부에서 사용하는 서비스라면 비용을 들일 필요 없이 자체적으로 만든 인증서를 사용해도 됩니다. OpenSSL을 이용해 자체 인증서를 만드는 방법은 http://lesstif.com/x/HoBq를 참고하세요.


RHEL과 CentOS는 인증서를 /etc/pki/tls/certs 디렉터리에 저장하며, SELinux의 보안 컨텍스트도 여기에 맞춰져 있으므로 반드시 이 경로에 설치합니다.


PEM(Privacy Enhanced Mail)이란?

PEM은 Base64 형식으로 인코딩된 인증서 형식을 의미합니다. 텍스트 편집기로 열어서 -----BEGIN CERTIFICATE-----로 시작하는 부분이 있으면 PEM 형식이고, 바이너리 데이터면 DER 형식입니다.


mod_ssl은 PEM을 사용하므로 DER 형식의 인증서가 있다면 openssl 명령어를 통해 PEM으로 변환해야 합니다.


$ openssl x509 -inform der -in certificate.cer -out certificate.pem



SELinux에 주의하자

인증서와 개인키가 존재하는데 웹 서버가 이를 읽지 못할 경우 SELinux가 원인인 경우가 있습니다. 이를 차단하는 주요 원인은 잘못된 보안 컨텍스트 때문이며, 인증서와 개인키를 저장하는 /etc/pki/tls/의 컨텍스트는 cert_t여야 합니다. 이 경우 SELinux의 restorecon이나 chjcon 명령으로 문제를 해결할 수 있습니다.



SSLCertificateKeyFile

공개키와 쌍을 이루는 개인키의 경로를 지정합니다. CentOS는 /etc/pki/tls/private 디렉터리에 저장하며, 개인키는 유출돼서는 안 되므로 루트 외에는 읽을 수 없도록 다음과 같이 설정하는 좋습니다.


chmod 700 /etc/pki/tls/private/


기본적으로 개인키 파일을 생성할 때 암호(Passphrase)를 넣어야만 사용할 수 있게 돼 있습니다. 암호로 보호되는 개인키를 웹 서버에서 SSL용으로 사용할 경우 웹서버를 구동할 때마다 암호를 입력해야 합니다. 이는 서비스 자동화에 방해가 될 수 있으므로 개인키를 보호하는 암호를 없애고 사용하고 싶은 경우 openssl 명령어를 이용해 암호를 제거한 개인키를 만들 수 있습니다.


1. 기존 개인키를 백업용으로 복사합니다.

cp /etc/pki/tls/private/example.com.key /etc/pki/tls/private/example.com.key.enc


2. openssl 명령어를 이용해 개인키의 암호를 제거합니다. 이때 기존 암호를 넣어야 합니다.

openssl rsa -in /etc/pki/tls/private/example.com.key.enc -out /etc/pki/tls/private/example.com.key



SSLCACerttificateFile

PEM 형식으로 된 SSL 인증서를 발급한 인증기관의 인증서 목록 파일을 설정합니다. 위에서 언급한 SSL 인증서 발급 기관이라면 보통 브라우저에 인증기관의 인증서가 포함돼 있으므로 따로 설정하지 않아도 서비스 하는데 문제가 없습니다.



로그 파일 설정

SSL 가상 호스트마다 ErrorLog, TransferLog 지시자로 로그 파일을 지정할 수 있습니다.


HTTP로 들어온 요청과 구분하기 위해 별도의 로그 파일로 분리하는 것이 좋으며, SSL일 경우 프로토콜 버전과 사용하는 암호 정보를 기술하는 별도의 로그 파일을 CustomLog 지시자로 지정할 수 있습니다. 다음은 기본 CustomLog 설정으로 시간, 클라이언트 IP, 프로토콜 버전, 암호 알고리즘 종류, 그리고 HTTP 요청 내용과 크기를 남기게 합니다.


CustomLog logs/ssl_request_log \ 

"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"


브라우저의 종류를 확인하기 위해 %b 뒤에 %{User-agent}i를 추가하고 웹 서버를 재시작 하면


CustomLog logs/ssl_request_log \

"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b %{User-agent}i"


이제 로그 파일을 보면 최신 브라우저들은 SSL 대신 TLS를 사용한다는 사실을 알 수 있습니다.


[13/Nov/2014:14:18:38 +0900] 192.168.10.10 TLSv1 AES128-SHA "GET / HTTP/1.1" 4958 Mozilla/5.0(compatible; MSIE 10.0; Windows NT 6.1; WOW61; Trident/6.0)

[13/Nov/2014:14:18:42 +0900] 192.168.10.10 TLSv1.2 DHE-RSA-AES128-GCM-SHA256 "GET / HTTP/1.1" 4958 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36

[13/Nov/2014:14:19:03 +0900] 192.168.10.10 TLSv1.2 DHE-RSA-AES128-SHA "GET / HTTP/1.1" 4958 Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0



웹서버 재구동

설정이 끝나면 service httpd restart 명령어로 웹 서버를 재구동해서 SSL/TLS 동작 여부를 확인해봅니다. 웨 ㅂ 브라우저의 URL에 https를 명시해서 연결해도 되며, 리눅스 명령줄이면 유틸리티 장에서 익힌 curl 명령어를 사용해도 됩니다.


curl은 SSL/TLS로 연결할 때 서버의 인증서를 검증하므로 인증기관에서 발급받은 인증서가 아닐 경우 -k, --insecure 옵션을 추가해야 합니다. -v 옵션을 추가하면 핸드셰이크 과정도 표시됩니다.


curl -k -v -J https://example.com/



SSL 가상 호스트

SSL 사이트가 여러 개인 경우에도 웹 서버의 가상 호스트 기능을 이용해 한 장비에서 서비스할 수 있습니다. 먼저 conf.d/ssl.conf에 이름 기반 가상 호스트를 사용하겠다는 설정을 추가합니다. SSL이므로 포트명에 443을 추가해야 합니다.


NameVirtualHost *:443


그런 다음 <VirtualHost *:443> 항목의 ServerName, ServerAlias에 가상 호스트명을 넣고 사용할 SSLCertificateFile, SSLCertificateKeyFile 등 가상 호스트마다 달라져야 할 설정을 추가하면 됩니다. 단, SSL 가상 호스트는 HHTP 기반 가상 호스트와 달리 주의해야 할 점이 하나 있습니다.


서버 이름 표시(SNI; Server Name Indication)


앞에서 가상 호스트는 HTTP의 Host: 헤더를 이용해 웹 서버가 처리한다고 설명한 적이 있는데, 브라우저가 Host: 헤더를 웹 서버에 전송하는 것은 연결이 이뤄진 후에 가능합니다. 그런데 SSL은 HTTP보다 하위 레이어이므로 SSL 세션을 구축하는 과정은 HTTP 연결보다 먼저 이뤄집니다. 이 경우 SSL 핸드셰이크 단계 3에서 이미 서버의 SSL 인증서를 전송받았는데 브라우저가 요청하는 가상 호스트가 이미 받은 SSL 인증서에 있는 주소와 다를 경우 브라우저는 신뢰할 수 없는 사이트라고 판단합니다. 이는 SSL이 HTTP보다 하위 레이어라서 발생하는 현상이며, HTTP 프로토콜에서는 처리할 수 있는 방안이 없습니다.


SSL/TLS 표준에서는 이 문제를 해결하기 위해 SSL 핸드셰이크 내에 도메인 이름을 보내도록 표준이 확장됐고, 이 기능을 서버 이름 표시라고 한합니다. 그러므로 SSL 가상 호스트를 사용하려면 확장된 표준을 웹 서버, 웹 브라우저, 또는 사용하는 SSL 라이브러이에서 지원해야 합니다.


CentOS 6에 탑재된 아파치 웹 서버는 이 기능을 지원하므로 문제가 없고 윈도우 사용자는 비스타 이상 버전을 사용해야 문제가 없습니다. 자바의 경우 JDK 7이상이어야 서버이름표시 기능을 지원합니다.


참고)

웹서버는 주로정적 데이터를 처리하고 WAS 서버는 애플리케이션을 처리하도록 역할이 나뉘어 있지만 여전히 웹 서버는 매우 중요한 역할을 수행합니다. 그 중에서 가장 중요한 역할은 바로 고객과 WAS를 연결하는 게이트웨이로서의 역할입니다.


톰캣의 가상 호스트 사용과 연관된 리버스 프록시 방식은 연계하려는 WAS의 종류에 상관없이 아파치로 서비스할 수 있는 기법이니 확실히 익혀두어야 합니다.