[워드프레스 Tips] Lets’ Encrypt SSL 인증서 수동 갱신 방법

By | 2017-05-17

이 글은 2017-09-15에 최종 수정하였습니다.

앞선 포스팅에서 무료 SSL인증서를 비교해 보았고 그 중 향후 가능성이나 사용편리성을 고려시 Let’s Encrypt가 가장 낫겠다고 판단했고 이를 적용하겠다고 했습니다.

이번 포스팅에서는 Let’s Encrypt를 통해서 무료 SSL인증서 발급받고 자동으로 연장하는 방안에 대해서 살펴보도록 하겟습니다.

이 글은 기존의 기라성과 같은 선배들이 제시해 준 가이드를 토대로 작성되었습니다.

SSL의 정석 (아파치 & nginx) ,
Let’s Encrypt, Nginx ,How to Install nginx and google PageSpeed on Ubuntu 16.04 (Xenial Xerus)

1. Let’s Encrypt (https://letsencrypt.org) 간략 소개

SSL-인증기관-lets-encrypt-2

앞 포스팅에서 소개한 내용을 그개로 여기에서도 인용해 봅니다.

Let’s Encrypt은 HTTPS의 확산이 늦어지는 것은 SSL인증서에 있다고 보고 무료 인증서 보급을 통해 HTTPS의 확산을 늘리겠다는 취지로 시작된 비영리 프로젝트입니다.

Mozilla, Akamai, Cisco, eff, Identrust, 지말토(Gemalto)와 HP 엔터프라이즈, 패스틀리(Fastly), 두다(Duda)등이 스폰서로 참여해서 HTTPS Everywhere를 모토로 100% 무료 SSL 인증서를 발급 해주고 있습니다.

2016년 4월 정식 버젼을 출시했으며 2014년 9월 8일 기준 약 537만개의 웹서버 인증서 170만 건을 발급했으며, 천만건이상의 SSL인증서 발급을 진행해왔습니다. (Let’s Encrypt 홈페이지 통계 기준)

Lets_Encrypt-인증서-발급추이_서버기준_1600918

Lets_Encrypt-인증서-발급추이_1600918

Let’s Encrypt의 정책은 독특합니다. 앞에서 HTTPS의 확산을 위한 비영리단체로 소개했듯이 Let’s Encrypt은 서버운영자들이 인증 관리를 철저히 하지 못한다는 점을 염려(?)해 인증서 설치부터 재발행(갱신)까지 다 책임진다는 자세로 인증관련 업무를 진행하고 있습니다.

인증기간이 90일로 상대적으로 짧은 것은 보안 상황이 계속 변동되므로 이를 반영해 갱신할 수 있도록 짧게 잡았으며 대신 자동으로 인증서가 연장(재발행)되는 기능을 사용하도록 권장하고 있습니다.

자동으로 연장(재발행)된다면 오히려 안심하고 사용할 수 있는 것이 아닌가 싶습니다.

  • HTTPS Everywhere 를 추구하는 비영리 프로젝트
  • 스폰서 : Mozilla, Akamai, Cisco, eff, Identrust
  • IdenTrust cross-sign됨
  • SSL 인증서 100% 무료화
  • 인증기간 연장 및인증서 재발급 무료
  • 사용편리성 : 콘솔상에서 인증서 발급/갱신/설치/세팅 자동화.
  • 멀티도메인 지원, SAN 기능(여러 도메인을 한 인증서로 묶어주는 기능) 지원

2. Let’s Encrypt에서 인증서 생성하기

현재 제 시스템 상황입니다.

  • Ubuntu 16.04
  • Nginx 1.11.4
  • PHP 7.0.3

Let’s Encrypt에서 제공하는 소프트웨어 클라이언트인 letsencrypt를 사용하면 쉽고 편하게 적용할 수 있습니다.
아파치서버에서는 완전 자동으로 SSL인증을 획득하고 적용할 수 있는 Nginx 서버에서는 이러한 자동화가 조금 늦게 적용되는 것 같습니다. Nginx에서의 자동화 방법은 없는것은 아니므로 이는 뒷부분에서 살펴보도록 하겠습니다.

아무튼 Nginx에서 Let’s Encrypt 인증서 생성에는 몇가지 조건이 있습니다.

  • root 접근 권한을 가지고 있어야 (즉 서버를 운영하고 있어야하므로 일반 웹호스팅은 안된다는 의미)
  • Let’s Encrypt가 아직은 공식적으로 Nginx를 지원하지 않은 상태이므로 아파치보다는 상대적으로 매뉴얼 작업이 필요합니다.

2.1. git 설치하고 certbot설치 하기

서버에 접근 후 root 계정을 전환 후

  • 첫째 /root에서 작업을 진행할 수 있게 /root로 이동합니다.

  • 둘째, 필요한 소프트웨어를 GitLab에서 받을 수 있도록 git를 설치합니다.

    처음 소프트웨어 설치 시 관련 소프트웨어를 업데이트할 수 있도록 Git repositories를 등록해 놓았다면 별도로 설치할 필요는 없는 것 같습니다. 긴가민가한다면 그냥 설치하는게 마음 편하겠죠.

  • 셋째, 새로운 작업을 시작하기전에 항시 최신 소프트웨어가 없는지 점검하기 위해서 업데이트 명령을 줍니다.

  • 넷째, 그 다음 git를 설치하라는 명령을 주는 거죠.

  • 다섯째, git이 설치되면 git 저장소에서 SSL 인증을 위한 소프트웨어 클라이언트인 certbot를 다운받습니다.

아래 차례대로 진행 명령을 보여주고 있습니다.

cd /root   # /root 디렉토리로 이동해 작업 시작
apt-get update   # 항상 소프트웨어를 설치하기 전에 최신 업데이트가 있는 지 학인
apt-get install git # git 설치
git clone https://github.com/certbot/certbot  # certbot 설치

2.2. certbot으로 인증서를 생성

다음에는 certbot이 설치된 폴더로 이동해 인증서를 생성하는 하는 단계입니다.

  • 첫째, certbot이 깔린 폴더로 이동합니다. cd certbot 명령 사용

  • 둘째, nginx를 중단시킵니다. Let’s Encrypt 의 인증 방식인 Standalone plugin 은 서버 인증을 위해서 80포트를 이용하는데 nginx가 80 포트를 계속 사용하고 있으면 인증이 제대로 될 수 없으므로 nginx 서버를 일시적으로 멈추는 것입니다.

  • 셋째, 인증 절차에 돌입합니다. 여기서 certonly 명령을 사용합니다. certonly는 인증서만 설치하겠다는 명령입니다. nginx에선 아작 아파치처럼 다양한 명령 옵션이 없다고 합니다.

  • 넷째, 나오는 화면 요구사항에 맞추어 인증을 진행합니다.

cd certbot  # /certbot 디렉토리로 이동해 작업 시작
service nginx stop   # 80포트를 사용하지 않토록 nginx를 중단시킴
./certbot-auto certonly # 인증 절차 진행, 조금 시간이 걸립니다.
service nginx start # 작업이 끝나면 다시 nginx를 가동시킴

▽ 메일 인증 장면

lets-encrypt-%ec%84%a4%ec%b9%98-%ed%99%94%eb%a9%b405_email

▽ 서비스 조건에 대해 일어보라는 메세지,
당연히 agree!!

lets-encrypt-%ec%84%a4%ec%b9%98-%ed%99%94%eb%a9%b406-read-pdf

▽ 인증절차가 진행되면 처음 나오는 화면,
webroot 인증을 할것인지 아니면 자동으로 스탠드올원으로 임시 웹서버로 인증할 것인지?
외국 문헌들은 webroot 인증을 추천하던데, 우리나라에서는 스탠드올원을 추천하고 있음

lets-encrypt-%ec%84%a4%ec%b9%98-%ed%99%94%eb%a9%b4

▽ SSL 인증할 도메인 입력,
가능하는 한 알고있는 또는 필요한 도메인을 전부 기록,
WWW는 별도로 입력해야 한다.

lets-encrypt-%ec%84%a4%ec%b9%98-%ed%99%94%eb%a9%b402

▽ 인증 완료 메세지,
생각보단 어렵지 않았다!!

lets-encrypt-%ec%84%a4%ec%b9%98-%ed%99%94%eb%a9%b406-%ec%84%b1%ea%b3%b5%ed%95%98%eb%a9%b4

2.3. DH Param 생성, 적용하기

앞의 2.2까지 진행하면 인증서 설치는 끝나지만 보다 보안을 강화하기 위해서 DH Param 생성을 합니다.

DH Param은 일부 암호화 알고리듬에 사용되는 커다란 난수 하나를 미리 생성해 두어서 암호화 성능을 향상시키고 보안을 높이는 방법입니다.

실제로 DH Param을 비적용시와 적용 시 보안 점수를 측정해보니 한등급 차이가 날 정도로 Gap이 컷습니다. DH Param를 적용시는 A+ 보안등급이 나오고 DH Param를 비적용시는 A-가 나오네요.

mkdir /etc/nginx/ssl
cd /etc/nginx/ssl
openssl dhparam -out dhparams.pem 4096  # 2048비트로 하려면 4096대신 2048로 대체 한다.
openssl rand 48 > session_ticket.key  # 세션 티켓키도 생성 이는 시간이 거의 걸리지 않는다.

2.4. 암호화 알고리즘 설정하기

XE 분야에서 탁월한 식견을 자랑하는 가지곰님이 Xpress Engine 공홈에 올린 SSL의 정석 (아파치 & nginx) 라는 글에 의하면 실제로 보안을 제공하는 것은 인증서가 아니라 암호화 알고리즘이라고 이야기 하고 있습니다. 인증서를 획득하는게 중요한게 아니고 얼마나 철저한 암호화 설정을 하느냐가 중요하다는 것입니다.

아래는 제가 SSL의 정석 (아파치 & nginx) , Let’s Encrypt, Nginx ,How to Install nginx and google PageSpeed on Ubuntu 16.04 (Xenial Xerus)의 글들을 토대로 SSL 암호화를 반영하고 구글 PPageSpeed Module을 적용한 스크립트입니다.

참고로 보시기 바랍니다.

server {
    listen       80;
    server_name  yourdomain.com www.yourdomain.com;
    return 301 https://$host$request_uri;
}

server {

    listen 443 ssl http2;
    server_name yourdomain.com;
    root   /home/happist;

    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
    add_header X-Frame-Options DENY;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;


    #OCSP Stapling(인증서가 유효하다는 증명을 미리 받아두어서 사이트에 처음 방문할 때 접속 속도를 높여주는 방법dla)

    ssl_dhparam /etc/nginx/ssl/yourdomain.com.pem;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; 
    resolver 8.8.8.8 8.8.4.4;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';


    ssl_prefer_server_ciphers on;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;

    access_log /var/log/nginx/yourdomain.com.access.log;
    error_log /var/log/nginx/yourdomain.com.error.log warn;


   location / {
       try_files $uri $uri/ /index.php?$args;
       index index.php index.html index.htm;
    }


    # Block dot file (.htaccess .htpasswd .svn .git .env and so on.)
    location ~ /\. {
        deny all;
    }

    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location ~* /(?:uploads|files|data)/.*\.php$ {
        deny all;
    }

    # Add trailing slash to */wp-admin requests.
    rewrite /wp-admin$ $scheme://$host$uri/ permanent;

    location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
        access_log off;
        log_not_found off;
        expires max;
    }

    location ~ [^/]\.php(/|$) {
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        if (!-f $document_root$fastcgi_script_name) {
            return 404;
        }

        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;

    }

pagespeed on;
pagespeed FileCachePath /var/ngx_pagespeed_cache;

pagespeed RewriteLevel CoreFilters;
pagespeed EnableFilters defer_javascript;

# Ensure requests for pagespeed optimized resources go to the pagespeed handler
# and no extraneous headers get set.
location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" {
  add_header "" "";
}
location ~ "^/pagespeed_static/" { }
location ~ "^/ngx_pagespeed_beacon$" { }

}

