SSL서비스 구축 및 OpenSSL (2007)

OpenSSL 개략

openssl을 이용하여 인증서 만들고 서명하는 방법
참고자료에서 openssl 에 대한 내용을 먼저 알고 있어야 이해할 수 있음.

문서변경내용

  • 2007.6.14 openssl 사용법 자세한 설명 및 웹서비스 연동 상세히 추가

참고자료

openssl

openssl 과 서비스연동

인증서 작업 개요

공인인증을 이용할 경우

  • 공인인증을 이용할 경우에는 스크립트나 명령을 이용하여 키를 생성하고 인증요청서를 생성한다. 여기서 생성한 CSR(certificate signing request)을 해당 기관에 보내 인증을 받은 공개키를 받고 CA의 공개키도 함께 받아 설치한다. 이 경우에는 자체 인증을 하는것이 아니므로 rootCA 는 만들지 않아도 된다.
  • rootCA를 이용하지 않고 공인인증기관을 이용할 경우 /usr/share/ssl/certs 의 Makefile을 이용하는 것이 편리하다.

자체인증을 이용할 경우

  • 공인인증이 필요없는 경우에는 직접 rootCA를 구축한다. rootCA를 구축할 경우에도 일반인증서를 만드는 것과 차이점은 거의 없으며 x509 옵션을 이용하여 자체 셀프사인한 것만 다르다.
  • 인증서 관리를 편리하게 하기 위해서는 자체 인증이 필요한 경우 인증서버를 한대두고 그 서버에서 자체 인증할 csr(certificate signing request)을 만들고 인증하는 것이 편리하다. 굳이 각 해당 도메인별로 rootCA를 따로 만들면 관리가 불편하고 생성한 key, csr도 한군데에서 관리하는것이 편리할 것이다.
  • openssl 명령에 익숙해지면 openssl 등에서 제공하는 스크립트를 이용하는 것보다는 직접 스크립트를 짜서 사용하는 것이 편리하다. 키파일 이름, 디렉토리가 제각각이기 때문이다.
  • rootCA를 구축할 경우 /usr/share/ssl/misc/CA 스크립트를 이용하는 것이 편리하다.

공인인증을 이용할 경우 초간단 사용법

  • 아래에서 키파일은 server.key 이며 로컬서버에 저장을 한다.
  • server.csr은 인증요청서이며 공인인증기관에 보내서 인증을 받아야 한다.
  • 인증을 받은 파일은 server.crt로 저장을 하고 server.csr은 필요없다.
  • 키를 만들때 -nodes 옵션을 주어서 개인키를 암호화하지 않은 경우이다. 유효기간은 365일로 하였다. subj 는 해당 인증서에 대한 정보로 여기서 도메인 tunelinux.pe.kr 을 사용하고자 하는 도메인 또는 이메일주소로 바꾸면 된다.
  • server.key , server.crt, 인증기관에서 받은 rootCA 인증키를 해당 응용프로그램에 따라 설정하면 된다.

    /usr/bin/openssl  req -new -nodes -keyout server.key -days 365 -out server.csr -subj "/C=KR/ST=Seoul/L=Guro/O=Samjung Data Service Co./OU=service/CN=tunelinux.pe.kr" 
    

openssl 사용법

openssl 설정 및 rootCA 구축하기

공인인증을 받을 필요가 없을 경우에는 자체서명된 root CA를 구축한다.
공인인증을 받는 경우에는 인증요청서 (CSR) 를 만들어서 공인인증기관에 보내 사인을 받은 후 사용하면 된다.

  • openssl 기본설정
    openssl 기본설정은 /usr/share/ssl/openssl.cnf 파일에 있다.
    아래 기본값을 바꾸어놓은 파일 openssl.cnf 여기서 common name 만 바꾸어서 사용하면 된다.

기본값중에서 인증서의 유효기간을 지정하는 옵션인 default_days 은 365일에서 더 늘려놓는 것이 관리상 편리할 것이다.
DN 입력하는 기본값을 넣어주면 편리하다. (openssl 명령행에서도 가능함)
인증서 생성시 옵션을 명령행에서 주지 않으면 일일이 나오는 질문에 답변을 해야하는데 작업을 자주 하는 경우는 매우 불편한 부분이다.
또 파일명이 헷갈릴 수 있기때문에 rootCA 서버 구축을 하는 경우 rootCA의 인증서(공개키) 이름을 다른 이름으로 바꾸어주었다.
이 파일명을 수정할 경우 CA 스크립트에서도 함께 수정해주어야 한다.

# diff openssl.cnf openssl.cnf.orig
43,44c43
< #certificate  = $dir/cacert.pem       # The CA certificate
< certificate   = $dir/samjung.rootca.crt       # The CA certificate
---
> certificate   = $dir/cacert.pem       # The CA certificate
64c63
< default_days  = 1825                  # how long to certify for
---
> default_days  = 365                   # how long to certify for
121c120
< countryName_default           = KR
---
> countryName_default           = GB
126c125
< stateOrProvinceName_default   = Seoul
---
> stateOrProvinceName_default   = Berkshire
129c128
< localityName_default          = guro
---
> localityName_default          = Newbury
132c131
< 0.organizationName_default    = Samjung Data Service Co.
---
> 0.organizationName_default    = My Company Ltd
139c138
< organizationalUnitName_default        = service
---
> #organizationalUnitName_default       =
142d140
< commonName_default            = tunelinux.pe.kr
146d143
< emailAddress_default          = joon@tunelinux.pe.kr
  • root CA 생성
    /usr/share/ssl/misc/CA 스크립트를 이용한다. CA 프로그램은 openssl을 편리하게 사용하기 위한 스크립트이다.
    일반인증서를 만들 경우에는 /usr/share/ssl/certs/Makefile 을 이용하는 것이 낫지만 root CA 생성시는 이 스크립트를 이용하는 것이 필요한 디렉토리까지 같이 생성해주므로 편리하다.

