저번시간에 발급받은 인증서를 이제 실제로 사용하겠습니다. 차근차근 순서대로 따라하시면 됩니다.
암호화 파일 생성하기(dhparam-2048.pem)
nginx 라우팅 설정 파일 안에 보안설정 내용을 직접 입력해도 가능합니다만
같은 내용이 여러번 사용되는 경우에는 별도의 파일로 보안설정을 작성한 뒤 실제 필요한 곳에서 include문을 통해 포함시키는 것이 유지보수 측면에서 좋습니다.
보안설정파일을 만들기에 앞서, 보안설정 파일 안에서 사용할 암호화파일을 생성하겠습니다. 암호화 파일이름은 dhparam-2048.pem으로 하겠습니다.
2048은 암호화 수준을 뜻하는 건데요. 더 강력한 암호를 원하신다면 4096으로 적으셔도 됩니다만, 암호화 파일을 만드는데 10분이상의 시간이 소요될 것입니다.(2048은 금방 만들어집니다)
암호화 수준을 4096으로 하면 https성능이 2048보다는 느릴것입니다. 암호푸는데 시간이 더 걸리니까요. 2048을 쓰더라도 보안수준에는 크게 지장이 없으니 저는 2048로 하였습니다.
아래 코드를 입력하면 암호파일이 /etc/nginx/에 만들어집니다. 4096 사용하실 분들은 2048대신 4096을 적으시면 됩니다.
sudo openssl dhparam -out /etc/nginx/dhparam-2048.pem 2048
제 컴퓨터는 느려서 그런지 2048로 해도 한참이 걸리는군요. 아래와 같은 점들이 계속해서 나오면서 진행됩니다.
보안설정을 기록한 별도의 파일 생성하기(ssl.conf)
저는 보안설정을 기록한 파일이름을 기억하기 쉽게 ssl.conf 라고 짓겠습니다. 생성할 위치는 /etc/nginx/snippets/ 입니다. 해당 위치는 소유자/그룹이 전부 root로 되어 있기 때문에 파일을 생성하기 위해서 sudo명령이 필요합니다. 아래의 명령어를 입력합시다.
sudo touch /etc/nginx/snippets/ssl.conf
아무반응없이 다음줄로 넘어갔다면 정상입니다.
잘 만들어졌는지 확인해보겠습니다. 아래의 명령어를 입력합니다.
sudo ls -l /etc/nginx/snippets/
맨 아래애 정상적으로 만들어진 ssl.conf를 확인할 수 있습니다.
그럼 ssl.conf를 열어서 파일안에 내용을 입력하겠습니다. 아래 명령어를 입력합시다.
sudo nano /etc/nginx/snippets/ssl.conf
빈 에디터 창이 보인다면 아래의 내용을 복사해서 붙여넣기 합니다. 화면에서 두줄로 보여도 사실은 한줄인 경우가 있으므로 반드시 복사해서 붙여넣기 하시기 바랍니다. 복사는 드래그해서 Control + C 누르시면 되고 붙여넣기는 원격접속되어있는 우분투에서 ‘마우스 오른쪽클릭 > Paste’를 누르면 됩니다.
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_dhparam /etc/nginx/dhparam-2048.pem;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_ecdh_curve secp384r1;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4;
add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload";
add_header X-Content-Type-Options nosniff;
############# iframe 사용 옵션. 참고: http://bit.ly/x-frames #############
add_header X-Frame-Options "SAMEORIGIN"; ##같은 도메인에서만 iframe 허용
####add_header X-Frame-Options DENY; ####모든 도메인에서 iframe 허용
####add_header X-Frame-Options "ALLOW-FROM https://example.com"; #####특정 도메인에서만 허용
위에서 다섯번째줄 맨 오른쪽 보면 dhparam-2048.pem;이라는 구문이 있는데요. 만약에 위에서 암호화파일 만들때 파일명을 저와 다르게 했다면(4096을 사용하거나 아예 파일명을 다르게 한 경우) 다르게 적은 파일명으로 바꿔주셔야 합니다.
작성완료하셨으면 Control + x 누르고 y 누르고 엔터 누르시면 변경사항이 저장됩니다.
이어서 nginx 라우팅설정 파일에 들어가서 방금 작성한 ssl.conf 파일을 include시키는 코드를 작성하겠습니다.
nginx 라우팅 설정파일(default) 수정
nginx의 라우팅 설정파일은 /etc/nginx/sites-available/ 아래에 있는 default라는 이름의 파일입니다. 예전 글에서는 http와 www에 대해서만 라우팅 설정을 해 두었는데요. 이젠 https에 대해 설정하겠습니다.
파일을 열어 수정하기 전에, 여러 방식의 접속을 어떻게 처리할 것인지 대략적인 구상을 해야 합니다.
라우팅 전략 수립
블로그에 접속하는 방법의 예시를 들어보겠습니다.(devbono.com대신 자신의 도메인을 대입하시면 됩니다)
- http://devbono.com
- http://www.devbono.com
- https://devbono.com
- https://www.devbono.com
현재 설정은 1번의 경우에 default_server 속성을 부여한 상태입니다. 특정한 요청(현재는 www가 앞에 붙은 경우만 따로 처리하게 설정되어 있음)을 제외한 모든 요청은 1번의 주소로 모이게 되어 있죠.
현재 2번 설정은 www가 앞에 붙은 경우인데, 이전의 글에서 www가 없는 주소(http://devbono.com)로 리다이렉팅 하도록 설정해 두었습니다.
3번과 4번의 라우팅 설정을 해야 하는데요. 그전에 1번과 2번의 설정을 다시 바꿔줘야 합니다.
저는 다음과 같이 설정하기로 했습니다.
- 1번(http://devbono.com)으로 접속한 사람은 3번(https://devbono.com)으로 보낸다.
- 2번(http://www.devbono.com)으로 접속한 사람은 4번(https://www.devbono.com)으로 보낸다.
- 4번(https://www.devbono.com)으로 접속한 사람은 3번(https://devbono.com)으로 보낸다.
각 번호별 접속시 최종 도착지가 어떻게 되는지 확인해보겠습니다.
- http://devbono.com -> 3. https://devbono.com
- http://www.devbono.com -> 4. https://www.devbono.com -> 3. https://devbono.com
- https://devbono.com
- https://www.devbono.com -> 3. https://devbono.com
결국 모두 3번 선택지인 https://devbono.com 으로 가게끔 해놨습니다.
여기서 왜 2번 선택지는 한단계 더 돌아서 3번으로 가게 해놓았을까요?
이것은 HSTS(HTTP Strict Transport Security)를 준수하기 위함입니다. 블로그 운용에 중요한 사항은 아니니 궁금하신분들은 구글에 검색하시면 자세히 알 수 있으실 겁니다.
default 파일 열어서 라우팅설정 입력하기
default 파일의 위치는 /etc/nginx/sites-available/default 입니다. 아래 명령어를 입력해서 파일을 엽시다.
sudo nano /etc/nginx/sites-available/default
default 파일을 열었다면 안의 내용을 전부 지우고 아래의 내용을 복사하여 붙여넣기 합니다. 이때 devbono.com대신에 자신의 도메인을 적으면 됩니다. 해당 위치는 굵은글씨로 표시해두었습니다. 맨 마지막에 php버전도 현재 설치한 버전으로 적으셔야 됩니다. 이것도 굵은글씨로 표시해두었습니다.
####################################
##### HTTP ##########
####################################
###### HTTP www.
server {
listen 80;
listen [::]:80;
server_name www.devbono.com;
include /etc/nginx/snippets/letsencrypt.conf; ### .well-know/acme-challenge 폴더위치를 알리는 location 블록
location / {
return 301 https://www.devbono.com$request_uri; ###### HTTPS www로 리다이렉팅
}
}
###### HTTP
server {
listen 80;
listen [::]:80 default_server ipv6only=on;
server_name devbono.com;
include /etc/nginx/snippets/letsencrypt.conf; ### .well-know/acme-challenge 폴더위치를 알리는 location 블록
location / {
return 301 https://devbono.com$request_uri; ###### HTTPS로 리다이렉팅
}
}
####################################
##### HTTPS ##########
####################################
###### HTTPS www.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.devbono.com;
ssl_certificate /etc/letsencrypt/live/devbono.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/devbono.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/devbono.com/fullchain.pem;
include /etc/nginx/snippets/ssl.conf; ### SSL 보안설정 ssl.conf 파일 위치
location / {
return 301 https://devbono.com$request_uri; ###### HTTPS로리다이렉팅
}
}
###### HTTPS 메인도메인(최종목적지)
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server ipv6only=on;
server_name devbono.com;
ssl_certificate /etc/letsencrypt/live/devbono.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/devbono.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/devbono.com/fullchain.pem;
include /etc/nginx/snippets/ssl.conf; ### SSL 보안설정내용경로
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
location / {
try_files $uri $uri/ =404;
# 워드프레스 고유주소(permalink)를 기본(plain)에서 글이름(post name)등 다른걸로 바꾸었을 때 기존 글들이 404페이지가 되는 것 우회
if (!-e $request_filename) {
rewrite ^.*$ /index.php last;
}
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_read_timeout 300;
}
location ~ /\.ht {
deny all;
}
}
작성완료하셨다면 Control + X 후 Y 후 엔터를 눌러 변경사항을 저장합시다.
default 설정파일에 문법오류가 있는지 검사하기 위해 아래의 명령어를 입력합니다.
sudo nginx -t
syntax is ok 및 test is successful 메시지가 나오면 성공입니다. 만약 에러메시지가 나타난다면 오타가 있는 것이므로 잘 찾아서 고쳐준뒤 다시 시도합시다. 성공하셨다면 아래 명령어를 입력해 nginx를 재시작합니다.
sudo service nginx restart
이제 새로 변경된 라우팅 설정이 반영되었습니다.
https 포트(443번 포트) 열기
https는 443번 포트를 사용하므로 해당 포트를 열어주겠습니다. 아래 명령어를 입력해서 열어줍시다.
ufw allow 443
SSL인증서 자동갱신위한 crontab작업 설정하기
Let’s encrypt의 인증서는 무료지만 유효기간이 짧은편입니다. 90일마다 수동으로 갱신하기 귀찮으므로 리눅스 예약명령인 crontab을 이용하여 자동으로 갱신하도록 하겠습니다.
크론탭의 사용방법에 대해서는 깊게 다루지 않고, 실질적인 자동갱신을 위한 명령어 입력만 실시하겠습니다.
터미널에 아래 명령어를 입력해 크론탭을 열겠습니다.
crontab -e
위와같은 화면이 나오면 nano가 들어있는 1번 항목을 선택해줍시다. 1을 누르고 엔터를 누릅시다. 그러면 아래와 같은 주석으로 가득한 화면이 보일 것입니다.
자동갱신을 하기 위해, 맨 아래 줄에 아래와 같은 명령어를 입력합니다.
06 05, 10 * * * certbot renew --post-hook "sudo service nginx restart"
위의 명령어의 아랫줄에 아래와 같은 명령어를 입력합니다.(아래 코드는 주기적 시스템 리부팅을 위한 것)
01 06 * * 1 root shutdown now -r
작성완료하였으면 Control + X 후 Y 후 Enter입력하여 변동사항을 저장합시다.
드디어 라우팅설정 및 자동갱신 작업이 완료되었습니다. 정말 고생많으셨습니다.
저번에 댓글 남겼던 대학생입니다!
데브보노님 글 보고 저도 드디어 성공했습니다
정말 감사합니다!
도움이 되었다니 정말 기쁩니다. 좋은하루되세요.
안녕하세요. 자세한 설명으로 포스팅 해주셔서 감사합니다.
잘 따라 하고 있다가 최근에 ssl 인증을 받는 내용을 따라하다보니
지원하지 않는 프로토콜을 사용한다는 내용과 ERR_SSL_VERSION_OR_CIPHER_MISMATCH 에러가 발생합니다.
혹시 해결방법을 알 수 있을까요?
정확한 해결법은 모르겠습니다만, 공식 홈페이지 https://certbot.eff.org/ 가시면 인증받는법이 나와있습니다. 영어로 되어있어서 어려울수도 있지만 거기에 써진대로 차근차근 한번 해보시길 바랍니다. 사실 저도 홈페이지에 써진거 보고 하면서 글을 쓴 것이라서요.
해당 문제가 저도 발생했었는데 관련 방식으로 SSL 인증을 받는 것이 좀 옛날 버전이라서 허용을 해주지 않는 것 같더라고요. 저는 https://velog.io/@chldppwls12/Lets-Encrypt-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EB%B0%9C%EA%B8%89-%EB%B0%8F-%EA%B0%B1%EC%8B%A0 이분 방식으로 해서 인증을 진행하니 관련 에러가 해결되는 것을 볼 수 있었습니다! 리다이렉트도 다 자동으로 이루어지더라고요! 데브 보노 님 덕분에 웹서버를 너무 수월하게 만들어서 감사 comment를 다려다가 해당 댓글이 보여서 도움이 될까 해서 comment 남깁니다! ㅎㅎ