DSM 5.x 또는 그 이하 버전에서 Lets’ Encrypt SSL 인증서를 발급받고 자동 갱신하는 방법을 설명합니다.

SSL 인증서 적용

참고로 DSM 6.0부터는 DSM 자체에 Lets’ Encrypt SSL 인증서를 발급받고 갱신하는 기능이 포함되어 있습니다.

공식 제공하는 Let’s Encrypt 클라이언트는 DSM 5.x에서는 정상 동작하지 않습니다. 그래서 다른 시스템을 이용하여 발급받아야 되는데요.. Lets’ Encrypt 인증서의 유효 기간이 90일이라서 만료 기간에 맞추어 인증서를 갱신하고 나스에 복사하는 작업이 쉽지 않습니다.

이 팁을 따라 하면 최초 한 번만 설치해두면 이후 자동으로 인증서를 갱신해줍니다.

∗ 2018년부터 와일드카드 인증서를 지원합니다. 아래 글을 참고바랍니다.

https://isulnara.com/archives/1581

1. 준비사항

 

  • Bootstrap – 여기서는 따로 설명하지 않겠습니다. 검색하여 각 모델에 맞는 거로 직접 설치 바랍니다.
  • Telnet or SSH 활성화 – DSM 관리자 페이지에서 활성화합니다.
  • 인증서를 발급받고자 하는 도메인(서브 도메인 포함)으로 웹 접속했을 때 나스로 연결되어야 됩니다. (웹브라우저로 http://도메인 으로  접속했을 때 나스의 웹서비스로 연결되어야 됩니다.)

 

 

2. 각종 툴/라이브러리 설치

 

TELNET이나 SSH 클라이언트로 터미널에 root 사용자로 접속하여 아래 명령을 내립니다.

root@dsm:~# ipkg install libcurl openssl grep mktemp bash git
Installing libcurl (7.24.0-3) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/libcurl_7.24.0-3_i686.ipk.
Installing openssl (1.0.2h-1) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/openssl_1.0.2h-1_i686.ipk.
Installing cacerts (20160916-1) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/cacerts_20160916-1_i686.ipk.
Installing zlib (1.2.8-2) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/zlib_1.2.8-2_i686.ipk.
Package openssl (1.0.2h-1) installed in /opt/ is up to date.
Installing grep (2.12-1) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/grep_2.12-1_i686.ipk.
Installing pcre (8.36-1) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/pcre_8.36-1_i686.ipk.
Installing libstdc++ (6.0.21-6) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/libstdc++_6.0.21-6_i686.ipk.
Installing mktemp (1.7-1) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/mktemp_1.7-1_i686.ipk.
Installing bash (4.3.42-1) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/bash_4.3.42-1_i686.ipk.
Installing readline (6.1-2) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/readline_6.1-2_i686.ipk.
Installing ncurses (5.7-5) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/ncurses_5.7-5_i686.ipk.
Installing ncurses-base (5.7-5) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/ncurses-base_5.7-5_i686.ipk.
Installing gettext (0.19.8.1-1) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/gettext_0.19.8.1-1_i686.ipk.
Installing libintl (0.19.8.1-1) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/libintl_0.19.8.1-1_i686.ipk.
Installing libunistring (0.9.4-2) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/libunistring_0.9.4-2_i686.ipk.
Installing git (2.9.3-1) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/git_2.9.3-1_i686.ipk.
package git suggests installing git-manpages
Installing diffutils (3.1-1) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/diffutils_3.1-1_i686.ipk.
Installing rcs (5.7-2) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/rcs_5.7-2_i686.ipk.
Installing expat (2.2.0-1) on /opt/.
Downloading http://ipkg.nslu2-linux.org/optware-ng/buildroot-i686/expat_2.2.0-1_i686.ipk.
Configuring ncurses-base.
Configuring libunistring.
Configuring diffutils.
update-alternatives: Linking //opt/bin/cmp to /opt/bin/diffutils-cmp
update-alternatives: Linking //opt/bin/diff to /opt/bin/diffutils-diff
update-alternatives: Linking //opt/bin/diff3 to /opt/bin/diffutils-diff3
update-alternatives: Linking //opt/bin/sdiff to /opt/bin/diffutils-sdiff
Configuring ncurses.
update-alternatives: Linking //opt/bin/clear to /opt/bin/ncurses-clear
Configuring readline.
Configuring libintl.
Configuring gettext.
Configuring bash.
Configuring cacerts.
Configuring openssl.
Configuring zlib.
Configuring libcurl.
Configuring libstdc++.
Configuring pcre.
Configuring grep.
update-alternatives: Linking //opt/bin/grep to /opt/bin/grep-grep
update-alternatives: Linking //opt/bin/egrep to /opt/bin/grep-egrep
update-alternatives: Linking //opt/bin/fgrep to /opt/bin/grep-fgrep
Configuring rcs.
Configuring expat.
Configuring git.
Configuring mktemp.
update-alternatives: Linking //opt/bin/mktemp to /opt/bin/mktemp-mktemp

 

 

3. dehydrated 설치

 

여기서는 /volume1/system 폴더에 설치합니다. 각자 원하는 폴더에 설치하면 됩니다.

root@dsm:~# mkdir /volume1/system

root@dsm:~# cd /volume1/system

root@dsm:/volume1/system# git clone https://github.com/lukas2511/dehydrated
Cloning into 'dehydrated'...
remote: Counting objects: 1271, done.
remote: Total 1271 (delta 0), reused 0 (delta 0), pack-reused 1271
Receiving objects: 100% (1271/1271), 357.60 KiB | 143.00 KiB/s, done.
Resolving deltas: 100% (773/773), done.
Checking connectivity... done

root@dsm:/volume1/system# cd dehydrated

root@dsm:/volume1/system/dehydrated# ll
total 76
drwxr-xr-x 1 root root 170 Nov 17 23:39 .
drwxr-xr-x 1 root root 20 Nov 17 23:39 ..
-rw-r--r-- 1 root root 1898 Nov 17 23:39 CHANGELOG
-rwxr-xr-x 1 root root 40821 Nov 17 23:39 dehydrated
drwxr-xr-x 1 root root 326 Nov 17 23:39 docs
drwxr-xr-x 1 root root 138 Nov 17 23:39 .git
-rw-r--r-- 1 root root 89 Nov 17 23:39 .gitignore
-rwxr-xr-x 1 root root 1938 Nov 17 23:39 letsencrypt.sh
-rw-r--r-- 1 root root 1085 Nov 17 23:39 LICENSE
-rw-r--r-- 1 root root 3823 Nov 17 23:39 README.md
-rwxr-xr-x 1 root root 9046 Nov 17 23:39 test.sh
-rw-r--r-- 1 root root 107 Nov 17 23:39 .travis.yml

root@dsm:/volume1/system/dehydrated# mkdir -p /var/www/dehydrated

 

 

4. 도메인 설정

 

domains.txt를 아래와 같이 생성합니다.

각 도메인은 한 줄에 하나씩 입력합니다. 서브 도메인은 한 줄에 공백(스페이스)으로 구분하여 입력합니다.

 

mydomain.com a1.mydomain.com a2.mydomain.com a3.mydomain.com

abc.com a1.abc.com a2.abc.com

 

 

5. 웹서버 설정

 

/etc/httpd/conf/extra/dehydrated.conf 파일을 아래와 같은 내용으로 생성합니다.

Alias /.well-known/acme-challenge /var/www/dehydrated
<Directory /var/www/dehydrated>
  Order allow,deny
  Allow from all
</Directory>

 

그리고, /etc/httpd/conf/httpd.conf-user 파일의 제일 끝에 아래와 같이 추가합니다.

Include conf/extra/dehydrated.conf

 

DSM 관리자 페이지에서 웹 서비스를 재시작하거나 아래 명령으로 재시작합니다.

root@dsm:/volume1/system/dehydrated# synoservicectl --restart httpd-user

 

 

6. 인증서 발급

 

아래 명령으로 인증서를 발급받습니다.

root@dsm:/volume1/system/dehydrated# ./dehydrated -c
#
# !! WARNING !! No main config file found, using default config!
# Processing mydomain.com with alternative names: a1.mydomain.com a2.mydomain.com a3.mydomain.com
+ Signing domains...
+ Creating new directory /volume1/system/dehydrated/certs/mydomain.com ...
+ Generating private key...
+ Generating signing request...
+ Requesting challenge for mydomain.com...
+ Requesting challenge for a1.mydomain.com...
+ Requesting challenge for a2.mydomain.com...
+ Requesting challenge for a3.mydomain.com...
+ Responding to challenge for mydomain.com...
+ Challenge is valid!
+ Responding to challenge for a1.mydomain.com...
+ Challenge is valid!
+ Responding to challenge for a2.mydomain.com...
+ Challenge is valid!
+ Responding to challenge for a3.mydomain.com...
+ Challenge is valid!
+ Requesting certificate...
+ Checking certificate...
+ Done!
+ Creating fullchain.pem...
+ Done!

 

이제 인증서가 “certs/도메인” 폴더에 생성되었습니다.

root@dsm:/volume1/system/dehydrated# ls -la certs/mydomain.com/
total 36
drwx------ 2 root root 4096 2016-11-07 18:27 .
drwx------ 3 root root 4096 2016-11-07 18:21 ..
-rw------- 1 root root 1834 2016-11-07 18:22 cert-1478510518.csr
-rw------- 1 root root 2289 2016-11-07 18:22 cert-1478510518.pem
lrwxrwxrwx 1 root root 19 2016-11-07 18:22 cert.csr -> cert-1478510518.csr
lrwxrwxrwx 1 root root 19 2016-11-07 18:22 cert.pem -> cert-1478510518.pem
-rw------- 1 root root 1647 2016-11-07 18:22 chain-1478510518.pem
lrwxrwxrwx 1 root root 20 2016-11-07 18:22 chain.pem -> chain-1478510518.pem
-rw------- 1 root root 3936 2016-11-07 18:22 fullchain-1478510518.pem
lrwxrwxrwx 1 root root 24 2016-11-07 18:22 fullchain.pem -> fullchain-1478510518.pem
-rw-r--r-- 1 root root 7179 2016-11-07 18:27 mydomain.com.pem
-rw------- 1 root root 3243 2016-11-07 18:22 privkey-1478510518.pem
lrwxrwxrwx 1 root root 22 2016-11-07 18:22 privkey.pem -> privkey-1478510518.pem

 

아파치(apache) 가상호스트 설정 파일에 인증서 적용

/etc/httpd/sites-enabled-user/httpd-ssl-vhost.conf-user에 아래와 같이 설정합니다. (도메인은 자신의 환경에 맞게 변경)

<VirtualHost *:443>
...
SSLCertificateFile /volume1/system/dehydrated/certs/mydomain.com/cert.pem
SSLCertificateKeyFile /volume1/system/dehydrated/certs/mydomain.com/privkey.pem
SSLCertificateChainFile /volume1/system/dehydrated/certs/mydomain.com/chain.pem
SSLCACertificateFile /volume1/system/dehydrated/certs/mydomain.com/fullchain.pem
...
</VirtualHost>

DSM 관리자 페이지에서 웹 서비스를 재시작하거나 아래 명령으로 재시작합니다.

root@dsm:/volume1/system/dehydrated# synoservicectl --restart httpd-user

 

HAProxy 설정에 인증서 적용

아래 과정은 HAProxy에 SSL 인증서를 적용하기 위한 과정으로 아파치를 위한 설정에서는 필요치 않습니다.

아래 명령으로 fullchain.pem(server cert + intermediates) 파일과 privkey.pem 파일을 하나로 만들어 줍니다.

root@dsm:/volume1/system/dehydrated# cat certs/mydomain.com/fullchain.pem certs/mydomain.com/privkey.pem > certs/mydomain.com/mydomain.com.pem

Frontends의 https 설정 중 Binds를 아래와 같이 수정합니다.

:5443 ssl crt /volume1/system/dehydrated/certs/mydomain.com/mydomain.com.pem ciphers AESGCM+AES128:AES128:AESGCM+AES256:AES256:RSA+RC4+SHA:!RSA+AES:!CAMELLIA:!aECDH:!3DES:!DSS:!PSK:!SRP:!aNULL no-sslv3

HAProxy 설정

 

 

7. 자동 갱신 설정

 

아래와 같이 /volume1/system/dehydrated/renew_certs.sh 파일을 만들어 줍니다. (DEHYDRATED_PATH와 DOMAIN은 자신의 환경에 맞게 수정)

#!/bin/sh

DEHYDRATED_PATH=/volume1/system/dehydrated
DOMAIN=mydomain.com

${DEHYDRATED_PATH}/dehydrated -c
cat ${DEHYDRATED_PATH}/certs/${DOMAIN}/fullchain.pem ${DEHYDRATED_PATH}/certs/${DOMAIN}/privkey.pem > ${DEHYDRATED_PATH}/certs/${DOMAIN}/${DOMAIN}.pem

 

아래 명령을 내려 실행 권한을 주고, 실제 동작하는지 확인합니다.

root@dsm:/volume1/system/dehydrated# chmod 755 renew_certs.sh
root@dsm:/volume1/system/dehydrated# ./renew_certs.sh
#
# !! WARNING !! No main config file found, using default config!
#
Processing mydomain.com with alternative names: a1.mydomain.com a2.mydomain.com a3.mydomain.com
 + Checking domain name(s) of existing cert... unchanged.
 + Checking expire date of existing cert...
 + Valid till Feb 15 15:02:00 2017 GMT (Longer than 30 days). Skipping renew!

위와 같이 30일 이상 남았다고 갱신을 중단한다는 메시지가 보이면 제대로 동작하는 것입니다.

 

 

작업 스케줄러 등록

이제 DSM 관리자 페이지의 작업 스케줄러에 아래와 같이 등록하면 됩니다.
작업스케줄러-일반

실행 명령에는 사용자 정의 스크립트 /volume1/system/dehydrated/renew_certs.sh를 입력하고,

작업스케줄러-스케줄

스케줄 설정은 “일요일”마다 실행되게 설정하였습니다. 위에서 만든 renew_certs.sh를 실행하면 인증서 만료 기간이 30일 이상 남았다고 나오고 중지되는 것이 보여 스케줄 주기는 30일 이내로 설정하였습니다.

 

이제 모든 설정이 끝났습니다.

 

* 본문 중 /volume1/system과 mydomain.com은 각자의 환경에 맞게 수정하여 사용하기 바랍니다.

* 작업 스케줄러에 의한 갱신은 인증서가 아직 만료 기간이 되지 않아서 제대로 동작하는지 확인하지 못하였습니다. 나중에 댓글로 동작 여부를 남기도록 하겠습니다. 이 팁을 적용하신 분들께서는 동작 여부를 댓글로 알려주시면 고맙겠습니다.