apache httpd 에 SSL/HTTPS 적용 및 VirtualHost 에 SNI(Server Name Indication) 문제 해결


사전 작업

  1. 먼저 SSL 인증서를 발급 받아야 한다. Self Signed CA 를 구성하려면 OpenSSL 로 ROOT CA 생성 및 SSL 인증서 발급 를 참고하여 SSL 인증서를 생성한다.
  2. apache web server 용 SSL 모듈인 mod_ssl 을 설치한다.

    yum install mod_ssl -y


아파치 웹서버 에 SSL 적용


갖고 있는 SSL 인증서와 개인키는 /etc/pki/tls/certs/lesstif.com.crt, /etc/pki/tls/private/lesstif.com.key  라고 가정한다.


  1.  vi /etc/httpd/conf.d/ssl.conf 

  2. 이름 기반 가상호스트를 사용하겠다는 설정인 NameVirtualHost 를 추가한다. 

    NameVirtualHost *:443 
  3. SSL 을 적용할 VirtualHost 를 설정한다.

    <VirtualHost *:443>
      ServerName lesstif.com
      ServerAlias www.lesstif.com
      
      SSLEngine on
      SSLProtocol all -SSLv2
      SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
     
      ## 위에서 생성한 SSL 인증서와 개인키
      SSLCertificateFile /etc/pki/tls/certs/lesstif.com.crt
      SSLCertificateKeyFile /etc/pki/tls/private/lesstif.com.key
      SSLCACertificateFile /etc/pki/tls/certs/lesstif-rootca.crt
     
      ## 
      <Files ~ "\.(cgi|shtml|phtml|php3?)$">
                SSLOptions +StdEnvVars
            </Files>
            <Directory "/var/www/cgi-bin">
                SSLOptions +StdEnvVars
            </Directory>
      SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
      ErrorLog logs/example.com-ssl_error_log
      TransferLog logs/example.com-ssl_access_log
      LogLevel warn
      CustomLog logs/example.com-ssl_request_log \
       "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
    </VirtualHost>
  4. service httpd restart
  5. Web browser에서 https 로 연결해서 제대로 보이는지 확인한다.

SELinux 주의 사항

분명히 파일이 있는데 httpd 가 인증서나 개인키를 못 찾을 경우 SELinux context 문제이다.  restorecon 명령어로 context 를 복구해준다.

restorecon -R /etc/pki/tls/private/
restorecon -R /etc/pki/tls/certs

Browser 에 신뢰하는 인증서 추가

Chrome

  1. 연결 -> 인증정보 클릭
  2. 향후 추가

VirtualHost 관련 issue

문제

여러 도메인의 사이트를 VirtualHost 기능을 이용하여 SSL 로 제공할 경우 다음과 같은 문제가 있다.

  • VirtualHost 는 Web Browser가 WebServer에서 HTTP 요청시 다음과 같이 Host Header를 전송

    * Connected to lesstif.com port 80 (#0)
    > GET / HTTP/1.1
    > User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
    > Host: lesstif.com

  • Web Server는 Host 에 있는 요청을 보고 VirtualHost 에 설정된 resource 를 Browser 에 전송
  • Browser가 Host Header 를 보내기전에 SSL handshaking이 이루어 지고 서버 인증서가 오므로 Browser 에서 SSL 인증서 검증시 인증서와 HostName 이 다르다는 에러가 발생


해결책

  1. SNI(Server Name Indication - RFC 4366) 을 지원하는 Web Server(apache 의 경우 2.2.12) 와 Web Browser(IE7+, FF2+ 등)를 사용해야 한다.
    1. Windows 의 경우 IE7 이상이고 Vista 이상이어야 (두 개가 and 조건이다. XP 에 IE7은 SNI 를 지원하지 않는다) SNI 지원된다.
    2. Java는 7 이상부터 지원한다. ((http://docs.oracle.com/javase/7/docs/technotes/guides/security/enhancements-7.html)
    3. 기타 미지원하는 환경은 wikipedia 의 SNI 항목을 참고(http://en.wikipedia.org/wiki/Server_Name_Indication#No_support)
  2. Web Server에 Multiple IP 를 할당하고 IP-based Virtual Hosts 를 설정한다.