[AWS] S3 & CloudFront 와 외부 공급자 ( Cloudflare ) 를 통한 CNAME 설정.

김지환·2023년 2월 8일
0
post-thumbnail

TL:DR;

간단한 Docs 서비스를 aws s3를 통해서 제공하고자 했는데 그 과정중에 SSL/TLS 인증서가 ACM을 통해서 어떻게 받아지고 관리되는지에 대한 이해가 부족해서 Cloudflare에 연결하는데 시간을 허비했다.

고쳐나가면서 필요했던 정보들을 기록하고 잊지말자!

S3 static website hosting 서비스

s3 에는 static hosting 기능이 제공된다.

s3에 bucket을 만들고 bucket 의 properties 탭으로 들어가서 아래로 내려가다 보면 Static website hosting 이 있다.

Edit을 통해서 해당기능을 enable 시키게 되면 설정을 할 수 있는데 두 가지 호스팅 타입이 있다.

  • Host a static website: 해당 bucket 을 통해서 client side scripting 만을 제공하는 단순한 website 서비스할 수 있다.
  • Redirect requests for an object: request를 bucket 의 object 또는 custom endpoint로 전달할 수 있다.

해당 블로그에서는 Host a static website만 기술하도록 하겠다.

Host a static website 타입을 선택하면 index document, error document, redirection rules 를 설정할 수 있다.

index document를 설정해서 endpoint를 통해서 사용자에게 보여줄 index.html 을 설정하면 된다. 해당 bucket에 있는 html 을 설정하면 되고 index 라는 명칭을 꼭 사용할 필요는 없다.

error document는 error 가 발생했을 때 보여줄 page 를 등록하는 것.

Redirection rules 는

[
    {
      "Condition": {
        "HttpErrorCodeReturnedEquals": "string",
        "KeyPrefixEquals": "string"
      },
      "Redirect": {
        "HostName": "string",
        "HttpRedirectCode": "string",
        "Protocol": "http"|"https",
        "ReplaceKeyPrefixWith": "string",
        "ReplaceKeyWith": "string"
      }
    }
  ]

위와같이 특정 조건에 대해서 어떻게 redirect할지를 설정하는 기능이다.

설정을 완료하고 나면 object에 접근할 수 있는 권한을 부여해줘야한다.

Block public access 를 통해서 필요에 따른 access 정도를 설정할 수 있다. 완전 public 오픈을 하려면 모든 block을 off 하면 된다.

그후 Bucket policy를 설정해주면 된다.

AWS 에서 제공해주는 정책생성기를 사용해서 만들어도 좋고 docs 를 참고해서 만들어도 된다. 단순 read 권한만 주기 위해 아래와 같이 GetObject action만 추가하였다.

