본문 바로가기
프로젝트/Recipository

[Dev] 23.05.01. https를 위한 인증서 발급 및 적용

by 규글 2023. 5. 1.

 참 마음이란 것이 신기하다. 처음에는 배포를 위한 AWS를 사용해보는 것이 최종 목표였다. 그래서 EC2 인스턴스를 생성하여 jar file을 build해서 올렸고, S3 bucket을 생성하여 IAM 인증을 통해 이미지를 업로드하도록 했다.

 그 다음에는 도메인 연결을 해보고 싶어졌다. 이력서를 쓰다보면 가끔 작업한 내용에 대하여 오픈된 주소가 있는지 작성하는 항목이 있었다. 그때마다 그 자리를 비워둔 채로 넘어갔는데, 막상 IP 주소를 올리려고 하니 마음에 걸렸다. 대놓고 IP 주소를 공개하는 것보다 깔끔하게 도메인을 연결하여 공개하는 것이 낫겠다는 생각이 들었다. 그래서 가비아에서 도메인을 얻어 EC2 인스턴스의 탄력적 IP를 연결해주었다.

 그랬더니 이제는 http 가 걸려서 https로 만들고 싶어졌다. 그래서 해당 내용을 찾기 시작했고, 지금 이 게시글을 작성하고 있다. 이번 작업을 마쳐도 뭔가 계속 이어나갈 것 같지만, 일단은 작업을 진행해보도록 하겠다. 참고한 블로그와 사이트를 footnote에 기록하고 시작한다.[각주:1] [각주:2]

 

Snap 버전 확인 or 설치

# snap 버전 확인
snap version

 우선 현재 snap이 설치되어 있는지 확인한다. 22년도 5월에 작성된 블로그 게시글에 따르면 ubuntu 16.04.4, 18.04, 20.04 버전을 사용하고 있다면 snap이 기본적으로 설치되어 있다고 한다.[각주:3] 필자가 위 명령어로 버전을 확인했을 때도, 이미 설치되어 있음을 알 수 있었다. 만약 설치해야 한다면 앞서 기록한 두 번째 footnote 사이트를 참고한다.

 

Snap을 최신 상태로 만들기

sudo snap install core

sudo snap refresh core

 위 두 명령어를 사용하여 snap을 최신 버전 상태로 만든다.

 

기존에 설치된 certbot 제거

sudo apt-get remove certbot

 두 번째 footnote 사이트에서는 snap으로 certbot을 설치하기 전에 먼저 기존에 어떤 방식으로든 설치된 certbot을 제거할 것을 권한다. 이는 certbot 명령어가 수행될 때, OS package로부터의 설치 대신에 snap이 사용되도록 하기 위함이라고 언급하고 있다.

 

Certbot 설치 및 사용 준비

# certbot 설치
sudo snap install --classic certbot

# certbot 사용 준비
sudo ln -s /snap/bin/certbot /usr/bin/certbot

 Snap을 통해 certbot을 설치하고 사용 준비를 한다. 사용 준비는 /snap/bin directory에 있는 certbot을 /user/bin directory에 있는 certbot에 symbolic link 하겠다는 명령어라고 한다. 혹시라도 체크해보고 싶다면 해당 directory로 가서 ls -al 명령어를 작성해보면 되겠다.

 

Certbot 실행하는 방식 선택

# 서버 재시작 필요
sudo certbot certonly --standalone

# 서버 재시작 필요 없음
sudo certbot certonly --webroot

 서버 재시작이 필요한 경우와, 이미 동작하는 서버가 있을 때 선택할 수 있는 방식의 두 가지가 있다. 필자는 아직 서버가 동작하고 있지 않으므로 첫 번째 방식을 택했다.

 

 명령어를 실행하고 나면 가장 먼저 이메일 주소를 묻는다. 이어서 서비스 정책에 동의하는지 묻고, 관련 메일을 받을 것인지 묻는다. 그리고 도메인 정보를 물은 뒤 마무리된다. 그러면 성공적으로 certificate가 발급되었다는 메시지를 확인하게 된다. 다음 작업은 certificate가 저장된 directory로 이동해서 진행한다.

 