2.5. nginx 서비스 재시작

세팅이 완료되었으면 ginx 서비스를 재시작 명령을 주어 설정이 반영되도록 합니다.

nginx -t   # 혹 설정에 문제가 없는지 점검
service nginx restart   # nginx 서비스를 재시작해 설정을 반영시킴

그리고 Qualys SSL Labs으로 이동해서 보안점수가 어는정도 나오는지 테스트해봅니다.

HOW WELL DO YOU KNOW SSL?

제대로 세팅만하면 A+은 그냥 나오므로 어느정도 신뢰 할 수 있는지 모르겠습니다. 변별력이 별로 없어 보여서요.

A+이 나온 SSL Test 결과

3. Let’s Encrypt 인증서 자동 갱신

Let’s Encrypt 무료 SSL 인증서는 3개월단위로 인증서가 발급됩니다. 3개ㅇ뤄마다 수동으로 이를 업데이트 시키려면 엄청 신경을 써야하고 바쁘다보면 그냥 지나칠 경우가 많겠지요.

아래는 두가지 방법을 제안해 놓았는데 2가지 방법 중 하나를 택해서 사용하면 좋을 것 같습니다.

저는 당분간 2개다 써보고 잘 작동하는지 더 모니터링 해볼 생각입니다.

3.1. 3개월 단위로 갱신하는 스크립트 사용

