Web Server/Apache

CentOS7 - Apache의 VirtualHost에서 http ⇢ https 로의 Redirect 설정

일편나루 2019. 5. 21. 20:32
반응형

목차 (INDEX)

     

    개요

    [Certbot / Let's encrypt] SSL인증서 적용하기 의 연장선에서, 이번에는 Name-based VirtualHost에서 여러개의 도메인을 Redirect하는 설정을 추가하겠습니다.  .htaccess설정으로 Redirect하기도 하지만, 여기서는 NameVirtualHost에 설정하는 것을 전제로 합니다.

    준비 / 현재 상태

    • CentOS7 / Apache 2.4.6
    • example.com : DocumentRoot로 '/var/www/html/', Default 디렉토리를 사용하는 호스트 = 주호스트
    • naruhodo.cf : DocumentRoot로 '/var/www/html/naruhodo.cf' 디렉토리를 사용하는 호스트
    • Let's encrypt 인증서 설치를 완료한 상태
    • 기존에 http로 서비스하던 여러개의 도메인을 모두 https로 전환하려는 중입니다.
    • 기존 서비스들은 htaccess의 Basic인증을 걸어둔 상태로 작업 예정

     

    301 Redirect 설정하기

    보통 /etc/httpd/conf.d/ 아래에서 설정을 하는데, 각각의 파일들을 살펴보면서 작업합니다.

    [root@centos7 conf.d]# ll
    -rw-r--r-- 1 root root 10501 May 21 20:04 ssl.conf           << mod_ssl 모듈을 설치하면 생깁니다. ssl의 기본설정
    -rw-r--r-- 1 root root 228 May 21 18:46 vhost-00.conf       << global적용 (80,443포트를 모두 deny)
    -rw-r--r-- 1 root root 1231 May 21 20:18 vhost-example.com.conf      << Default DocumentRoot 사용하는 도메인
    -rw-r--r-- 1 root root 1098 May 21 20:06 vhost-naruhodo.cf.conf      << 서비스용 도메인
    -rw-r--r-- 1 root root 374 May 21 18:07 vhost-z-123.123.123.10.conf       << ip로 접속 시도할 경우에도 표시
    -rw-r--r-- 1 root root 841 May 20 19:48 welcome.conf       << 표시할 페이지가 없을 때 보여지는 페이지 설정파일
    [root@centos7 conf.d]#

    새로 생성하거나 확인/편집해야 할 파일과 내용입니다.

    1. httpd.conf : (확인/편집) ServerName 설정
    2. ssl.conf : (확인/편집) 443포트 활성화, ServerName, SSL인증키 등을 적용
    3. vhost-example.com.conf : (생성 or 확인/편집) example.com 도메인을 위한 설정파일
    4. vhost-naruhodo.cf.conf : (생성 or 확인/편집) naruhodo.cf 도메인을 위한 설정파일

    ① httpd.conf

    [root@centos7 conf.d]# vi /etc/httpd/conf/httpd.conf
    # If your host doesn't have a registered DNS name, enter its IP address here.
    #
    ServerName example.com:80    <<     추가 or 확인
    또는
    ServerName www.example.com:80     <<     추가 or 확인 

    ※ 설정 확인 후 재기동
    [root@centos7 conf.d]# httpd -t
    Syntax OK
    [root@centos7 conf.d]# systemctl restart httpd

    위 설정과는 별도로 Name-based VirtualHost설정을 할 경우, 여기의 주호스트 설정이 사라지기 때문에 ServerName과 DocumentRoot를 동일하게 하여 VirtualHost를 생성해 주어야 합니다.

    또한, VirtualHost 블록은 적힌 순서대로 또는 파일로 분리했을 경우 파일 이름순으로 적용되므로 주호스트를 가장 앞쪽에 배치시키는 것이 좋습니다. 

    ② ssl.conf

    Listen 443 https    <<    확인/편집
    SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
    SSLSessionCache         shmcb:/run/httpd/sslcache(512000)
    SSLSessionCacheTimeout  300
    SSLRandomSeed startup file:/dev/urandom  256
    SSLRandomSeed connect builtin
    SSLCryptoDevice builtin

    DocumentRoot "/var/www/html/"           << 확인/편집
    ServerName example.com:443              << 확인/편집
    ErrorLog logs/ssl_error_log
    TransferLog logs/ssl_access_log
    LogLevel info
    SSLEngine on         <<   확인/편집
    SSLProtocol all -SSLv2 -SSLv3      
    SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4     
    SSLCertificateFile /etc/letsencrypt/live/www.example.com/cert.pem                  << 추가
    SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem         << 추가
    SSLCertificateChainFile /etc/letsencrypt/live/www.example.com/chain.pem         << 추가   
    Include /etc/letsencrypt/options-ssl-apache.conf    << 추가 

        SSLOptions +StdEnvVars

    <Directory "/var/www/cgi-bin">
        SSLOptions +StdEnvVars

    BrowserMatch "MSIE [2-5]" \
             nokeepalive ssl-unclean-shutdown \
             downgrade-1.0 force-response-1.0
    CustomLog logs/ssl_request_log \
              "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
              

    ※ 설정 확인 후 재기동
    [root@centos7 conf.d]# httpd -t
    Syntax OK
    [root@centos7 conf.d]# systemctl restart httpd

    ④ vhost-example.com.conf

    가상호스트를 사용하면 주호스트 설정이 없어지므로  여기에서 다시 설정해 줍니다.

    80과 443을 나눠서 2개의 파일로 관리했었는데, 직관적이지 못해서 하나의 파일로 합칩니다.

     

    최소한의 설정은 엔진을 ON한 다음에 원하는 rule을 기술하는 것인데,

    실제로는 변수값을 제대로 가져오지 못하는 경우가 생길 수 있기에, 조건들을 필요에 따라서 추가해줄 필요가 생깁니다.

    RewriteEngine       on
    RewriteRule         ^(.*)$  https://%{HTTP_HOST}$1       [R=301,L]  

    작성(동작) 흐름은 RewriteEngine을 ON > rule이 작동할 조건지정 > 조건에 따른 rule 실행 입니다.

    [root@centos7 conf.d]# vi vhost-example.com.conf 
    <VirtualHost *:80>
        ServerName example.com
        ServerAlias www.example.com
        
        <Directory "/var/www/html">  
            Options Indexes FollowSymLinks
            AllowOverride AuthConfig Limit
            Order allow,deny
            Allow from all
        </Directory>

        DocumentRoot /var/www/html
        ErrorLog logs/virtual-error_log
        CustomLog logs/virtual-access_log combined env=!no_log

       ※ Redirectt 설정 ↓↓↓↓↓↓
        RewriteEngine       on
        RewriteMap          lowercase       int:tolower                       << 변수들을 소문자로 바꿉니다
        RewriteCond         "${lowercase:%{HTTPS}}"         !on           << https라는 변수값이 off 이거나
        RewriteCond         "${lowercase:%{REQUEST_SCHEME}}"        !https       <<  request_scheme값이 https가 아니거나
        RewriteCond         "${lowercase:%{SERVER_PORT}}"      !443    << server_port값이 443이 아니거나
        RewriteRule         ^(.*)$  https://%{HTTP_HOST}$1         [R=301,L]    << 모두 https://www.example.com으로 Redirect


      ※ Redirectt 설정  ↑↑↑↑↑↑

    </VirtualHost>

    <VirtualHost *:443>
        ServerName example.com
        ServerAlias www.example.com

        AddDefaultCharset UTF-8

       ※ Redirect될 URL이 https://www.example.com 인 경우, www.example.com 으로 발행된 인증서를 입력해 줍니다.
        ↓↓↓↓↓↓↓
        SSLCertificateFile /etc/letsencrypt/live/www.example.com/cert.pem               
        SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem       
        Include /etc/letsencrypt/options-ssl-apache.conf    
        SSLCertificateChainFile /etc/letsencrypt/live/www.example.com/chain.pem       

        DocumentRoot /var/www/html

        ErrorLog logs/virtual-ssl-error_log
        CustomLog logs/virtual-ssl-access_log combined env=!no_log
    </VirtualHost>
    [root@centos7 conf.d]# 

    ※ 설정 확인 후 재기동
    [root@centos7 conf.d]# httpd -t
    Syntax OK
    [root@centos7 conf.d]# systemctl restart httpd

    Redirect 결과

    try🐶everything backend$ curl -I http://example.com
    HTTP/1.1 301 Moved Permanently
    Date: Wed, 22 May 2019 06:04:54 GMT
    Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.45
    Location: https://www.example.com    << OK !!
    Content-Type: text/html; charset=iso-8859-1

    try🐶everything backend$ curl -I http://www.example.com
    HTTP/1.1 301 Moved Permanently
    Date: Wed, 22 May 2019 06:04:59 GMT
    Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.45
    Location: https://www.example.com      << OK !!
    Content-Type: text/html; charset=iso-8859-1

    ⑤ vhost-naruhodo.cf.conf

    [root@centos7 conf.d]# cat vhost-naruhodo.cf.conf 

    <VirtualHost *:80>

        ServerName naruhodo.cf

        ServerAlias www.naruhodo.cf

     

        <Directory "/var/www/html/naruhodo.cf">

            Options Indexes FollowSymLinks

            AllowOverride AuthConfig Limit

            Order allow,deny

            Allow from all

        </Directory>

     

        DocumentRoot /var/www/html/naruhodo.cf

        ErrorLog logs/virtual-error_log

        CustomLog logs/virtual-access_log combined env=!no_log

       
        ※ Redirectt 설정 
    ↓↓↓↓↓↓ (간단하게 기술하기)

        RewriteEngine    on  

        RewriteRule      ^(.*)$ https://%{HTTP_HOST}$1     [R=301,L]

        ※ Redirectt 설정  ↑↑↑↑↑↑
    </VirtualHost>

     

     

    <VirtualHost *:443>

        ServerName naruhodo.cf

        ServerAlias www.naruhodo.cf

     

        AddDefaultCharset UTF-8

     

        SSLCertificateFile /etc/letsencrypt/live/www.naruhodo.cf/cert.pem

        SSLCertificateKeyFile /etc/letsencrypt/live/www.naruhodo.cf/privkey.pem

        Include /etc/letsencrypt/options-ssl-apache.conf

        SSLCertificateChainFile /etc/letsencrypt/live/www.naruhodo.cf/chain.pem

     

        DocumentRoot /var/www/html/naruhodo.cf

        ErrorLog logs/virtual-ssl-error_log

        CustomLog logs/virtual-ssl-access_log combined env=!no_log

    </VirtualHost>


    ※ 설정 확인 후 재기동

    [root@centos7 conf.d]# httpd -t

    Syntax OK

    [root@centos7 conf.d]# systemctl restart httpd

     

    Redirect 결과

    try🐶everything backend$ curl -I http://naruhodo.cf
    HTTP/1.1 301 Moved Permanently
    Date: Wed, 22 May 2019 03:07:11 GMT
    Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.45
    Location: https://www.naruhodo.cf   << OK !!
    Content-Type: text/html; charset=iso-8859-1

    try🐶everything backend$ curl -I http://www.naruhodo.cf
    HTTP/1.1 301 Moved Permanently
    Date: Wed, 22 May 2019 03:07:19 GMT
    Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.45
    Location: https://www.naruhodo.cf    << OK !!
    Content-Type: text/html; charset=iso-8859-1

    try🐶everything backend$

     

    이상으로, Name-based VirtualHost설정으로 https로 redirect를 해 보았습니다.

    가상호스트의 동작방식이,

    여러개의 <VirtualHost>블럭에서 앞에서부터 순차적으로 적용되고,

    파일을 도메인별로 분리했을 경우에도 파일이름순으로 앞에서부터

    순차적으로 적용된다는 점에 주의해야 합니다.

     

    반응형

     

    [2019/05/24] 내용추가

    위에서 설정한 SSL인증서의  FQDN과 브라우저에 입력하는 URL의 FQDN이 서로 다를 경우, 경고와 함께 제대로 표시되지 않는다.

    예)

    적용된 SSL인증서 : www.naruhodo.cf 

    브라우저로 접속: http://naruhodo.cf   ⇒ https://naruhodo.cf  (https로 전환되지만, 인증서가 다르다는 경고가 뜬다) 

     

    naruhodo.cf로 접속하는 경우에는 그 앞에 www.을 자동으로 붙여서 https로 전환시키는 예제 

    </VirtualHost>
        ...
        
        RewriteEngine   on
        RewriteMap      lowercase           int:tolower
        RewriteCond     "${lowercase:%{HTTPS}}"     !on
        RewriteCond     "${lowercase:%{REQUEST_SCHEME}}"        !https
        RewriteCond     "${lowercase:%{SERVER_PORT}}"       !443
        RewriteCond     "${lowercase:%{HTTP_HOST}}"         "^naruhodo\.cf$"    << naruhodo.cf를 입력하면
        RewriteRule     ^(.*)$  https://www.%{HTTP_HOST}$1  [R=301,L]          << 앞에 www. 을 붙여서 처리
        RewriteRule     ^(.*)$ https://%{HTTP_HOST}$1   [R=301,L]          << 그외는 입력한 도메인을 그대로 https화
        
        ...
    </VirtualHost>
    
    
    수정전)
    try🐶everything ~$ curl -I http://naruhodo.cf
    HTTP/1.1 301 Moved Permanently
    Date: Fri, 24 May 2019 05:01:35 GMT
    Server: Apache/2.4.39 (Unix) OpenSSL/1.1.1b
    Location: https://naruhodo.cf/
    Content-Type: text/html; charset=iso-8859-1
    
    try🐶everything ~$ 
    
    수정후)
    try🐶everything ~$ curl -I http://naruhodo.cf
    HTTP/1.1 301 Moved Permanently
    Date: Fri, 24 May 2019 05:02:53 GMT
    Server: Apache/2.4.39 (Unix) OpenSSL/1.1.1b
    Location: https://www.naruhodo.cf/
    Content-Type: text/html; charset=iso-8859-1
    

     

     

     

    참고:

    * 정규표현 확인툴입니다. 작성하면서 곧바로 결과를 볼 수 있어서 편리하더군요.

    https://weblabo.oscasierra.net/tools/regex/  

     

    * Name-based Virtual Host Support

    https://httpd.apache.org/docs/2.4/vhosts/name-based.html

    반응형