rootCA 관련한 작업은 기준디렉토리가 /usr/share/ssl/misc 이므로 이 디렉토리로 이동하여 모든 작업을 하면 된다. 다른 디렉토리에 있으면 디렉토리정보때문에 에러가 생긴다.
CA 스크립트에서 rootCA 인증서의 유효기간을 늘려놓고 공개키의 이름을 openssl.cnf 변경에 맞추어 함께 변경한다.
CACERT 파일명을 바꾸는 이유는 기본값으로 되어있으면 나중에 헷갈릴 수 있으며 사용하는 사이트에 맞추어 변경을 하는 것이다.

root CA 생성은 아래 디렉토리 사용함.
/usr/share/ssl/misc/demoCA

root CA 생성은 아래와 같다.

이전에 만들어놓은 rootca를 삭제하려면 먼저 아래와 같이 실행을 한다.
# cd /usr/share/ssl/misc/
# rm -rfv demoCA/

# diff CA CA.orig
33c33
< DAYS="-days 1825"
---
> DAYS="-days 365"
41c41
< CACERT=./samjung.rootca.crt
---
> CACERT=./cacert.pem

ca를 신규로 생성한다.
# ./CA -newca 
( openssl req -new -x509  -keyout /usr/share/ssl/misc/demoCA/private/cakey.pem \
-out /usr/share/ssl/misc/demoCA/cacert.pem -days 365 )

CA 스크립트에서 demoCA 디렉토리를 생성하고 ca를 위한 개인키, 공개키를 생성한다.
인증서의 유효기간은 쉘스크립트에서 DAYS를 이용해 지정하므로 이 부분을 필요에 따라 늘려놓으면 편리하다.

디렉토리 구조는 아래와 같다.

