#5 웹 프로필 - SSL 인증서 및 와일드카드 인증서

2021. 10. 21. 23:35Projects/Web Profile

개요

나의 웹사이트에 CA 서버로부터 SSL 인증서를 받아와 설치하고, 해당 인증서를 통해 HTTPS 프로토콜을 활성화시킨다. 또한 서브도메인을 위해 와일드카드 인증서를 발급받는다. 

기본적으로 HTTP 프로토콜을 사용하는 것은 매우 위험하다. 이유는 사용자의 세션 정보가 암호화되지 않아 외부로 노출될 수 있기 때문이다. 회원가입 또는 로그인 기능이 탑재되어있는 웹 애플리케이션이 HTTP 프로토콜로 동작한다면 사용자가 입력하는 아이디와 비밀번호부터 개인정보까지 모두 외부로 노출되어 악용될 수 있다. 하지만 HTTPS 프로토콜을 사용하면 클라이언트에서 서버로 들어오는 정보는 모두 암호화되고 해당 암호를 해독할 수 있는 열쇠(key)는 서버에 저장되어있어 서버와 클라이언트만 해당 암호화된 HTTPS 프로토콜을 통해 통신할 수 있다. 제삼자가 정보를 빼내가도 열쇠(key)가 없다면 쉽게 해독할 수 없다. 

현재 나의 웹사이트는 이메일 기능을 위한 사용자의 이름, 이메일, 이메일 내용 입력 정도밖에 요구하지 않는다. 그 외 기능은 모두 Static으로 사용자의 입력을 필요로 하지 않아 HTTP 프로토콜 동작 시 외부로 노출되는 사용자의 개인정보가 거의 없다고 할 수 있다. 하지만 요즘에는 많은 웹사이트가 HTTPS 프로토콜로 동작하고, HTTP 프로토콜을 통한 통신을 웹 브라우저에서 기본적으로 막고 있는 추세이다.


SSL 인증서와 와일드카드 인증서

CA 서버는 SSL 인증서를 발급해주는 서버이다.

과거에 리눅스 시스템에 CA 서버를 직접 만들어 해당 서버에서 SSL 인증서를 받아오는 것을 진행해보았지만, HTTPS인증은 되지만, 인증되지 않은 CA 기관이라며 오류가 발생하였고, 접속 또한 매끄럽지 못했다. 이유는 직접 만든 CA 서버가 인증받은 CA 서버가 아니어서 그렇다고 알고 있다.

이번에는 조금 더 제대로 HTTPS를 구현해보고 싶어 비록 무료이긴 하지만 "let's encrypt"라는 CA 서버에서 발급받은 SSL 인증서를 사용했다.  

와일드카드 인증서란 여러 서브도메인에 하나의 인증서를 통해 모두 인증하는 인증 방식이다. 현재 app.leinadynohp.site 서브도메인을 사용하여 django 프로젝트를 하나 배포해놓았기 때문에 와일드카드 인증서 방식을 사용했다.


Free vs. Paid

SSL 인증서는 무료로 발급받거나 유료로 구매할 수 있다. 

궁금증에 리서치를 해본 결과 무료 인증서와 유료 인증서의 암호화 단계(level)는 큰 차이가 없다는 내용을 찾을 수 있었다.

하지만 차이점은 분명히 있었다. 무료 인증서는 인증서 갱신 주기가 짧고(최대 90일), 유료 인증서는 주기가 길다(최대 2년). 또한 도메인만을 인증해주는 무료 SSL과는 다르게 도메인 소유자(기업)의 정보를 받아 해당 소유자를 인증해주고, 문제가 생길 시 대처 방식에서 또한 차이점이 있다고 한다. 


AWS IAM 유저 생성

AWS에서 IAM 은 Identity and Access Management의 약자이다. 와일드카드 SSL 인증서를 설치하기 위해서는 Cerbot을 실행할 때 AWS의 사용자 ID(Access Key ID)와 비밀키(Secret Access Key)가 필요하다. 하지만 여기서 root 또는 administrator 계정을 넣으면 보안에 위협이 될 수 있다. 그래서 이전 포스트에서 생성한 hosted zone만을 관리할 수 있는 계정을 따로 생성해주어야 한다. 

IAM User for cerbot

위와 같이 유저를 생성해 준 후 cerbot 공식문서에 명시되어있는 필수 권한만 설정해주었다.

필수 권한,
route53:ListHostedZones
route53:GetChange
route53:ChangeResourceRecordSets

공식문서,
certbot-dns-route53.readthedocs.io/en/stable/

Certbot

쉘 접속(Shell Access)이 가능한 환경에서 let's encrypt를 통해 SSL 인증서를 받아올 때는 certbot을 활용하는 것이 가작 접합하고 손쉬운 방법이다. 

Cerbot 또한 여러 방법이 있지만, 일반적으로 웹서버 자체에 SSL 인증서를 설치하고 싶은 경우 cerbot 공식 사이트에 나와있는 절차를 따라 하면 SSL 인증서 설치 및 Apache, Nginx 등의 웹서버 설정 또한 자동으로 해주는 것 같다. 

하지만 나의 경우 리버스 프록시 하단에 웹서버가 위치해있고 서버들 또한 도커 컨테이너에서 동작하고 있어 컨테이너 자체에 cerbot을 설치하는 것은 조금 꺼림칙했다. 그리고 현재 서브도메인 또한 사용 중이기 때문에 와일드카드 인증서 또한 필요하여 다른 방법을 찾아보니 Cerbot에서 공식적으로 배포한 도커 컨테이너가 있었고, Rotue53을 위한 DNS 플러그인이 탑재되어있는 컨테이너도 있어 해당 컨테이너를 사용하기로 했다.

