본문 바로가기

DevOps/[Linux]

[ubuntu + Nginx + certbot] certbot을 이용한 https 보안 사용하기

반응형

 

INTRO


 

ubuntu 22.04 + nginx 서버에 certbot을 이용하여

let's encrypt기관의 무료 인증서를 발급받아

웹 사이트에 https 보안을 사용해 볼 것이다.

 

 


 

🚦apache2서버에 https를 적용하고자 하는 분은 아래 포스팅을 참고해주세요

 

1. UFW 를 사용한 방화벽 열기

- UFW(Uncomplicated Firewall)는 리눅스 데비안 계열에서 사용하는 방화벽 관리 프로그램이다.

- apt-get install 로 쉽게 설치가 가능하다.

- 직접적으로 iptables에 규칙을 추가해도 되지만, 해당 프로그램을 사용하는것이 명령에 사용에 있어 더 편리하다.

- 필자의 현재 구조는 아래와 같다.

- https 포트인 443과, http 포트인 80 포트를 모두 열어줘야하는데

- 현재 도커 컨테이너에 아파치 서버를 올린 형상이므로,

- 외부 방화벽과 컨테이너의 방화벽 모두 ufw를 이용하여 열어주었다.

 

 $ sudo apt-get install ufw
 $ sudo ufw allow 443/tcp
 $ sudo ufw allow 80/tcp
 
 // 혹시 모르니 22번 포트도 열어두자. 안그러면 enable이후 ssh 접속이 불가해질 수도..
 $ sudo ufw allow 22/tcp
 $ sudo ufw enable
 $ sudo ufw status
 
 // 이렇게 해도 된다.
 $ sudo iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT
 $ sudo iptables -I INPUT 1 -p tcp --dport 443 -j ACCEPT

 

 

2. certbot 설치

- 하기 명령어를 이용하여 certbot을 설치하고,

- certbot을 이용하여 발급받은 인증서를 본인의 서버 환경에 적용해주는 패키지도 함께 설치한다.

$ sudo apt install certbot python3-certbot-nginx

3. nginx 설정

- 현재 기준(2022년 11월) 최신 버전의 nginx 를 설치하게되면, nginx 가 기본적으로 참조하는 config파일이 
/etc/nginx/sites-enabled 아래 확장자 없이 default라는 파일로 생성되어있다.

- 해당 파일을 제거해주자.

 

- 이 다음 스텝에서는 certbot이 nginx경로를 자동 인식하여 config파일들을 변경해주는 과정이 있는데,

- /etc/nginx/sites-enabled 에 있는 default라는 파일은 참조하지 못하는 것으로 보임

- 따라서  /etc/nginx/conf.d 경로에 .conf 확장자를 가진 파일을 만들어줘야한다. (default.conf로 만들자)

- 만들고 난 뒤 certbot이 인식할 수 있게 아래와 같은 내용으로 채워준다.(발급받을 도메인 주소를 적어주자)

 

- certbot에서 해당 파일을 수정할 예정이다.

server {
        listen       80;
        listen  [::]:80;
        server_name  "발급받을 도메인 주소(aaaa.com)";
        location / {
                root   /usr/share/nginx/html;
                index  index.html index.htm;
        }
}

 

 

- 하기 명령어를 통해 인증서를 발급받는다.

- 인증서를 생성하게 되면, /etc/nginx/conf.d 경로에 있는default.conf파일이 수정된다

 

$ sudo certbot --nginx

 

- 이후 별다른 설정 없이 본인의 도메인에 접속해보면 https보안이 적용되어 있는 것을 확인할 수 있다.

 

 

- 발급받은 인증서는 90일의 유효기간이 있고,

- 이를 갱신하는 명령어는 아래와 같다.

$ sudo certbot renew --dry-run

 

- 필자의 환경대로 설치했다면, /etc/cron.d 폴더 내

- crontab으로 하루 2회씩 수행되는 스크립트가 설치되어있을것이다.

- 이는 만료일이 30일 이하로 남은 인증서들을 체크하여 갱신해준다.

 /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

 

4. certonly 옵션을 통한 수동 적용(2023.02.09)

- 하기 명령어를 통해 인증서를 발급받게되면, nginx config파일을 certbot이 건드리지 않게 된다.

- 따라서 수동으로 config 파일에 인증서를 적용시켜줘야한다.

sudo certbot certonly -d "domain.com"

- 아래 과정을 거치면 /etc/letsencrypt/live/domain.com 경로에 4가지 인증서가 생성된다.

Saving debug log to /var/log/letsencrypt/letsencrypt.log

How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Nginx Web Server plugin (nginx)
2: Spin up a temporary webserver (standalone)
3: Place files in webroot directory (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-3] then [enter] (press 'c' to cancel): 1
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): [이메일 입력]

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, 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
Account registered.
Requesting a certificate for domain.com


Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/domain.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/domain.com/privkey.pem
This certificate expires on 2023-05-10.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 

- 이 중 사용해야 할 인증서는 fullchain.pem, privkey.pem이다.

- 각 인증서가 뭔지 간략하게 짚고넘어가보면..

- cert.pem : let's encrypt에서 서명한 인증서

- chain.pem : Let's Encrypt 중간 인증서(intermediate certificate)

- fullchain.pem : cert.pem + chain.pem

- privkey.pem : 인증서의 개인키

 

- privkey.pem을 바로 사용해도 되지만, .key로 변환해서 사용하는 경우를 봐서 아래에 방법을 정리

sudo openssl rsa -in privkey.pem -text > cert.key

 

- 이제 nginx config파일에 인증서의 경로를 입력해주면 된다.

- ssl_ciphers는 TLS 인증에서 사용할 알고리즘을 정의하는것.

- 입력하지 않아도 default로 적용되나, 높은 수준의 보안을 요구하는 곳에서는 필수로 사용함 

server {
        server_name domain.com;
        listen 443 ssl;
        ssl_protocols TLSv1.3;  #TLSv1 TLSv1.1 TLSv1.2;
        ssl_certificate [fullchain.pem 인증서의 경로];
        ssl_certificate_key [privkey.pem 인증서의 경로];
        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:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK;
        ssl_prefer_server_ciphers  on;
        ssl_session_cache  shared:SSL:20m;
        ssl_session_timeout  10m;

        client_max_body_size 15M;
        location / {
                root   /data/dist;
                index  index.html index.htm;
                try_files $uri $uri/ /index.html;
        }

        error_page   500 502 503 504  /50x.html;

        location = /50x.html {
                root   /usr/share/nginx/html;
        }
}

 

 

 

마무리

Ubuntu + nginx 기반의 서버에서 https보안을 위한 SSL/TLS 인증서를 발급받아 적용시키는 방법에 대해 포스팅했다.

개인적인 프로젝트를 진행할 때에는 매우 유용하게 쓰이니 알아두면 좋을 것 같다.

 

 

 

-퍼가실 때는 출처를 꼭 같이 적어서 올려주세요!

 

반응형