이런 귀찮은 업데이트를 자동으로 해주는 방법입니다. 이 방법은 크론탭과 쉡 스크립트를 사용한 방법으로 Let’s Encrypt 무료 SSL 인증서 갱신하기라는 글을 참조하였습니다.

여기에선 매달 10일 새벽 4시에 인증서 갱신 여부를 확인해 갱신 시기가 다가오면 갱신토록 하였습니다. 15일을 택한 이유는 제가 17일자로 인증을 받았으므로 1주 정도 여유를 둔 것입니다.

먼저 letsencrypt.sh 파일을 만들어 Shell Script 생성합니다.

touch /root/letsencrypt.sh

다음으로 letsencrypt.sh 파일에 755권한을 줍니다.

chmod 755 /root/letsencrypt.sh

그리고 letsencrypt.sh 파일에 명령 스크립트를 적습니다.

#!/bin/sh
/etc/init.d/nginx stop
if ! /root/tools/letsencrypt/letsencrypt-auto -renew > /var/log/letsencrypt-renew.log 2>&1 ; then
    echo Automated renew failed;
    cat /var/log/letsencrypt-renew.log
    exit 1
fi
/etc/init.d/nginx start

마지막으로 crontab 아래 내용 추가합니다.

30 0 1 1-12 * root /root/letsencrypt.sh