{
    "Version": "2012-10-17",
    "Id": "Policy1661773862871",
    "Statement": [
        {
            "Sid": "Stmt1661773860570",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::your-bucket-name/*"
        }
    ]
}

이를 설정했으면 properties tap에서 제공되는 endpoint를 확인할 수 있다. 이를 통해서 접속이 가능하다. 하지만 s3 static website hosting은 SSL/TLS를 제공해주지는 않는다. (각 object에 대한 https 는 되는데 이건 안된다.) 따라서 추가적으로 CloudFront 혹은 Loadbalancer를 달아줘야한다. 하지만 굳이 Loadbalancer를 달아줄 필요는 없으니 CloudFront로 대체.

AWS ACM ( Amazon Certificate Manager) 의 인증서 발급

https 를 사용하기 위해서는 SSL 인증서가 필요하다 따라서 해당 인증서를 발급받아줘야한다. AWS에서는 ACM을 통해서 인증서 발급이 가능하다. AWS 자체에서 Route 53 을 통해 도메인 등록이 가능하지만 따로 외부 공급자 ( 고대디, 가비아, Cloudflare )를 사용한다면 해당 공급자에서 정보를 가져오게 된다.

ACM 을 통해서 인증서를 발급을 신청할 때 2 가지 옵션이 있는데

  • Dns validation
  • Email validation

Email validation은 AWS에 등록된 이메일 계정을 통해서 인증을 하는 방식이다.

Dns validation 은 CA 의 CNAME record를 등록하여서 이를 통해서 검증을 하는 방식이다.

Dns validation

값을 모두 설정하고 요청을 날리게 되면 Certificate이 생성되고 다음과 같은 CNAME 값을 주게된다.

(Record value 값은 _424c7224e9b0146f9a8808af955727d0.acm-validations.aws.)

해당 값을 사용하고 있는 CA에 등록해주면 된다.

위 예는 Cloudflare이다. 위와 같이 등록을 해주면 인증서의 유효성검사가 통과되게 되고 ACM에서 CA의 인증서를 받아 관리를 할 수 있게 되는 것이다.

값을 등록할 때는 Domain Name, Record Name(Key), Record Type, Record Value(Value) 모두 정확하게 입력해줘야한다. 그래야 검사를 통과할 수 있음!

ACM 은 이 Key, Value 값을 Ownership 검사를 하게 되는데 같은 Key, Value를 사용하는 ACM이라면 같은 인증서라고 보면 된다.

이렇게 한 번 등록하고 나면 추가로 ACM을 발행할 때 따로 등록할 필요없이 바로바로 사용할 수 있어서 편리하다.

CloudFront를 통한 S3 연결

ACM 발급까지 끝났다면 CloudFront를 s3에 연결하면 된다. (부가적인 기능들은 생략하고 SSL 설정만 다루도록 하겠음 )

Origin domain으로 설정한 s3 static website 의 endpoint를 등록해주고 name을 정해준다. 추가로 Routing될 때 헤더값을 추가할 수 있는데 해당 설정이 필요하다면 추가하면 된다.

등록했던 SSL 인증서를 등록

생성을 하면 Domain name 및 기타 정보들이 제공된다.

해당 Domain name을 통해서 접속이 가능하며 이제 최종적으로 해당 값을 CA에 DNS Record를 등록하여 사용할 수 있게 된다.

SSL/TLS 인증서 발급 과정과 SSL Handshake 과정

Cloudflare에서는 인증서를 통해서 검증을 마친 request들만 pass를 시키고 있었는데 인증서 작업을 거치지 않은 static website를 연결하려고 하니 SSL handshake flaed 문제가 발생했었다.

인증서 발급 과정

  1. 서버의 공개키(public key)와 비밀키(private key)를 생성한다.
  2. 인증서를 발급받기 위해, 서버는 CA 에 아래의 정보들을 전달한다.
    • 1번에서 생성한 서버의 공개키(public key)
    • 서버의 각종 정보
  3. 2번에서 서버로부터 받은 정보(서버의 공개키도 들어있음)들을 담아 SSL 인증서를 발급한다.
  4. 3번에서 만든 인증서를 암호화하기 위해, CA의 공개키(public key)와 비밀키(private key)를 생성한다. CA의 비밀키를 이용해 SSL 인증서를 암호화한다.
  5. 4번에서 암호화한 SSL 인증서를 다시 서버에 전달한다. SSL 인증서 발급 완료

SSl Handshake

SSL 이 일어나기 전에 TCP 3-way-handshake가 일어난다.

그 후에 아래와 같이 일련의 과정을 거치게 된다.

  1. 'ClientHello' 메시지: 클라이언트가 서버로 "헬로" 메시지를 전송하면서 핸드셰이크를 개시. 이 메시지에는 클라이언트가 지원하는 TLS 버전, 지원되는 암호 제품군, 그리고 "Client Random"라고 하는 무작위 바이트 문자열이 포함되어 있음.

  2. 'ServerHello' 메시지: ClientHello 메시지에 대한 응답으로 서버가 서버의 SSL 인증서, 서버에서 선택한 암호 제품군, 그리고 서버에서 생성한 또 다른 무작위 바이트 문자열인 "Server Random"를 포함하는 메시지를 전송

  3. 인증: 클라이언트가 서버의 SSL 인증서를 인증서 발행 기관을 통해 검증한다. 이를 통해 서버가 인증서에 명시된 서버인지, 그리고 클라이언트가 상호작용 중인 서버가 실제 해당 도메인의 소유자인지를 확인

  4. premaster secret: 클라이언트가 "premaster secret"라고 하는 무작위 바이트 문자열을 하나 더 전송한다. premaster secret는 공개 키로 암호화되어 있으며, 서버가 개인 키로만 해독할 수 있다. (클라이언트는 서버의 SSL 인증서를 통해 공개 키를 받는다.)

  5. 개인 키 사용: 서버가 premaster secret를 해독한다.

  6. 세션 키 생성: 클라이언트와 서버가 모두 Client Random, Server Random, premaster secret를 이용해 세션 키를 생성합니다. 모두 같은 결과가 나와야 한다.

  7. 클라이언트 준비 완료: 클라이언트가 세션 키로 암호화된 "Success" 메시지를 전송한다.

  8. 서버 준비 완료: 서버가 세션 키로 암호화된 "Success" 메시지를 전송한다.

  9. 안전한 대칭 암호화 성공: 핸드셰이크가 완료되고, 세션 키를 이용해 통신이 계속 진행된다.

Reference

https://nuritech.tistory.com/25 ( 인증서 발급 과정 )
https://www.cloudflare.com/ko-kr/learning/ssl/what-happens-in-a-tls-handshake/

profile
Developer

0개의 댓글