Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>

Contents

어느날 부터 joinc 사이트 접속에 문제가 생기다

2017년 1월 초, 그동안 문제 없이 돌던 사이트에 경고메시지가 뜨기 시작했다. 구글이 https를 적용하지 않은 사이트에 접속할 경우 "안전하지 않음(Not Secure)" 표시를 띄워서 사용자들에게 경고하기로 결정 했다. 서비스 사용에는 문제가 없으나 기분이 좋지는 않을 테다. 어차피 해야 할 것 SSL 인증서를 올리기로 했다.

몇 개 공짜 SSL을 제공해주는 사이트가 있다. 처음에는 StartSSL을 발급 받아서 사용했다. 잘 작동했는데, 얼마가지 않아서 Not Secure 메시지가 떴다. 구글측에서 Startcom의 루트 인증서를 인정해주지 않기로 결정하면서, 그렇게 됐다고 한다.

Lets Encrypt

그래서 찾아낸게 let's encrypt다. Lets Encrypt는 자율적으로 작동하는 개방된 CA(Certificate authority-인증기관)으로 공공성(공공의 이익)을 위해서 운영되는 서비스다. 이 서비스는 ISRG(Internet Security Researhc Group)에서 운영하고 있다.

Lets Encrypt의 특징은 다음과 같다.
  • 무료 : 도메인 이름을 가지고 있다면, 공짜로 신뢰할 수 있는 인증서를 얻을 수 있다.
  • 자동 : CLI 환경에서 간편하게 인증서를 확보하고 갱신할 수 있다.
  • 투명 : 발급/철회된 모든 인증서가 공개적으로 기록되며 누구든 검사 할 수 있다.
  • 공개 : 자동발급과 갱신을 위한 프롵토콜은 모든 사람이 사용 할 수 있도록 공개된다. 표준화를 목표로 하고 있다.
  • 협업 : 다른 인터넷 프로토콜들과 마찬가지로 여러 조직의 지원과 공동노력으로 만들어진다.

설치

환경은 다음과 같다. Lets Encrypt는 인증과정을 자동화하기 위한 에이전트 프로그램을 제공한다. 에이전트 프로그램인 certbot-auto를 다운로드 하고 실행권한을 준다.
# cd /usr/local/bin
# wget https://dl.eff.org/certbot-auto
# chmod +x certbot-auto

웹서버 설정 변경한다. Lets Encrypt는 ACME(Automatic Certificate Management Environment)라는 인증서 자동관리 프로토콜을 이용해서 인증서를 발급하고 관리한다. 인증서를 발급하려면, 인증서를 사용하려는 사용자가 권한을 가진 사용자인지를 판별해야 한다. 예컨데 www.joinc.co.kr에 대한 SSL 인증서를 요구한다면, 요구하는 사람이 www.joinc.co.kr에 대한 권한을 가지고 있는 사람인지(이 경우 yundream)를 확인해야 한다. ACME는 아래와 같은 방식으로 도메인의 유효성을 검토한다. www.joinc.co.kr 도메인을 기준으로 설명해보겠다.
  1. 유저가 www.joinc.co.kr 도메인에 대한 인증서를 요구한다.
  2. Lets Encrypt는 요청자에게 임의의 인증 문자열을 알려준다. 일종의 OTP(One time password)라고 보면 된다.
  3. 그리고 이 인증 문자열을 www.joinc.co.kr/.well-known 경로밑에 있는 특정 파일에 적어둘 것을 명령한다.
  4. www.joinc.co.kr 관리자(yundream)는 Lets Encrypt의 명령대로 .well-known 경로밑에 파일을 만들고 인증문자열을 적는다.
  5. Lets Encrypt는 www.joinc.co.kr/.well-known/인증문자열을적은파일을 읽어서 경로와 내용이 일치하는지 확인한다.
  6. www.joinc.co.kr 도메인 사용자가 해당 도메인의 관리자이여야만 1-5의 과정을 진행 할 수 있을 것이다.
이러한 과정을 거쳐서 도메인에 대한 유효성을 체크한다. 꽤 귀찮은 작업이지만, 프로그램을 이용해서 자동화 할 수 있으니 걱정 할 건 없다.

따라서 먼저 nginx 서버에 /.well-known 디렉토리를 만들어야 한다.
server {
    ....
    location ~ /.well-known {
        allow all;
    }
    ....
}

이제 certbot-auto를 실행한다.
  • webroot-path : .well-known 디렉토리를 만들 위치다. 내 NginX의 Document root를 설정했다.
  • -d : SSL 인증서를 설치한 도메인을 설정한다. 여러 개 도메인을 설정할 수 있다.
# certbot-auto certonly -a webroot --webroot-path=/var/www -d slide.joinc.co.kr -d www.joinc.co.kr
Saving debug log to /var/log/letsencrypt/letsencrypt.log

-------------------------------------------------------------------------------
You have an existing certificate that contains a portion of the domains you
requested (ref: /etc/letsencrypt/renewal/www.joinc.co.kr.conf)

It contains these names: www.joinc.co.kr

You requested these names for the new certificate: slide.joinc.co.kr,
www.joinc.co.kr.

Do you want to expand and replace this existing certificate with the new
certificate?
-------------------------------------------------------------------------------
(E)xpand/(C)ancel: E
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for slide.joinc.co.kr
http-01 challenge for www.joinc.co.kr
Using the webroot path /var/www for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Unable to clean up challenge directory /var/www/.well-known/acme-challenge
Generating key (2048 bits): /etc/letsencrypt/keys/0002_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0002_csr-certbot.pem
도메인 유효성 검증이 성공하면 /etc/letsencrypt/keys와 /etc/letsencrypt/csr 디렉토리밑에 Lets encrypt가 발급한 Key와 CSR 파일을 복사한다. 그리고 /etc/letsencrypt/live/www.joinc.co.kr 밑에 fullchain.pem과 privkey.pem으로 링크를 건다. 이 링크를 nginx에 설정하면 된다.
...
server {
    listen 443;
    server_name www.joinc.co.kr
    root /var/www/;
    index index.html index.htm;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/www.joinc.co.kr/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.joinc.co.kr/privkey.pem;
....
이걸로 끝. 브라우저로 접근해서 인증서 정보를 확인해 보자.

자동 갱신

Lets encrypt에서 발급한 SSL의 유효기간은 3달이다. 3 달마다 수작업으로 갱신 할 수는 없는 노릇이다. crontab으로 certbot-auto을 실행하는 것으로 자동관리 할 수 있다.
# crontab -e
30 2 1 * 1 /usr/local/bin/certbot-auto renew >> /var/log/le-renew.log
매월 1일 2시 30분에 certbot-auto renew 를 호출해서 SSL 인증서를 갱신하도록 설정했다.

참고