[TLS] Let's Encrypt 를 이용하여 무료로 TLS 인증서를 발급/갱신해보자

Hocaron·2024년 5월 1일
1

DevOps

목록 보기
5/5

도메인을 구입해서 TLS 인증서를 발급받을 때 주로 사용했던 AWS CA 대신 Let's Encrypt 를 사용해서 직접 인증서를 발급 / 갱신해보자.

앞서 포스팅했던 Jenkins 대신 Github Action 으로 배포하기에서 CD 스크립트에 아래와 같은 명령어가 있다. nginx 컨테이너를 띄우고, TLS 인증서를 발급받기 까지의 과정을 살펴보자.

docker exec -i nginx nginx -s reload

우선 TLS(Transport Layer Security)는 무엇일까?

전송 계층 보안(TLS)은 인터넷 상의 커뮤니케이션을 위한 개인 정보와 데이터 보안을 용이하게 하기 위해 설계되어 널리 채택된 보안 프로토콜이다. TLS의 주요 사용 사례는 웹 사이트를 로드하는 웹 브라우저와 같이 웹 응용 프로그램과 서버 간의 커뮤니케이션을 암호화하는 것이고,이메일, 메시지, 보이스오버 IP(VoIP) 등 다른 통신을 암호화하기 위해 사용된다.

TLS는 국제 표준 기구인 IETF(Internet Engineering Task Force)에 의해 제안되었으며 프로토콜의 첫 번째 버전은 1999년에 발표되었다. 가장 최신 버전은 2018년에 발표된 TLS 1.3이다.

TLS와 SSL의 차이점은 무엇일까?
TLS는 Netscape가 개발한 SSL(Secure Sockets Layer)이라고 불리는 이전의 암호화 프로토콜에서 발전한 것이다. TLS 버전 1.0은 SSL 버전 3.1로서 개발을 시작했지만 Netscape와 더 이상 연관이 없음을 명시하기 위해 발표 전에 프로토콜의 이름이 변경되었다. 이러한 역사 때문에 가끔 서로 바꿔서 사용된다.

TLS와 HTTPS의 차이점은 무엇일까?
HTTPS는 HTTP 프로토콜 상위에서 TLS 암호화를 구현한 것으로 모든 웹 사이트와 다른 웹 서비스에서 사용된다. 따라서 HTTPS를 사용하는 웹 사이트는 TLS 암호화를 이용한다.

TLS 인증서란 무엇일까?

웹 사이트나 응용 프로그램이 TLS를 사용하기 위해서는 원본 서버에 TLS 인증서가 설치되어 있어야 한다(위에서 설명한 이름 혼동 때문에 이 인증서는 "SSL 인증서"라고도 알려져 있다). 인증 기관이 도메인을 소유한 사람 혹은 비즈니스에게 TLS 인증서를 발행하면,
서버의 공개 키와 누가 도메인 소유자인지에 대한 정보를 통해 서버의 신원을 확인하는 데 사용된다.

TLS는 어떻게 작동할까?

TLS 연결은 TLS Handshake로 알려진 일련의 순서를 통해 수행된다.

  1. 사용할 TLS 버전(TLS 1.0, 1.2, 1.3 등)을 지정
  2. 사용할 암호 제품군(아래 참고)을 결정
  3. 서버의 TLS 인증서를 사용하여 CA 로부터 서버의 신원을 인증
  4. 클라이언트는 서버의 공개키로 대칭키를 암호화 하여 서버에게 보냄
  5. 서버는 자신의 비밀키로 이를 복호화 하여 클라이언트의 대칭키(세션 키)를 알아냄
  • 공유된 암호화 키 또는 세션 키와 같은 세부 정보를 명시하는 알고리즘 집합으로 해당 특정 세션에 사용된다. 공개 키 암호화로 알려진 기술 덕분에 TLS는 암호화되지 않은 채널을 통해 일치하는 세션 키를 설정할 수 있다.

그럼 이제 둘은 대칭키로 암,복호화 하여 통신을 하는 것이다.

Handshake는 또한 인증을 처리하며, 이는 대개 클라이언트에게 신원을 증명하는 서버로 구성된다. 이는 공개 키를 사용하여 수행된다. 공개 키는 단방향 암호화를 사용하는 암호화 키로, 공개 키를 가진 누구나 신뢰성을 보장하기 위해 서버의 개인 키로 암호화된 데이터를 해독할 수 있음을 의미하지만 원래 발신자만 개인 키를 사용해 데이터를 암호화할 수 있다. 서버의 공개 키는 TLS 인증서의 일부이다.

데이터카 암호화되고 인증되고 나면, 메시지 인증 코드(MAC)와 함께 서명됩니다. 수신자는 데이터의 무결성을 보장하기 위해 MAC를 확인할 수 있다.

이제 TLS 는 뭔지 조금을 알 것 같다. Let's Encrypt 로 인증서를 발급받아보자

도메인과 서버 IP 매핑을 위해 A 레코드 등록