3.2. 매일 갱신 여부를 체크하는 스크립트 사용

이는 a href=”https://wpu.kr/7449">Let’s Encrypt, Nginx 에서 소개하는 방식으로 cron을 매일 04시 30분, 31분, 35분에 nginx를 중지시키고 갱신을 확인하고 nginx를 다시 시작하라는 명령을 준 것입니다.

crontab에 아래 명령을 추가합니다.

30 04 * * * /etc/init.d/nginx stop
31 04 * * * /root/certbot/certbot-auto renew >> /var/log/letsencrypt/le-renew.log
35 04 * * * /etc/init.d/nginx start

4. SSL 사용을 위한 워드프레스 설정하기

워드프레스에서는 별로 할것은 없습니다.
워드프레스 어드민의 설정 – 일반으로 가서 워드프레스 주소와 사이트주소에 S를 붙여줍니다.

워드프레스와 사이트 주소에 S를 붙임

5. SSL 설정 후 속도 개선하기

SSL을 설정하고 인터넷을 실행하면 속도가 확 떨어집니다.
저의 경우 test.pingdom에서 test를 해보면 waiting 시간이 2초 가까이(이 엄청난 속도!!!!!)나오더군요..

이를 해결하는 방법은 OCSP Stapling을 적용하는 방법이라고 합니다. 이는 앞서서도 소개한 가진곰님의 SSL의 정석 (아파치 & nginx) 에서 소개하는 방법으로 사이트에 적용한 인증서가 유효하다는 증명을 미리 받아두어서 사용자가 사이트를 방문 시 접속 속도를 높여주는 방법입니다.