Certificate가 저장된 directory로 이동 및 인증서를 pkcs12 형식으로 변환

sudo su

 바로 앞선 단계에서 certificate가 생성된 위치로 이동하려고 하면  Permission denied 된다. 이때 위 명령어를 사용해서 root 권한을 얻어 directory에 접근할 수 있다.

 

openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out keystore.p12 -name tomcat -CAfile chain.pem -caname root
  • -export : pkcs12 file을 생성하려고 한다.
  • -in : p12 file에 들어갈 인증서
  • -inkey : p12 file에 포함시킬 개인 키
  • -out : 생성할 p12 file name
  • -name : Java에서 KeyStore로 접근할 때 사용되는 alias라고 한다.
  • -CAfile : 인증서 발급 chain. 인증서의 묶음이라고 한다. Pem 방식을 이어서 작성해주면 된다고 한다.
  • -caname : 이것은 잘 모르겠다. Root CA(Certificate Authority)를 생성하는 것이라고 한다.

 위 명령어를 사용하면 생성하려고 한 이름 그대로 p12 file이 생긴 것을 볼 수 있다. 작업은 local에서 하기 때문에, 이 친구를 local로 옮겨주고 싶다.

 

Certificate from EC2 to Local

scp -i "local pem file 경로" ubuntu@{ip 주소}:{인스턴스의 파일 경로} {copy할 local 경로}

scp -i aws-ssh.pem ubuntu@ec2-{ip address}.ap-northeast-2.compute.amazonaws.com:/etc/letsencrypt/live/xxx/keystore.p12 ~/Desktop/Projects/aws

# directory에 대한 권한 변경
sudo chmod 777 /etc/letsencrypt/live/

 해당 작업은 local에서 진행된다. EC2 인스턴스에 접근하기 위한 key pem file이 있는 곳에서 원하는 file을 지정하여 local로 copy해오기 위한 명령어이다.[각주:4] 그냥 명령어를 수행하면 Permission denied 된다. 권한이 없기 때문인데, 이때 directory에 대한 접근 권한을 변경하면 정상적으로 file을 copy할 수 있게 된다.[각주:5]

 

Spring Boot application.properties setting

# https를 위한 pkcs12 file ssl 설정
server.ssl.key-store=classpath:kestore.p12
server.ssl.key-store-type=PKCS12
server.ssl.key-store-password=blah~ blah~
server.ssl.key-alias=tomcat

 필자는 EC2 인스턴스로부터 옮겨온 pkcs12 형식의 인증서를 프로젝트의 /src/main/resources 에 위치시켰다. 그리고 application.properties에 위와 같이 설정했다. 비밀번호는 인증서를 생성할 때 입력했던 것을 작성해주면 된다.

 

Local에서의 실행?

 이제 이렇게 설정된 것을 local에서 체크해보고 싶었는데, https로 도메인을 통해 접근하려고 했을 때 기존의 http에서의 '안전하지 않음'보다 더 안좋아보이는 '주의 요함'을 보게 되었다.

 

 안타깝게도 Let's Encrypt docs에 따르면 localhost에 대한 인증서는 제공할 수 없다고 적혀있다. 게다가 기존에 인증서를 생성할 때 입력했던 도메인은 localhost가 아니기 때문에 당연하게도 local에서는 생성한 인증서로 https 접속을 체크할 수 없다. 따라서 확인하고자 한다면 프로젝트를 build하여 EC2 인스턴스에서 직접 실행해보아야 한다.

 

Port Forwarding (443 to 8080)

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 8080

 이전 게시글에서 도메인을 연결하고 port forwarding을 했었다.[각주:6] Browser는 http에 대한 기본 port는 80, https에 대한 기본 port는 443으로 설정되어 있다. 따라서 이번에도 443 port를 8080 port로 forwarding 해주었다.

 

 

 이렇게 모든 작업을 마무리하고 도메인 앞에 https:// 를 달아 접근했을 때, 성공적으로 화면을 볼 수 있었다. 다음 게시글에서는 EC2 인스턴스가 왜 자꾸 터지는가에 대한 고찰을 해보려고 한다. 마침 밤에 켜놓고 잤는데, 아침에 터진 상황이다.

 

Reference

 

댓글