docker command to run certbot container

dns-route53 플러그인이 포함된 Certbot 컨테이너를 실행하기 위해 위와 같이 명령어를 사용했다.

--name : 컨테이너의 이름을 지정한다.
-v : 호스트 시스템의 디렉터리를 컨테이너 내부의 디렉터리로 마운트 한다. (호스트 시스템에 해당 디렉터리가 존재하지 않는다면 명령어 입력 시 새로 생성되고, 마운트 이후 컨테이너 내부에서 생성된 파일들은 호스트 시스템 속 마운트 포인트에도 똑같이 저장된다. 이러한 원리로 컨테이너 내부에서 생성되는 SSL 인증서가 호스트 시스템의 디렉터리로 같이 저장된다.)
--env : 컨테이너 생성 시 컨테이너 내부에 설정할 환경변수를 정의해준다. dns-route53 플러그인을 사용하여 와일드카드 인증서를 적용할 경우  Route53에 접근할 수 있는 유저의 권한이 필요하다. 이 옵션을 사용자 ID와 비밀키를 환경변수로 설정해준다. 
certonly : SSL 인증서를 받기 위한 cerbot의 명령어이다.
-d : 와일드카드 인증서를 적용할 도메인과 서브도메인을 지정할 수 있다. 
--manual : Certbot은 자동으로 웹서버에 인증서를 설치해주지만 해당 옵션을 사용하여 자동으로 설치하지 않고 내가 직접(mannually) 설정할 수 있다. 웹서버에서 직접 certbot을 설치하지 않는 경우 해당 옵션을 사용한다.
--preferred-challenges :  http와 dns 옵션이 존재한다. DNS 와일드카드 인증서를 적용할 예정이므로 dns라고 명시해준다. 

TXT Record Value
TXT Record Value
TXT Record Value
Route53 Hosted Zone

해당 명령어를 입력하면 몇 개의 지시사항이 나오며 도메인과 서브도메인의 TXT 레코드 값을 준다. Router53의 호스트 영역에서 Certbot으로부터 받은 TXT 레코드 값을 하나씩 추가해준다. 마지막에 Certbot에서 지시한 것과 같이 레코드 등록이 완료가 되면 Certbot에서 더 진행하기 이전에 "https://toolbox.googleapps.com/apps/dig/#TXT" 링크에서 _acme-challenge.<my-domain>. 과 같이 입력해주면 각 도메인과 서브도메인인에 해당되는 값이 보이게 된다. 해당 링크에서 값이 제대로 출력되는지 확인한 후 Certbot에서 진행을 해야지만 오류가 나는 불상사를 피할 수 있다. 

* 해당 TXT 레코드 값의 용도와, 해당 값이 노출이 되어도 안전한지 확실하지 않아서 Stack Overflow에 질문글을 올렸다. 답변받은 내용은 아래와 같고 결론은 단순히 Certbot에서 내가 해당 도메인의 소유권이 있는지 확인하는 용도일 뿐이고, 비밀번호 같이 노출시키지 않도록 주의할 필요는 없다는 답변을 받았다.

"해당 값은 비밀이 아닙니다. 해당 값은 그저 당신이 그 도메인을 소유하고 있는지 증명하는 용도입니다. 제가 '이 계정이 진짜 당신의 페이스북 계정인지 확인을 위해 모자를 쓰고 있는 다람쥐의 사진을 업로드해주십시오'라고  요청하는 것과 똑같습니다. 그 다람쥐 사진은 비밀이 아니죠, 사실 제가 당신이 업로드한 그 다람쥐 사진을 보기 위해서는 공개되어 있어야만 합니다. 각각의 레코드 값들은 당신에게 고유해야 하고, 다른 사람의 도메인에 연결되어있는 값과 동일해서는 안 되는 것 또한 사실입니다 (그래서 비밀번호처럼 보였을 수도 있습니다), 제가 페이스북 계정 확인을 위해 그냥 아무 고양이 사진을 업로드해달라고 요청하지 않는 것과 같은 거죠."

원본 링크
https://stackoverflow.com/questions/69668834/what-are-the-txt-record-values-from-certbot

마치며

정리해보니 그다지 어려운 내용은 없지만 해당 과정을 진행하는 데 있어 많은 오류와 고충이 있었다. 첫 번째로는 기본적으로 certbot을 리눅스 시스템에 설치하는 튜토리얼 자료는 많이 있지만 도커와 certbot/dns-route53 컨테이너를 사용하는 과정을 정리해놓은 자료는 많이 없어서 certbot 공식문서를 하나씩 읽어보며 사용법을 익히는데 많은 시간이 투자되었다. 두 번째로는 도커 명령어를 실행할 때 예상치 못한 권한 문제로 시간과 체력을 많이 빼앗겼다.

docker command to run cerbot container

위 사진은 첫 번째로 cerbot/dns-route53 컨테이너를 실행할 때 사용한 명령어이다. 맥 OS에서 실행하였는데, 모든 인증서 설치 과정이 완료된 후 인증서를 찾으려고 하였지만 어디에도 인증서가 있지 않았다. 이유는 로컬의 /etc/ 디렉터리는 root 계정의 디렉터리이고, 일반 유저는 해당 디렉터리에 쓰기(write) 권한이 없어 -v 옵션 적용이 되지 않았던 것이다. 

오류의 원인을 발견하고 로컬 디렉터리 위치를 일반 유저 소유의 디렉터리 경로로 설정한 후 다시 명령어를 실행하니 정상적으로 SSL 인증서 설치가 된 것을 확인할 수 있었다.