Let's Encrypt는 어떻게 자동으로 인증서를 갱신할 수 있을까?
이메일로 블로그 포스트 받아보기: https://techchallengearena.substack.com
요즘은 대부분의 애플리케이션에서 HTTPS를 사용한다. 개인 블로그를 하더라도 HTTPS를 통해서 안전한 연결을 하도록 하는 것이 보통이다. HTTPS 연결이 필요한 이유는 SSL 인증서 덕분에 클라이언트와 서버가 통신을 할 때 암호화된 상태로 통신하여 최소한의 안전을 제공해 주기 때문이다.
HTTPS가 대중적으로 널리 사용된 계기 중 하나가 바로 Let's Encrypt의 등장이 아닐까 싶다. Let's Encrypt는 도메인 소유자에게 무료로 SSL 인증서를 제공해 준다. 대표적인 프런트 앱 도구인 Vercel도 Let's Encrypt를 통해 인증서를 제공해 준다.
SSL 인증서 발급을 위해서는 웹사이트와 사용자의 안전한 통신을 보장하기 위해 인증 기관(CA, Certificate Authority)이 웹사이트의 신뢰성을 증명하는 과정을 포함한다. 즉, CA의 개입 없이는 인증서를 발급하거나 인증할 수 없다. 따라서 CA는 누구나 신뢰할 수 있다는 전제하에 인증서 발급/인증이 이루어진다. Let's Encrypt나 Digicert와 같은 기관이 바로 CA를 운영하고 있는 기관이다.
인증서를 발급하는 절차는 다음과 같다.
먼저, 비대칭 암호화 알고리즘을 사용하여 키 쌍을 생성한다. 비대칭 암호화 알고리즘에는 RSA 또는 ECC가 포함되며, 이 과정에서는 공개 키(Public Key)와 개인 키(Private Key)라는 두 개의 키가 생성된다. 공개 키는 인증서에 포함되며 누구나 볼 수 있는 정보이지만, 개인 키는 서버에서만 사용되고 절대 외부로 유출되지 않도록 안전하게 보관해야 한다.
다음은 개인 키를 사용하여 인증서 서명 요청(CSR)을 생성한다. CSR은 SSL 인증서를 발급받기 위해 CA에 제출하는 데이터 파일이다. CSR에는 공개 키와 함께 도메인 이름, 조직 정보, 위치 등과 같은 중요한 정보가 포함된다. CA는 이 정보를 사용하여 도메인 소유권 및 조직의 신원을 확인한다. CSR을 생성할 때 입력하는 정보는 SSL 인증서에 포함되므로 정확하게 작성해야 한다. CSR 데이터는 개인 키를 통해서 암호화한다.
CSR이 생성되면 이를 CA에 제출해야 한다. CA는 제출된 CSR을 검토하고, 도메인 소유권 및 조직 신원을 확인하는 절차를 밟는다. CA는 일반적으로 세 가지 유형의 검증을 제공한다. (참고로, 이 중 Let's Encrypt는 DV 방식을 사용한다.)
도메인 검증(DV): 가장 기본적인 방법으로, 주로 이메일 확인이나 DNS 기록 확인을 통해 이루어진다.
조직 검증(OV): 도메인 검증에 추가로 조직의 실제 존재 여부를 확인하는 단계가 추가된 방식이다.
확장 검증(EV): 가장 엄격한 검증 방식으로, 조직의 법적, 물리적, 운영적 존재를 철저히 확인한다.
CA는 검증 절차가 완료되면 CSR에 포함된 정보를 바탕으로 SSL 인증서를 발급한다. SSL 인증서에는 공개 키, 도메인 이름, 조직 정보, 발급 날짜 및 만료 날짜 등이 포함된다. 발급된 인증서는 CA의 디지털 서명으로 서명되며, 이는 인증서의 신뢰성을 보장하는 중요한 요소이다.
이렇게 과정을 거치면 인증서 발급이 완료된다. 관리자는 인증서 발급이 완료되면, 웹 서버 혹은 로드 밸런서 등에 인증서를 설치한다. 이때 필요한 파일은 인증서 체인과 개인 키 파일이다. 인증서 체인은 서버 인증서와 루트 인증서 간의 Chain Of Trust 가 맺어진 연결고리를 의미한다. 해당 체인에는 중간 인증서도 있는데, 이는 루트 인증서와 서버 인증서의 중간 체인을 연결하기 위해서 사용된다.
이렇게 설치가 완료되면, 클라이언트와 서버는 TLS로 통신이 가능하다.
위 과정에서 3번 부분을 자세하게 살펴보자.
서버는 Server Hello 이후 자신이 가지고 있는 인증서 체인을 전달한다. 해당 체인에는 서버 인증서 - 중간 인증서가 포함되어 있다. 루트 인증서는 이미 클라이언트나 운영체제에 설치가 되어 있기 때문에 따로 공유하지 않는다.
클라이언트는 전달받은 인증서 중 서버 인증서가 중간 인증서로 사인되었는지, 확인한다. 그리고 중간 인증서는 자신이 신뢰하고 있는 루트 인증서로 사인되었는지 확인한다. 이 과정에서 만료되었거나 취소된 인증서가 있는지도 체크한다. 이 모든 과정을 거치게 되면, 클라이언트는 서버 인증서에서 공개 키를 추출한다. 서버 인증서는 X.509 인증서이기 때문에 디코딩 과정을 거치면, 공개 키를 알아낼 수 있다.
위와 같은 과정은 실제로 많은 시간이 소요된다. 또한, 인증서가 만료되면 매번 수동으로 갱신을 해주어야 한다. 이러한 번거로움을 없애고자 나온 게 바로 ACME 프로토콜이다.
ACME(Automated Certificate Management Environment) 프로토콜은 SSL/TLS 인증서를 자동으로 발급하고 갱신하기 위해 설계된 프로토콜이다. 이 프로토콜은 Let's Encrypt와 같은 무료 인증 기관(CA)에서 주로 사용되며, 인증서 관리를 보다 쉽게 자동화할 수 있도록 도와준다.
ACME 프로토콜의 동작 원리는 다음과 같다.
1.Certbot과 같은 ACME 클라이언트를 서버에 설치한다.
2. ACME 클라이언트를 사용하여 인증 기관(CA)에 계정을 등록한다. 보통 이메일 주소를 제공하여 계정을 생성하고 ACME 서버와 통신하기 위한 계정 키를 생성하는 과정을 거친다.
3. 계정 등록이 완료되면, ACME 클라이언트는 인증서 발급을 요청한다. 이때, 도메인 소유권을 검증하게 되는데, 대표적으로 DNS에 TXT 레코드를 추가하는 방식이 있다. 또 다른 방식으로는 인증 토큰 파일을 웹서버의 특정 위치에 넣고, 이를 확인하는 방식이 있다.
4. 도메인 소유권 검증이 완료되면, CA는 인증서를 발급한다. ACME 클라이언트는 발급된 인증서를 다운로드하여 서버에 설치해 준다. 만약 nginx를 웹서버로 사용한다면, 자동으로 nginx의 SSL 관련 설정을 추가해 주고, 필요한 파일을 경로에 넣어준다.
이렇게 발급받은 인증서는 자동으로 갱신할 수 있다. 보통 만료 날짜가 가까워지면, ACME 클라이언트가 자동으로 이를 인지하여 새로운 CSR을 생성하고, 갱신 요청을 CA에 전달한다. CA는 앞서 진행했던 도메인 소유권 검증 과정을 다시 한번 거친 후에 인증서를 갱신해 준다. 이때 새로운 인증서가 발급되고, ACME 클라이언트는 이를 기존 인증서 자리에 덮어쓴다. 이제 서버를 재시작하거나 reload 하면 새로운 인증서를 통해서 TLS 통신이 가능해진다.
실제로 잘 동작하는지 확인하기 위해 certbot을 사용하여 간단히 테스트를 해보았다. 테스트를 위해서 로컬에 nginx와 certbot을 설치했다.
테스트에 앞서, 공인 CA 없이 자체 승인한 상태에서는 웹페이지가 어떻게 나오는지 확인해 보았다. Openssl을 통해서 만든 사설 인증서를 넣고 nginx SSL 설정을 추가했다. 도메인은 techchallengearena.com을 사용했다. 이후에 접속을 해보니 다음과 같이 인증서가 올바르지 않다는 경고문이 나왔다.
이제는 Certbot을 통해서 Let's Encrypt로부터 공인된 인증서를 발급받아 보았다. Certbot을 통해서 인증서 발급을 요청하면 다음과 같은 문구가 나온다.
먼저, Account registered 문구에서 볼 수 있듯이 계정을 등록한다. 이후에 도메인 인증을 위해서 TXT 레코드를 알려준다. 테스트를 위해서 수동으로 넣도록 했는데, Route53이나 Cloudflare 등에 자동으로 레코드를 추가해 주는 옵션도 있다.
아래와 같이, 레코드를 추가한 후, Enter를 누르면 된다.
그러면, 아래와 같이 인증서 체인인 fullchain.pem과 개인 키인 privkey.pem 파일이 생성된다. 이 두 파일을 기존 nginx SSL 설정에 추가해 주면 끝난다.
인증서를 추가한 후에 다시 접속을 시도하면 다음과 같이 Let's Encrypt에서 발급되었다고 나온다. 이제, HTTPS를 통해서 로컬 nginx에 접속을 할 수 있게 된 것이다.
요컨대, 최소한의 보안 사항 중 하나인 HTTPS 통신을 위해서는 SSL 인증서가 필요하다. SSL 인증서는 반드시 신뢰할 수 있는 CA에서 발급받아야 하는데, 그중 하나가 바로 Let's Encrypt이다. Let's Encrypt는 CA인 동시에 ACME 서버 역할을 하고, ACME 클라이언트는 서버와 통신을 주고받으며, 자동으로 인증서를 발급하고, 갱신할 수 있다. 이 덕분에 매번 수동으로 갱신해야 하는 부담도 줄일 수 있고, 누구든 쉽게 인증서를 받을 수 있게 되었다.
참고자료