ssl_dhparam /폴더/경로/아까.생성한.dhparam;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /폴더/경로/2~3번.인증서.붙인거.파일명;
resolver 8.8.8.8 8.8.4.4;

resolver는 내부적으로 인증서 발급업체와의 통신을 위해 사용하는 네임서버라고 하구요. 일반 서버호스팅은 IDC에서 제공하는 네임서버 성능이 좋지 않아서 구글에서 제공하는 네임서버로 셋팅한다고 합니다.

6. 마치며

이상으로 간단히 SSL 적용 방법을 적어 보았습니다.
이 분야에의 문외한이 겁없이 시작해서 많은 시행착오 끝에 SSL를 적용했습니다. 참 어려운 여정이었습니다.

이제 적용하고 보니 이게 최선인가하는 회의가 듭니다. 왜냐면 SSL 적용후 속도가 만족스럽지 못하기 때문이죠.
다들 속도때문에 SSL은 로그인이나 회원 가입등 일부 부분에서만 사용한다고 하네요. 네이버도 일부분만 적용한다고.

우선 가상호스팅을 사용하고 있으므로 봉안 차원이라도 SSL을 적용하는게 좋을 것 같고, 속도 문제는 차후 어떻게 개선할지 고민해 봐야겠습니다.

429 times, 4 times today
  • 좋은 정보 감사합니다~
    전 Lets’ Encrypt SSL을 설치했다가 제거한 상태입니다ㅎㅎ

    추후에 다시 설치한다면 이 글이 많은 도움이 될 것 같습니다.

    • 고맙습니다.

      어제 퇴근하고 비몽사몽간에 적었던거라 오타도 많고 지금보니 많이 부복하네요.
      근데 갑자기 매뉴얼로 갱신하려니 매뉴얼 갱신 관련 내용이 없어서 (제가 못 찾았겠지요) 공유차 적었습니다.

      구글의 영향으로 SSL설치가넘 당연시되고 있는 가운데 무료 제공하는 Lets’ Encrypt SSL은 좋은 선택이라는 생각입니다. 다만 90일마다 갱신해야하는데 이도 자동으로 갱신하는 방법이 많이 있어서 큰 문제는 안되는 것 같습니다.

      처음에는 속돡 늦어지는 싶었는데 솔직히 당시 측정해보면 조금 늦어진것 같습니다만.
      최근 서버 성능들이 좋아졌고 SSL 설치가 당연시 되다보니 속도에 대한 불만이 없어졌습니다.

      아무튼 자기 지식으로 쌓이는 것은 직접 해봐야 온전히 자기것이 된다는 것을 다시한번 깨닫게 되었습니다.

  • cron job 에 자동갱신 설정해 놓으시면 수동으로 갱신 안하셔도 됩니다.

    52 0,12 * * * root /full/path/to/certbot-auto renew –quiet

    아, 자동갱신 시도를 해보셨었네요…

    • 네,
      최근에 여러번 서버를 옮기다보니 또 조만갈 또 옴겨봐야지하는 생각에 자동 갱신을 설정해 놓지 않았습니다.
      이번에는 꾹 참고 오래 머무르려고하고 있어서요.
      짬이 나는대로 자동 갱신을 적용해 보려고 합니다.

      그래도 한번 매뉴얼로 갱신해보니깐 오히려 이해하는데는 더 도움이 되었습니다.
      조금 더 고민하게되고
      물론 아까운 시간을 버리긴 했습니다.