# tree /usr/share/ssl/misc/demoCA/
/usr/share/ssl/misc/demoCA/
|-- cacert.pem -> 공개키
|-- certs
|-- crl
|-- index.txt
|-- index.txt.old
|-- newcerts
|   `-- 01.pem
|-- private
|   `-- cakey.pem -> 개인키
|-- serial
`-- serial.old
  • 자체 서명 인증서 만들기
    자체 서명한 인증서는 -x509 옵션을 이용하여 만든다. 위에서 만든 root CA도 자체서명한 인증서이다.
    자체 서명하는 인증서는 별도로 공인인증을 받지 않고 사용할 경우 이용하면 된다. 위와 동일한 스크립트이지만 key 파일이름과 경로, 공개키파일의 이름과 경로만 다르다.

    ./CA -newcert
    또는 
     /usr/bin/openssl req -new  -keyout newreq.pem  -x509 -days 1825 -out newreq.pem
    또는
    cd  /usr/share/ssl/certs/Makefile/
    make server.crt  -> 여기서 앞의 파일명은 임의로 만들어도 된다.
    

    CA 스크립트나 make 파일을 이용해도 되고 openssl 명령을 이용해도 된다.

  • 인증요구서 만들기
    자체적으로 구축한 root CA를 이용하여 사인을 하려하거나 공인인증을 받으려고 하는 경우에는 인증요구서를 만들어야 한다.

    ./CA -newreq 
    또는 
    (openssl req -new -keyout newreq.pem -out newreq.pem -days 365) 
    
  • 키확인하기
    해당 키가 server.key 일 경우 아래와 같이 생성한 키를 확인할 수 있다.

    # openssl rsa -noout -text -in server.key
    
  • 인증요구서 확인하기
    csr 이 server.csr 일 경우 아래와 같이 확인한다.

    #openssl req -noout -text -in server.csr
    

아래 예제를 본다.

/usr/bin/openssl req -new -nodes -key /etc/httpd/conf/ssl.key/server.key -days 1825 \
-out /etc/httpd/conf/ssl.csr/server.csr

여기서는 개인키를 이미 만들어둔경우여서 -key 옵션을 사용하였다.
-nodes 옵션을 개인키를 만들때 암호화하지 않는 것이다. 키를 생성할 경우 비밀번호를 물어보는데 이렇게 하면 아파치 등 대몬 프로그램을 내리고 올릴때 비밀번호를 넣어주어야한다. 보안상 문제가 될 수 있지만 관리측면에서는 불편한 부분이므로 넣어서 사용하는 것이 좋을 듯하다.

-out 에 지정한 파일에 인증요구서가 만들어지고 ca 옵션을 이용하여 root CA로 사인을 하였다.

 openssl ca -out /etc/httpd/conf/ssl.crt/server.crt -infiles /etc/httpd/conf/ssl.csr/server.csr
  • crt 인증서 확인하기

    # openssl x509 -in /etc/httpd/conf/ssl.crt/server.crt -noout -text
    
  • rootCA 인증한 인증서 철회하기
    rootCA 인증을 받은 server.crt를 철회할 경우는 아래와 같이 하면 된다. index.txt에 인증서에 정보가 있다.
    R는 철회된 인증서, V는 유효한 인증서, E는 유효기간이 만료된 인증서를 뜻한다.
    아래에서 인증서를 철회하면서 V가 R로 바뀐 것을 확인할 수 있다.

다음으로 인증철회목록(Certificate Revoked List, CRL)을 업데이트한다.

# pwd
/usr/share/ssl/misc

# cat /usr/share/ssl/misc/demoCA/index.txt
V       080612041333Z           01      unknown /C=KR/ST=Seoul/O=Samjung Data Service Co./OU=service/CN=tunelinux.pe.kr

# openssl ca -revoke /etc/httpd/conf/ssl.crt/server.crt 

# cat /usr/share/ssl/misc/demoCA/index.txt
R       080612041333Z   070614005917Z   01      unknown /C=KR/ST=Seoul/O=Samjung Data Service Co./OU=service/CN=tunelinux.pe.kr

# openssl ca -gencrl  -out demoCA/crl/sopac-ca.crl
Using configuration from /usr/share/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:

인증서 생성시 주의사항

참고자료 : http://manual.anycert.co.kr/entry/Apache-2X-CSR-%EC%83%9D%EC%84%B1-%EA%B0%80%EC%9D%B4%EB%93%9C 에서 인용

  • Organization(영문회사명)에는 < > ~ ! @ # $ % ^ * / \ ( ) ? 등의 특수 문자를 넣을 수 없습니다. 사업자 등록증에 기재된 회사명과 일치하는 영문회사명을 넣어 주시기 바랍니다. (예: 사업자 등록증에 '닷네임 코리아'이면 dotname korea 으로 넣어주셔야 합니다. dotname만 넣으시면 않됩니다.)
    또한, 인증서를 설치할 Common Name(인증 받을 도메인 주소)에 해당하는 도메인의 등록정보를 반드시 참조하셔서 해당 등록정보에 기재된 회사명을 참고 하실 수 있겠습니다.
    영문 회사명은 소유하고 계신 도메인이 com/net/org인 경우에는 Network Solutions에서, kr인 경우에는 KRNIC에서 확인할 수 있습니다.
  • Common Name(인증 받을 도메인 주소)에는 IP 주소, 포트번호, 경로명, http:// 등을 포함할 수 없습니다.
  • 정보입력 과정에서 마지막에 나오는 Extra Attributes, 즉 A challenge password와 An optional company name은 입력하지 마시고 Enter키만 눌러주셔야 합니다. 두 항목에 내용을 입력하실 경우 잘못된 CSR이 생성될 수 있습니다.

입력예는 아래 참조

Country Name (국가코드) : KR
State or Province Name (시/도) : Seoul
Locality Name (구/군) : Songpa
Organization Name (회사명) : Dotname Korea
Organizational Unit Name (부서명) : Digital Certificate Team
Common Name (인증 받을 도메인 주소) : www.anycert.co.kr
Email Address :
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password :
An optional company name : 

제공스크립트 이용하기

public/private key 쌍을 만들거나 (pem 으로 저장), SSL 인증 사인 요청서 (CSR), 자체 사인한 테스트 인증서 작성등에 사용할 수 있으며 apache ssl 연동에도 사용할 수 있다.
스크립트 예제를 보면 된다. 해당 스크립트에서 일부 옵션을 조정하여 사용하면 되는데 -days 등의 옵션이 여기에 해당할 것이다.

일반적인 경우라면 위의 스크립트로 충분하다. csr을 만들때 nodes 옵션정도를 조정하면 편리할 것이다.

  • /usr/share/ssl/certs/Makefile 스크립트 이용하기

    .PHONY: usage
    .SUFFIXES: .key .csr .crt .pem
    .PRECIOUS: %.key %.csr %.crt %.pem
    
    usage:
            @echo "This makefile allows you to create:"
            @echo "  o public/private key pairs"
            @echo "  o SSL certificate signing requests (CSRs)"
            @echo "  o self-signed SSL test certificates"
            @echo
            @echo "To create a key pair, run \"make SOMETHING.key\"."
            @echo "To create a CSR, run \"make SOMETHING.csr\"."
            @echo "To create a test certificate, run \"make SOMETHING.crt\"."
            @echo "To create a key and a test certificate in one file, run \"make SOMETHING.pem\"."
            @echo
            @echo "To create a key for use with Apache, run \"make genkey\"."
            @echo "To create a CSR for use with Apache, run \"make certreq\"."
            @echo "To create a test certificate for use with Apache, run \"make testcert\"."
            @echo
            @echo Examples:
            @echo "  make server.key"
            @echo "  make server.csr"
            @echo "  make server.crt"
            @echo "  make stunnel.pem"
            @echo "  make genkey"
            @echo "  make certreq"
            @echo "  make testcert"
    
    %.pem:
            umask 77 ; \
            PEM1=`/bin/mktemp /tmp/openssl.XXXXXX` ; \
            PEM2=`/bin/mktemp /tmp/openssl.XXXXXX` ; \
            /usr/bin/openssl req -newkey rsa:1024 -keyout $$PEM1 -nodes -x509 -days 365 -out $$PEM2 ; \
            cat $$PEM1 >  $@ ; \
            echo ""    >> $@ ; \
            cat $$PEM2 >> $@ ; \
            $(RM) $$PEM1 $$PEM2
    
    %.key:
            umask 77 ; \
            /usr/bin/openssl genrsa -des3 1024 > $@
    
    %.csr: %.key
            umask 77 ; \
            /usr/bin/openssl req -new -key $^ -out $@
    
    %.crt: %.key
            umask 77 ; \
            /usr/bin/openssl req -new -key $^ -x509 -days 365 -out $@
    
    KEY=/etc/httpd/conf/ssl.key/server.key
    CSR=/etc/httpd/conf/ssl.csr/server.csr
    CRT=/etc/httpd/conf/ssl.crt/server.crt
    
    genkey: $(KEY)
    certreq: $(CSR)
    testcert: $(CRT)
    
    $(CSR): $(KEY)
            umask 77 ; \
            /usr/bin/openssl req -new -key $(KEY) -out $(CSR)
    
    $(CRT): $(KEY)
            umask 77 ; \
            /usr/bin/openssl req -new -key $(KEY) -x509 -days 365 -out $(CRT)
    

apache 와 연동하는 경우 키파일은 다음과 같다.
KEY=/etc/httpd/conf/ssl.key/server.key
CSR=/etc/httpd/conf/ssl.csr/server.csr
CRT=/etc/httpd/conf/ssl.crt/server.crt

기존 파일을 지우려면 다음과 같이 한다.

 rm -fv /etc/httpd/conf/ssl.crt/server.crt /etc/httpd/conf/ssl.csr/server.csr /etc/httpd/conf/ssl.key/server.key

Makefile 에서 편리하게 생성을 해주고 자동으로 파일을 복사해준다.
make genkey : 키생성 . 키는 따로 생성하지 않아도 아래 명령어에서 자동으로 생성해줌
make certreq : CSR 생성. root CA 로 사인하거나 공인인증을 받으려고 하는 경우 필요
make testcert : 자체 사인한 인증서 생성

key(키), csr(CSR), crt(자체사인한 인증서), pem (키와 인증서를 파일 하나로 만듬) 등 확장자에 따라 자동으로 생성해주므로 편리하다.

csr이나 crt 파일을 만들면 key파일은 자동으로 Makefile에서 만들어준다.
처음 아파치를 rpm으로 설치하고 새롭게 인증서파일을 만들 경우에는 기존의 파일을 먼저 지워준다.
CSR은 공인인증을 받을경우 이용하면 되고 자체사인한 인증서를 사용하려면 CRT를 이용하면 된다.
참고로 위 스크립트에서 보듯이 기본 유효기간이 365일이므로 더 늘려서 사용하는것이 운영상 편리할 것이다.

보안설정

개인키는 위험에 노출되지 않도록 안전한 곳에 보관을 한다.

# ll /usr/share/ssl/misc/demoCA/private/
total 4
-rw-------  1 root root 963 Dec 28 13:55 cakey.pem
# ll /etc/httpd/conf/ssl.key/
total 4
-rw-------  1 root root 963 Dec 28 14:01 server.key

openssl 주요명령어 설명

주요 명령어

openssl 상세한 사용법은 해당 man page 를 봐야한다.

  • genrsa : RSA 개인키생성
  • rsa : RSA 키 처리 프로그램. 개인키의 암호화를 없앨 경우 사용할 수 있음
  • req : X.509 Certificate Signing Request (CSR) Management (man openssl) . 인증서 생성시 사용
  • ca : Certificate Authority (CA) Management (man openssl) . ca에서 사용
  • req 에 대한 상세설명은 man req 을 참고한다.

genrsa

  • -des3 : 개인키 암호화. 이 옵션을 빼면 개인키를 암호화하지 않아서 비밀번호를 물어보지 않는다.

req

  • -new : 인증 요청서 생성
    this option generates a new certificate request. It will prompt the user for the relevant field values. The actual fields prompted for and their maximum and minimum sizes are specified in the configuration file and any requested extensions. If the -key option is not used it will generate a new RSA private key using information specified in the configuration file
  • -key : 읽어들일 개인키 지정. 개인키를 미리 생성하여 사용할 경우에 필요함
    This specifies the file to read the private key from. It also accepts PKCS#8 format private keys for PEM format files.
  • -keyout : 새로 생성할 개인키 파일명 지정
    this gives the filename to write the newly created private key to. If this option is not specified then the filename present in the configura-tion file is used.
  • -out : 공개키 파일 명 지정
    This specifies the output filename to write to or standard output by default.
  • -days : 인증서 유효기간. 기본값은 30일임
    when the -x509 option is being used this specifies the number of days to certify the certificate for. The default is 30 days.
  • -x509 : 인증요청서를 만드는 대신에 자체 사인한 인증서를 만듬. 보통 테스팅용 인증서를 만들거나 root CA를 만들 경우에 필요함.
    this option outputs a self signed certificate instead of a certificate request. This is typically used to generate a test certificate or a self signed root CA. The extensions added to the certificate (if any) are specified in the configuration file. Unless specified using the set_serial option 0 will be used for the serial number.
  • -subj : DN 내용을 미리 입력할 수 있음.
    sets subject name for new request or supersedes the subject name when processing a request. The arg must be formatted as /type0=value0/type1=value1/type2=..., characters may be escaped by \ (backslash), no spaces are skipped.
    예제 : /usr/bin/openssl req -new -subj '/CN=tunelinux.pe.kr/O=samjung/C=KO/ST=gurogu/L=seoul' -keyout newreq.pem -x509 -days 1825 -out newreq.pem
  • -nodes : 개인키 암호화를 하지 않는다. 대몬프로그램을 올리고 내릴때 편리하다.
    if this option is specified then if a private key is created it will not be encrypted.

ca

  • -infiles : 인증요청서(csr) 파일명
    if present this should be the last option, all subsequent arguments are assumed to the the names of files containing certificate requests.
  • -out : 생성할 인증서 파일
  • -revoke : 인증을 철회할 파일명
  • -gencrl : this option generates a CRL based on information in the index file.

인증서 서비스에 활용

자체사인한 ssl 인증서 생성 스크립트

self 사인한 ssl 인증서를 생성하는 스크립트이다. 자체생성하여 만든 개인키는 /usr/local/direct/ssl 에 보관하고 CA에서 받은 인증서파일은 cacerts 하위 디렉토리에 보관한다.
이것을 가지고 apache, ldap 등에서 연동하여 사용한다.
openldap 에서는 /usr/local/direct/ssl/cacerts/ 디렉토리를 /etc/openldap/cacerts/ 디렉토리로 심볼릭 링크하여 사용한다.

#!/bin/bash
# joon
# 자체 사인한 인증서를 생성하며 만료기간은 1825일(5년)으로 해 두었다.
# 프라이비트키는 root로 두어야하지만 ldap 사용자가 읽어야 하기에 ldap 사용자 계정으로 바꾸어주었다.
KEY_NAME='wiki.tunelinux.pe.kr'
KEY_DIRECTORY=/usr/local/direct/ssl
CA_DIRECTORY=$KEY_DIRECTORY/cacerts
PUBLIC_KEY=$CA_DIRECTORY/$KEY_NAME.crt
PRIVATE_KEY=$KEY_DIRECTORY/$KEY_NAME.key
DAYS="1825"

[ -f $PUBLIC_KEY ] && mv -fv $PUBLIC_KEY $PUBLIC_KEY.orig
[ -f $PRIVATE_KEY ] && mv -fv $PRIVATE_KEY $PRIVATE_KEY.orig

[ ! -d $KEY_DIRECTORY ] && mkdir -p $KEY_DIRECTORY
[ ! -d $CA_DIRECTORY ] && mkdir -p $CA_DIRECTORY

ln -s $CA_DIRECTORY /etc/openldap/cacerts

SUBJ='/C=KR/ST=gurogu/L=seoul/O=samjung/OU=itservice/CN='$KEY_NAME

/usr/bin/openssl req -new -nodes -keyout $PRIVATE_KEY -x509 -days $DAYS -out $PUBLIC_KEY -subj $SUBJ

/bin/chmod 644 $PUBLIC_KEY*
/bin/chown ldap.ldap $PRIVATE_KEY
/bin/chmod 400 $PRIVATE_KEY*

/etc/init.d/ldap restart
/etc/init.d/httpd stop && /etc/init.d/httpd startssl
/usr/sbin/cacertdir_rehash $CA_DIRECTORY

위와 같은 작업을 한후 /etc/openldap/slapd.conf 에서 다음과 같이 설정한다.

TLSCipherSuite HIGH:MEDIUM:+SSLv2
TLSCACertificateFile /usr/local/direct/ssl/cacerts/wiki.tunelinux.pe.kr.crt
TLSCertificateFile /usr/local/direct/ssl/cacerts/wiki.tunelinux.pe.kr.crt
TLSCertificateKeyFile /usr/local/direct/ssl/wiki.tunelinux.pe.kr.key

사용자 인증으로 ldap 을 사용할 경우 /etc/ldap.conf 에서 tls_cacertdir 이 /etc/openldap/cacerts 로 지정되어 있는 경우 cacertdir_rehash 명령을 실행해주어야 한다.

/usr/sbin/cacertdir_rehash /etc/openldap/cacerts/

웹서버설정에서는 아래과 같이 지정한다.
/etc/httpd/conf.d/ssl.conf

SSLCertificateFile /usr/local/direct/ssl/cacerts/wiki.tunelinux.pe.kr.crt
SSLCertificateKeyFile /usr/local/direct/ssl/wiki.tunelinux.pe.kr.key
SSLCACertificateFile /usr/local/direct/ssl/cacerts/wiki.tunelinux.pe.kr.crt

여기에서 wiki.tunelinux.pe.kr.crt 파일은 공인인증을 받지 않았으므로 윈도우에서 crt 파일을 클릭한 경우 인증서가져오기(확장자를 .crt로 하면 됨)를 실행하여 인증서를 저장하면 된다.
그러면 웹브라우즈에서도 인증서 설치한 이후에는 편리하게 사용할 수 있다.

위에서 만약 사설인증이 아니라 공인인증을 이용했을 경우 ldap 에서 TLSCACertificateFile, 아파치에서 SSLCACertificateFile 파일만 달라질 것이다.

아래는 아파치에서 자체적으로 만든 rootCA를 이용하여 별도로 crt 파일을 만든 경우이며 공인인증을 이용했을 경우에는 csr을 보내 인증받을 인증서를 SSLCertificateFile 에 넣고 SSLCACertificateFile 만 공인인증기관의 것을 이용하면 된다.

SSLCertificateFile /tmp/test/crt/tunelinux.pe.kr.crt
SSLCertificateKeyFile /tmp/test/key/tunelinux.pe.kr.key
SSLCACertificateFile /usr/share/ssl/misc/demoCA/cacert.pem

여기에서 mirror.crt 파일은 공인인증을 받지 않았으므로 윈도우에서 crt 파일을 클릭한 경우 인증서가져오기(확장자를 .crt로 하면 됨)를 실행하여 인증서를 저장하면 된다.
그러면 웹브라우즈에서도 인증서 설치한 이후에는 편리하게 사용할 수 있다.

apache 에서 ldap인증을 사용할 경우

apache 에서 ldap 인증을 사용하는 경우에는 아래 내용이 httpd.conf에 있어야한다.
CA키만 적절한 것으로 바꾸어주면 된다.

LDAPTrustedCA /usr/share/ssl/misc/demoCA/cacert.pem
LDAPTrustedCAType BASE64_FILE

이제 htaccess 파일에서 아래와 같이 지정을 하면 된다.

# cat .htaccess
AuthType Basic
AuthName "Samjung Staff Only"
AuthLDAPBindDN cn=readonly,ou=admingroup,dc=samjung,dc=com
AuthLDAPBindPassword readonly
AuthLDAPURL ldaps://xxxx.direct.co.kr/ou=people,dc=samjung,dc=com?uid?sub?(objectClass=*)
require valid-user

주소록

아웃룩등의 주소록에서는 기타 설정에서 SSL사용을 체크해주면 된다.

ldapadmin 프로그램

자체서명해서 사용하면 ldapadmin 에서는 셀프사인한 root 인증서라는 주의사항이 나온다. 이것은 불편해서 그냥 사용을 해야 할 듯하다.

스크립트 이용하여 처리하기 (csr 인증요청서 및 자체 rootCA 인증)

인증서 처리 방법

모든 인증서는 intranet 에서 관리를 한다.
/usr/local/direct/SSL_KEY_STORE/ 디렉토리에 key, csr, crt 등을 보관한다.
intranet 에 자체 rootCA 인증을 구성하여 자체 사인한 인증서가 필요할 경우 활용을 한다.
아래 두개의 스크립트는 /usr/local/direct/scripts 에 있다.

CSR 인증요청서 만들어서 처리하기

아래는 CSR (인증요청서)를 만드는 스크립트이다.
해당 도메인에 대하여 dns에 등록되어있는지 확인을 한다.
만약 키파일이나 CSR파일이 있는 경우는 백업하고 진행하거나 중지하거나 백업하지 않고 새로운 파일을 만들 수 있도록 한다.
키, csr 파일 생성시 nodes 옵션을 이용하여 개인키 비밀번호를 설정하지 않았다.

# CSR 생성요청 스크립트

if [ $# -lt 1 ]
then
        echo "CSR을 생성할 도메인명을 입력하십시요"
        echo "사용방법 : $0 domain"
        exit
fi

# 신청할 도메인명
KEY_NAME=$1

# 키보관 디렉토리. 개인키는 key, 인증요구서는 csr,인증받은 인증서는 crt, CA 인증서는 cacerts 디렉토리에 넣어둠
SSL_KEY_STORE=/usr/local/direct/SSL_KEY_STORE
KEY_DIRECTORY=$SSL_KEY_STORE/key
CSR_DIRECTORY=$SSL_KEY_STORE/csr
CRT_DIRECTORY=$SSL_KEY_STORE/crt
CA_DIRECTORY=$SSL_KEY_STORE/cacerts

CSR_FILE=$CSR_DIRECTORY/$KEY_NAME.csr
KEY_FILE=$KEY_DIRECTORY/$KEY_NAME.key

# 인증서 유효기간
DAYS="365"

# 이전 인증파일을 현재 년월일-시분초기준으로 백업함
# %F     same as %Y-%m-%d
# %T     time, 24-hour (hh:mm:ss)
NOW=`date +%F-%T`

# openssl 프로그램 경로
OPENSSL_CMD="/usr/bin/openssl"

# directory 생성
[ ! -d $KEY_DIRECTORY ] && mkdir -p $KEY_DIRECTORY
[ ! -d $CSR_DIRECTORY ] && mkdir -p $CSR_DIRECTORY
[ ! -d $CRT_DIRECTORY ] && mkdir -p $CRT_DIRECTORY
[ ! -d $CA_DIRECTORY ] && mkdir -p $CA_DIRECTORY

# 등록되어 있는 도메인인지 확인을 합니다
/usr/bin/host $KEY_NAME | grep "not found" && echo "경고 : $KEY_NAME 도메인은 dns에 등록되어 있지 않습니다. 정상적인 사용을 위해서는 도메인 등록을 해야합니다"

if [ ! -f $KEY_FILE ]
then
        $OPENSSL_CMD genrsa -out $KEY_FILE 1024

#       echo "기존에 키파일이 존재합니다. 백업을 하고 새로 생성을 하려면 y를 누르세요. n를 누르면 더이상 진행하지 않습니다. 그냥 엔터를 치면 백업을 하지 않고 새로운 키를 생성합니다."
#
#       read remove_key
#       case "$remove_key" in
#               Y|y) mv -fv $KEY_FILE $KEY_FILE.$NOW ;
#                    echo "기존 $KEY_FILE 을 $KEY_FILE.$NOW 로 백업하였습니다" ;;
#               N|n) echo "실행을 멈춥니다";
#                    exit;;
##              *) echo "$KEY_NAME 에 대한 새로운 key 파일을 생성합니다." ;;
#       esac
fi


if [ -f $CSR_FILE ]
then
        echo "CSR 파일이 존재합니다. n을 누르면 더이상 진행하지 않습니다. 엔터를 치면 백업을 하고 새로운 키를 생성합니다."

        read remove_key
        case "$remove_key" in
#               Y|y) mv -fv $CSR_FILE $CSR_FILE.$NOW ;
#               Y|y) mv -fv $CSR_FILE $CSR_FILE.0 ;
#                    echo "기존 $CSR_FILE 을 $CSR_FILE.0 로 백업하였습니다" ;;
                N|n) echo "실행을 멈춥니다";
                     exit;;
                *)  mv -fv $CSR_FILE $CSR_FILE.0 ;;
#                   echo "$KEY_NAME 에 대한 새로운 CSR 파일을 생성합니다.";;
        esac
fi


# 생성할 인증서에 대한 정보
SUBJ="/C=KR/ST=Seoul/L=Guro/O=Samjung Data Service Co./OU=service/CN=$KEY_NAME"
#SUBJ="/C=KR/ST=Seoul/L=Guro/O=SamjungDataServiceCo/OU=service/CN=$KEY_NAME"


# 인증서 생성
#$OPENSSL_CMD req -new -keyout $KEY_FILE -days $DAYS -out $CSR_FILE -subj "$SUBJ" || exit
$OPENSSL_CMD req -new -nodes -key $KEY_FILE -days $DAYS -out $CSR_FILE -subj "$SUBJ" || exit

# 파일퍼미션 조정
/bin/chmod 400 $KEY_FILE
/bin/chmod 644 $CSR_FILE

echo "==================================================================================================="
echo "인증요청서를 정상적으로 생성하였습니다!"
#echo "$KEY_DIRECTORY 에 key, csr, crt, CA 인증서등을 보관하면 편리합니다."
echo "KEY(개인키)는 $KEY_FILE 입니다."
echo "비밀번호를 생성하여 개인키를 만들었을 경우 비밀번호를 반드시 기억해두셔야 하며 안전한 곳에 보관하시기 바랍니다. 또한 일반사용자가 읽지못하도록 해야 합니다."
echo ""
echo "CSR(인증요청서)는 $CSR_FILE 입니다. 원하는 인증기관에 보내서 인증을 받아야 합니다"

자체 rootCA 인증서로 인증할때 사용하는 스크립트(인증서 생성 및 인증서 철회하기)

자체 rootCA 인증서버를 구축하고 위에서 만든 키를 이용하여 인증을 한다. 자체 테스팅용으로 필요할 수가 있다.
자체사인한 경우이므로 days 에서 유효기간은 1825로 길게 주었다.

# cat /usr/local/direct/scripts/rootca_certs.sh

#!/bin/bash
# joon
# CSR 생성요청 스크립트

if [ $# -lt 2 ]
then
        echo "셀프사인, 인증서철회를 할 도메인명을 입력하십시요"
        echo "rootCA 인증하기 : $0 sign domain "
        echo "rootCA 인증서철회 : $0 revoke domain "
        exit
fi

# 신청할 도메인명
ACT=$1
KEY_NAME=$2

# 키보관 디렉토리. 개인키는 key, 인증요구서는 csr,인증받은 인증서는 crt, CA 인증서는 cacerts 디렉토리에 넣어둠
SSL_KEY_STORE=/usr/local/direct/SSL_KEY_STORE
KEY_DIRECTORY=$SSL_KEY_STORE/key
CSR_DIRECTORY=$SSL_KEY_STORE/csr
CRT_DIRECTORY=$SSL_KEY_STORE/crt
CA_DIRECTORY=$SSL_KEY_STORE/cacerts

rootCA_DIRECTORY="/usr/share/ssl/misc"

CSR_FILE=$CSR_DIRECTORY/$KEY_NAME.csr
KEY_FILE=$KEY_DIRECTORY/$KEY_NAME.key
CRT_FILE=$CRT_DIRECTORY/$KEY_NAME.crt

# 인증서 유효기간
DAYS="1825"

# 이전 인증파일을 현재 년월일-시분초기준으로 백업함
# %F     same as %Y-%m-%d
# %T     time, 24-hour (hh:mm:ss)
NOW=`date +%F-%T`

CSR_SCRIPTS="csr_create.sh"

# openssl 프로그램 경로
OPENSSL_CMD="/usr/bin/openssl"


INDEX_FILE="$rootCA_DIRECTORY/demoCA/index.txt"
CRL_FILE="$rootCA_DIRECTORY/demoCA/crl/sopac-ca.crl"

[ ! -f $INDEX_FILE ]  && echo "$INDEX_FILE 이 없습니다. rootCA 등록이 안되어 있을 가능성이 높습니다" && exit

[ ! -f $CSR_FILE ] && echo "csr 파일이 없습니다. 먼저 $CSR_SCRIPTS 를 이용하여 인증요청서를 생성해야 합니다." && exit

cd $rootCA_DIRECTORY

if [ $ACT = "sign" ]
then
        grep "$KEY_NAME" $INDEX_FILE | grep "^V" && echo "이미 등록되어 있습니다. 기존의 인증서를 철회해야 합니다" && exit

        # 인증서 생성
        $OPENSSL_CMD ca -out $CRT_FILE -infiles $CSR_FILE || exit

        echo "==================================================================================================="
        echo "$CRT_FILE 을 정상적으로 생성하였습니다!"
        echo ""

fi

if [ $ACT = "revoke" ]
then
        [ ! -f $CRT_FILE ]  && echo "$CRT_FILE 이 없습니다. 셀프사인한 인증서를 만들지 않았을 가능성이 높습니다" && exit

        # 도메인이 없는 경우
        grep $KEY_NAME $INDEX_FILE
        if [ $? -ne 0 ]
        then
                echo "$INDEX_FILE 에 등록된 도메인이 없습니다"
                exit
        fi

#       grep "$KEY_NAME" $INDEX_FILE | grep "^R"
#       if [ $? -eq 0 ]
#       then
#               echo "이미 철회된 인증서입니다"
#               exit
#       fi

        $OPENSSL_CMD ca -revoke $CRT_FILE || exit
        $OPENSSL_CMD ca -gencrl -out $CRL_FILE || exit

        echo "==================================================================================================="
        echo "$CRT_FILE 에 대한 인증을 철회하였습니다!"
        echo ""
fi

apache ssl 세팅하기

  • openssl 확인
    openssl은 rpm으로 설치확인을 한다.
  • apache mod_ssl 확인
    Apache 웹서버는 두가지 방식의 모듈 설치를 지원하므로 statically linking module, DSO(Dynamic Shared Objects) module 로 설치된 모듈을 확인할 수 있습니다.
    $HTTPD 변수는 아파치 설치 디렉토리를 가르킵니다.
    • statically linking module 로 설치된 mod_ssl 모듈확인

      # /usr/local/apache/bin/httpd -l | grep mod_ssl
        mod_ssl.c
      
    • DSO module 로 설치된 mod_ssl 모듈확인

      # /usr/local/apache/bin/httpd -l | grep mod_so
        mod_so.c
      
      # ll /usr/local/apache/modules/ | grep ssl
      -rwxr-xr-x  1 root root  155624 Aug 13  2006 mod_ssl.so
      

      웹서버에 설치된 mod_so.c 를 확인하고 dso 모듈로 설치된 mod_ssl.so를 확인하면 됩니다.

  • CSR 생성 및 인증받기
    위의 내용 참고
  • 네트워크 확인사항
    SSL을 적용하면 기본 443 포트를 사용한다. 그러므로 방화벽에서 443 포트에 대한 접근을 허용해야한다.
    추가로 한대의 서버에서 여러개의 SSL 웹서비스를 하는 경우는 각 SSL 서비스별로 별도 포트를 지정해야한다.
  • 인증받은후 인증서 설치하기
    인증받은 인증서는 보통 도메인명.crt 형태이다. 또한 공인인증기관의 rootCA 인증서가 같이 온다.
    해당 crt 파일을 윈도우에서 더블클릭하여 열어보면 내용을 확인할 수 있다.

아파치의 conf/ssl.conf 에서 ssl 설정을 한다.

SSL Virtual Host Context 부분이 ssl 가상호스팅 설정을 하는 부분이다.

중요한 부분은 아래의 세줄이다.
SSLCertificateFile 은 인증받은 도메인이름으로 된 인증서(crt 파일),
SSLCertificateKeyFile 은 CSR 파일생성할때 먼저 생성한 개인키파일
SSLCACertificateFile 은 인증받은 기관에서 받은 인증서를 넣으면 된다.

SSLCertificateFile /usr/local/direct/ssl/tunelinux.pe.kr.crt
SSLCertificateKeyFile /usr/local/direct/ssl/tunelinux.pe.kr.nodes.key
SSLCACertificateFile /usr/local/direct/ssl/cacerts/QuickTrustSSL_Bundle.crt

실제 설정예

<VirtualHost tunelinux.pe.kr:443>
DocumentRoot "/usr/local/apache/htdocs"
ServerName tunelinux.pe.kr:443
ServerAdmin you@example.com
#ErrorLog /usr/local/apache/logs/error_log
#TransferLog /usr/local/apache/logs/access_log

SSLCertificateFile /usr/local/direct/ssl/tunelinux.pe.kr.crt
SSLCertificateKeyFile /usr/local/direct/ssl/tunelinux.pe.kr.nodes.key
SSLCACertificateFile /usr/local/direct/ssl/cacerts/QuickTrustSSL_Bundle.crt


SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
</VirtualHost>

이제 아파치 프로그램을 시작하여 확인해보면 된다.

bin/apachectl startssl 
또는 
bin/apachectl -D -SSL -k start 

log/error_log 파일을 확인해서 문제가 있는지 확인을 한다.

  • 프로세서 확인

    # ps auxw | grep http
    root     12681  0.0  1.0  7540 2636 ?        Ss   13:58   0:00 /usr/local/apache/bin/httpd -k start -DSSL
    nobody   12682  0.0  0.9  7888 2464 ?        S    13:58   0:00 /usr/local/apache/bin/httpd -k start -DSSL
    nobody   12683  0.0  0.9  7888 2460 ?        S    13:58   0:00 /usr/local/apache/bin/httpd -k start -DSSL
    
    # netstat -atn | egrep ":80|:443"
    tcp        0      0 :::80                       :::*                        LISTEN
    tcp        0      0 :::443                      :::*                        LISTEN
    
  • 여러개의 서버 가상호스팅하는 경우
    이경우에는 각 호스트별로 포트를 다르게 해야한다.
    아래 설정을 참고한다.
    원래의 파일에서 일부 순서를 조정하였다.
    FilesMatch, Directory, SetEnvIf, CustomLog 부분은 원래 가상호스팅설정에 있는 부분인데 공동으로 써도 되는 내용이며 빼놓아도 잘 작동한다.
# grep -v "^#" ssl.conf 
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
<IfDefine SSL>
Listen 443
Listen 444

AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl

SSLPassPhraseDialog  builtin

SSLSessionCache         dbm:/usr/local/apache/logs/ssl_scache
SSLSessionCacheTimeout  300

SSLMutex  file:/usr/local/apache/logs/ssl_mutex

<FilesMatch "\.(cgi|shtml|phtml|php3?)$">
    SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/usr/local/apache/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>

SetEnvIf User-Agent ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

CustomLog /usr/local/apache/logs/ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

<VirtualHost tunelinux.pe.kr:444>
DocumentRoot "/usr/local/apache/htdocs"
ServerName tunelinux.pe.kr:444
ServerAdmin you@example.com

SSLCertificateFile /usr/local/direct/ssl/tunelinux.pe.kr.crt
SSLCertificateKeyFile /usr/local/direct/ssl/tunelinux.pe.kr.nodes.key
SSLCACertificateFile /usr/local/direct/ssl/cacerts/QuickTrustSSL_Bundle.crt

SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
</VirtualHost>

<VirtualHost ssl.tunelinux.pe.kr:443>
DocumentRoot "/usr/local/apache/cent4"
ServerName ssl.tunelinux.pe.kr:443
ServerAdmin you@example.com

SSLCertificateFile /usr/local/direct/ssl/ssl.tunelinux.pe.kr.crt
SSLCertificateKeyFile /usr/local/direct/ssl/ssl.tunelinux.pe.kr.nodes.key
SSLCACertificateFile /usr/local/direct/ssl/cacerts/QuickTrustSSL_Bundle.crt

SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
</VirtualHost>

</IfDefine>

참고사항

개인키의 비밀번호 암호화 없애기

csr 생성시 nodes 옵션을 이용하거나 이미 생성된 개인키에서 비밀번호를 없앨 수 있다.
그래야 부팅시에 웹서버(또는 ldap 등 다른서버)가 패스워드 입력없이 정상적으로 동작한다.
개인키 파일 또는 개인키가 포함된 server.eky 파일을 가지고 다음의 명령을 통해 비밀문구를 제거할 수 있다.
같은 키파일에 nodes라는 것을 추가하여 알아보기 쉽도록 추가하였다.

openssl rsa -in server.key -out server-nodes.key 

위 작업을 거치면 비밀문구가 제거된 server-nodes.key 이름의 개인키 파일이 생길 것이다.
이 파일에는 비밀문구가 빠졌기 때문에 보안상 대단히 위험하다. 때문에 이에 대한 조치를 취해야 한다.
예를 들어 파일 권한을 변경해서 관리자만 볼 수 있게 한다든지 등의 조치가 필요하다.
만약 이 파일이 누출된다면 여러분의 사이트는 망가지게 될 것이다.

한개의 인증서에 여러개의 도메인 설정하기

CSR 생성시 cn 이름을 여러개 넣어도 작동은 한다.
공인인증기관에서 해주는지는 모르겠으며 이런 방식을 이용하여 서비스를 하는곳도 있다.
이에 대해서는 KISA에서 나온 보안서버구축가이드를 참고한다.

openssl req -new -nodes -keyout cent34.key -days 365 -out cent34.csr \
-subj '/C=KR/ST=Seoul/L=Guro/O=Samjung Data Service Co./OU=service/CN=tunelinux.pe.kr/CN=ssl.tunelinux.pe.kr'

디렉토리경로

인증서를 관리하는 인트라넷에서는 /usr/local/direct/SSL_KEY_STORE/ 디렉토리에 key, csr, crt를 나누어서 보관을 한다.
실제 이용하는 서버에서는 /usr/local/direct/ssl/ 디렉토리에 key, crt 를 보관하고 /usr/local/direct/ssl/cacerts 디렉토리에 CA에서 받은 인증서를 저장한다.