YGH

[홈서버 만들기] 7. 인증서

2020년 11월 17일

개요

도메인을 꼭 써야하는 이유 중 하나가 인증서 때문이기도 하다.

인증서는 도메인에 대한 보안을 인증해주고 안정한 통신이 되도록 해주는 역할을 한다.

많은 인증서 발급 기관 중 무료로 인증서를 발급해주는 Let’s Encrypt를 사용할 것이다.

이번 시간에 인증서 발급부터 자동갱신 그리고 웹서버 적용까지 해보도록 하겠다.

Certbot 설치

인증서 발급 소프트웨어인 Certbot을 설치할 것인데 apt에서 제공하는 Certbot 패키지는 조금 오래된 버전이므로 항상 최신을 유지하고 있는 Certbot의 레포지토리를 apt에 추가하여 다운받아보자.

하는 도중 엔터를 눌러 설치를 계속 진행하면 된다.

$ sudo add-apt-repository ppa:certbot/cerbot

Certbot의 Nginx패키지를 설치하자.

$ sudo apt install python3-certbot-nginx

인증서 발급

새로운 도메인 레코드를 등록했을 때 인증서를 다시 발급받을 일을 없애기 위해 와일드 카드 인증서를 발급받을 것이다.

와일드 카드 인증서를 발급 받기 위해서는 호스팅케이알에서 DNS TXT레코드를 하나 추가해서 도메인 인증 받는 단계를 하나 더 거쳐야 한다.

아래 명령어를 입력해서 진행해보도록 하자.

$ sudo certbot certonly --manual --preferred-challenges dns -d "*.ygh.kr" -d "ygh.kr"

개인 이메일을 입력한다.

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel):

약관에 동의 하는지 묻는다.

A를 입력하자.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel:

개발소식을 이메일로 받을 것인지 묻는다.

Y를 입력하자.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o:

도메인 인증을 진행 할 것인지 묻는다.

Y를 입력하자.

Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for ygh.kr
dns-01 challenge for ygh.kr

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.

Are you OK with your IP being logged?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o:

아직 엔터 누르지말자!!!

도메인 소유자가 맞는지 인증하는 부분이다.

우선 이 화면 그대로 두고 가운데 난수 값이 있을 텐데 콘솔에 나온 것을 그대로 복사한 후 호스팅케이알의 DNS 레코드를 추가하러 가자.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.ygh.kr with the following value:

wjLN7fIvSAbB2Ab8BAsZ_ab6P0PJtM9EicTAxSXlhiM

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
  1. [서브도메인] 란에 “_acme-challenge” 입력
  2. [레코드 타입] 을 “텍스트(TXT)” 로 지정
  3. [IP주소 / 레코드 값] 란에 콘솔에서 복사한 문자열을 붙여넣기
  4. [설정 내용 추가] > [적용하기]

DNS 레코드 설정이 완료되었지만 적용되는데 시간이 좀 걸린다.

제대로 적용되었는지는 nslookup으로 확인할 수 있는데 터미널이 사용 중이라 새로운 세션을 만들어야 한다.

윈도우의 명령프롬포트 cmd를 사용해서 확인해보자.

> nslookup
> set type=txt
> _acme-challenge.ygh.kr

내용이 나타난다고 해서 안심하고 진행하지 말자.

해당 도메인이 널리널리 퍼질 때까지 조금만 기다릴 필요가 있다.

시간이 몇분 지나고 잘 적용 된 것 같다 싶을 때 콘솔로 돌아가서 엔터를 입력하고 진행하면 된다.

만약 실패했을 경우 인증서 발급 부분의 첫번 째 명령어를 다시 입력하면 도메인 인증 부분부터 다시 진행할 수 있으니 콘솔 내용 복사부터 차근차근 다시 진행하면 된다.

와일드 카드 인증서 발급이 끝났다.

레코드 확인이 되지 않아 문제가 생겼을 경우 이 화면이 뜰 때까지 Certbot 명령어를 다시 입력해서 과정을 반복 해보길 바란다.

레코드 확인이 끝나면 이제 필요없으니 호스팅 케이알에서 아까 확인때 등록한 _acme-challenge DNS 레코드를 삭제해주자.

인증서 확인

인증서들이 잘 생성 되었는지 확인해보자.

$ ls -l /etc/letsencrypt/live/ygh.kr

인증서 자동 갱신

발급받은 인증서를 90일뒤 자동 파기되는데 걱정할 필요 없다.

Certbot을 이용해 발급받았기 때문에 자동 갱신되도록 되어있다.

인증서는 만료되기 30일 이후부터 갱신을 할 수가 있는데 리눅스의 cron이라는 스케줄러 프로그램이 매일 0시와 12시에 갱신이 필요한지 확인하고 갱신까지 해준다.