A 레코드는 컴퓨터에서 도메인 이름을 IP 주소로 변환하는 데 사용된다. 나는 Route53 을 통해 도메인을 구입하였으므로, Route53 에서 구매한 도메인의 하위 도메인으로 개발 API 서버를 생성하고, 서버가 구동되는 ec2 인스턴스의 IP 주소와 매핑해놓았다.

docker-compose 로 nginx 의 공식 이미지 와 Let's Encrypt 인증서를 얻기 위한 EFF 도구인 certbot 빌드 스크립트 작성

version: "3"
services:
  nginx:
    container_name: 'nginx'
    image: nginx
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/certbot/conf:/etc/letsencrypt
      - ./nginx/certbot/www:/var/www/certbot
  certbot:
    container_name: 'certbot'
    image: certbot/certbot:v0.36.0
    volumes:
      - ./nginx/certbot/conf:/etc/letsencrypt
      - ./nginx/certbot/www:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

nginx 스크립트 구성

########################## api(8071/8070) ##########################
server {
    listen 80;
    server_name example.org;
    server_tokens off;

    location /.well-known/acme-challenge/ {
        allow all;
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name example.org;
    server_tokens off;

    ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://example.org:{서버포트};
        proxy_set_header Host $host:$server_port;
        proxy_set_header X-Forwarded-Host $server_name;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    error_page 502 /502.json;
    location /502.json {
        return 502 '{"data": null, "code": "BAD_GATEWAY", "message": "received an invalid response from the upstream server"}';
    }
}

더미 인증서를 생성하고, nginx를 시작한 후, 더미를 삭제하고 실제 인증서를 요청

et's Encrypt 유효성 검사를 수행하려면 nginx가 필요하다. 하지만 인증서가 없으면 nginx가 시작되지 않는다.

이를 위해 편리한 스크립트가 있다. 다음과 같이 스크립트를 작업 디렉터리에 다운로드한다.

$ curl -L https://raw.githubusercontent.com/wmnnd/nginx-certbot/master/init-letsencrypt.sh > init-letsencrypt.sh

그런 다음 실행

$ chmod +x init-letsencrypt.sh
$ sudo ./init-letsencrypt.sh.

자동 인증서 갱신

entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

위 스크립트는 docker-compose 에 이미 정의되어있다.

$  /bin/sh -c 'while:; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"

이렇게 하면 nginx가 백그라운드에서 6시간마다 구성(및 인증서)을 다시 로드하고 포그라운드에서 nginx를 시작한다.

번외: AWS Route53 레코드의 다양한 유형

SOA(권한 레코드 시작)

Basic SOA는 아래와 같은 정보를 저장한다.

  • 영역에 대한 데이터를 제공한 서버의 이름
  • 해당 영역의 관리자 및 데이터 파일의 현재 버전

NS 레코드(네임 서버 레코드)

NS 레코드는 기본적으로 최상위 도메인 서버에서 권한 있는 레코드가 포함된 콘텐츠 DNS 서버로 트래픽을 전달하는 데 사용되는 이름 서버 레코드이다.

따라서 Route53에서 호스팅 영역을 생성할 때마다 두 가지 유형의 레코드가 자동으로 생성된다. 하나는 SOA 이고 두 번째는 NS 이다.

  • TTL(Time to Live):
    각 DNS 레코드에는 TTL이 필수이다. 따라서 TTL은 DNS 레코드가 확인 서버나 사용자 자신의 노트북에 캐시되는 길이이다. TTL이 낮을수록 DNS 레코드 변경 속도가 빨라진다. 레코드 세트를 생성할 때마다 이에 대한 TTL을 정의해야 한다.

A 레코드(IPv4에 대한 URL)

주소 레코드를 나타냅니다. A 레코드는 컴퓨터에서 도메인 이름을 IP 주소로 변환하는 데 사용됩니다.

예: (http://medium.com은 http://126.78.98.90을 가리킬 수 있다.)

CNAME(표준 레코드- URL에서 URL로)

URL을 다른 URL로 가리킵니다. (gaurav.gupta.com => gkg.example.com), 루트가 아닌 도메인(aka.something.mydomain.com)에만 사용한다.

별칭 레코드

AWS 리소스에 대한 URL을 가리키며, 별칭 레코드는 호스팅 영역의 리소스 레코드 세트를 Elastic Load Balancer, CloudFront 또는 S3 버킷 웹 사이트에 매핑하는 데 사용된다.

4- AAAA: (IPv6에 대한 URL)

도메인 이름을 도메인을 호스팅하는 컴퓨터의 IP 주소(버전 6)에 매핑한다. AAAA 레코드는 이름에서 인터넷에 연결된 컴퓨터의 IP 주소를 찾는 데 사용된다.

MX 레코드(주 교환 레코드)

도메인 이름을 대신하여 이메일 메시지를 수락하는 메일 서버를 지정한다. DNS (Domain Name System)의 리소스 레코드이다. 일반적으로 부하 분산 및 중복성을 위해 메일 서버 배열을 가리키는 여러 MX 레코드를 구성할 수 있다.

References

profile
기록을 통한 성장을

0개의 댓글