당연히 되어있겠지만 파일을 열어 제일 아래 줄을 확인해보자.

필자와 같이 certbot이 보인다면 된 것이다.

# /etc/cron.d/certbot: crontab entries for the certbot package
#
# Upstream recommends attempting renewal twice a day
#
# Eventually, this will be an opportunity to validate certificates
# haven't been revoked, etc.  Renewal will only occur if expiration
# is within 30 days.
#
# Important Note!  This cronjob will NOT be executed if you are
# running systemd as your init system.  If you are running systemd,
# the cronjob.timer function takes precedence over this cronjob.  For
# more details, see the systemd.timer manpage, or use systemctl show
# certbot.timer.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew

DH Param 키 생성

디피-헬먼 키를 추가해서 사이트의 보안을 더 강화할 것이다.

이게 시간이 상당히 오래 걸린다고 하는데 진짜 오래 걸렸다.

필자는 20분쯤 걸리니 끝이 났다.

$ sudo openssl dhparam -out /etc/ssl/dhparam.pem 4096

아래 코드로 파일이 있는지 확인해보자.

$ ls -l /etc/ssl/dhparam.pem

Nginx에 인증서 적용

아래 내용을 수정한 후 적용하자.

server {
        listen 80 default_server;
        server_name ygh.kr;
        return 301 https://$server_name$request_uri;
}

server {
        listen 443 ssl http2 default_server;
        server_name ygh.kr;
        root /var/www;

        ssl_certificate /etc/letsencrypt/live/ygh.kr/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/ygh.kr/privkey.pem;
        ssl_trusted_certificate /etc/letsencrypt/live/ygh.kr/chain.pem;
        ssl_dhparam /etc/ssl/dhparam.pem;
        ssl_session_timeout 10m;
        ssl_session_cache shared:SSL:10m;
        ssl_session_tickets off;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
        ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256;
        ssl_ecdh_curve secp384r1;

        add_header Strict-Transport-Security max-age=31536000;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-XSS-Protection "1; mode=block" always;

        ssl_stapling on;
        ssl_stapling_verify on;

        index index.html index.nginx-debian.html;

        location / {
                try_files $uri $uri/ =404;
        }
}
$ sudo nginx -t
$ sudo service nginx restart

https로 리디렉션

접속 주소은 아래와 같이 4가지가 있다.

이 4가지 모두 두번째인 https://ygh.kr로 전달되게끔 하고싶다.

첫번째 주소는 이미 301 리디렉션을 적용해 두었으니 www.ygh.kr에 대하여 서버블록을 하나 더 만들어서 나머지도 적용해보자.

$ cd /etc/nginx/sites-available
$ sudo cp ygh.kr www.ygh.kr
$ sudo vim www.ygh.kr
server {
        listen 80;
        server_name www.ygh.kr;
        return 301 https://ygh.kr$request_uri;
}

server {
        listen 443 ssl http2;
        server_name www.ygh.kr;
        return 301 https://ygh.kr$request_uri;
}

수정이 끝났으면 sites-enabled 폴더에 심볼릭 링크를 만들고 서버 블록을 작동시키자.

$ cd /etc/nginx/sites-enabled
$ sudo ln -s /etc/nginx/sites-available/www.ygh.kr .
$ sudo nginx -t
$ sudo service nginx restart

접속 테스트

우선 301 리디렉션이 제대로 이루어 지는지 크롬 웹 브라우저를 이용하면 GUI환경으로 쉽게 볼 수 있다.

크롬창에서 F12를 누르면 개발자도구가 열린다 여기서 Network탭을 누르고 Disable cache를 체크한 상태로 주소창에 4가지 접속 주소를 모두 입력해본다.

화면은 필자와 다를 것이니 I love nginx! 문구는 신경쓰지 말자.

왼쪽 상단의 좌물쇠 모양을 클릭하면 인증서 정보도 볼 수 있다.

와일드카드 도메인과 발급자, 유효기간 등을 확인할 수 있다.

보안 평가

이제 나의 사이트가 안전한지 보안 등급을 매겨주는 테스트를 해보자.

https://www.ssllabs.com/ssltest/analyze.html

자신의 도메인 주소만 입력하면 수 분 뒤 결과를 알려준다.

지금 높은 등급을 받았다고 안심하기는 이르다.

현재 웹서버에 적용된 알고리즘들의 취약점이 발견되어 사용하지 말아야하는 경우도 생길 것이며 몇 개월에 한번씩은 자신의 서버의 보안등급을 확인하여 설정들을 갱신해주는 것이 좋다.