Chapter 22

CloudFront + WAF: CDN 배포 + 웹 방화벽

학습 목표

  • CloudFront(CDN)의 역할과 동작 원리를 이해한다
  • S3 정적 웹사이트를 CloudFront를 통해 배포한다
  • OAC(Origin Access Control)로 S3 직접 접근을 차단한다
  • WAF(Web Application Firewall)로 웹 공격을 차단한다
  • 관리형 규칙과 Rate-based 규칙을 적용한다

왜 CloudFront + WAF가 필요한가?

Chapter 01~21에서 ShopEasy 애플리케이션을 배포하고 다양한 보안 서비스를 적용했습니다. 하지만 아직 두 가지 중요한 문제가 남아 있습니다: 프론트엔드의 성능(속도)웹 공격 방어입니다.

현재 S3 정적 웹 호스팅으로 직접 서비스하고 있어 CDN 캐싱이 없고, SQL 인젝션이나 XSS 같은 웹 공격에 대한 방어도 전혀 없습니다.

비유로 이해하기: 전국 체인 편의점 (CloudFront)

CloudFront는 전국 체인 편의점과 같습니다.

원래는 서울 본점(S3 버킷)에서만 물건을 살 수 있었습니다. 부산이나 대구 고객은 서울까지 가야 했죠. 시간도 오래 걸리고, 본점에 손님이 몰려 혼잡합니다.

이제 전국에 편의점(엣지 로케이션)을 열면, 부산 고객은 부산 편의점에서, 대구 고객은 대구 편의점에서 빠르게 물건을 살 수 있습니다. 본점 부담도 줄고, 고객 응답 시간도 대폭 단축됩니다!

CloudFront는 전 세계 400개 이상의 엣지 로케이션에서 콘텐츠를 캐싱하여 사용자에게 가장 가까운 위치에서 빠르게 응답합니다.

비유로 이해하기: 쇼핑몰 보안 검색대 (WAF)

WAF는 쇼핑몰 입구의 보안 검색대와 같습니다.

일반 고객은 자유롭게 통과하지만, 위험 물품(SQL 인젝션, XSS 스크립트)을 소지한 사람은 차단합니다.

또한 비정상적으로 빠르게 들어오는 사람(DDoS 공격, 무차별 접속)도 Rate Limit 규칙으로 차단합니다.

보안 검색대가 없으면 누구든 무엇이든 가지고 들어올 수 있어 위험합니다. WAF가 이 역할을 합니다.

현재 문제점
  • 성능 문제: S3 정적 웹 호스팅 직접 접속 - CDN 없이 느림, 캐싱 없음
  • 보안 문제: 웹 공격(SQL 인젝션, XSS, DDoS)에 대한 방어가 전혀 없음
  • 접근 제어 부재: S3 버킷에 누구나 직접 접근 가능
ShopEasy 시나리오

"S3에서 직접 서비스하던 프론트엔드를 CloudFront CDN을 통해 배포하고, WAF로 웹 공격을 차단합시다. 고객에게는 더 빠른 응답을, 서비스에는 더 강력한 보안을 제공합니다."

현재 상태 vs 목표 상태

현재 아키텍처 (S3 직접 접근)

현재: S3 정적 웹 호스팅 직접 접근
사용자 브라우저
전 세계 어디서든
S3 버킷
shopeasy-frontend-ACCOUNT_ID
정적 웹 호스팅 (직접 접근)
CDN 없음, 보안 없음
항목현재 상태문제점
접근 방식S3 웹 호스팅 URL 직접 접근CDN 캐싱 없음, 느림
보안방어 없음웹 공격에 무방비
S3 접근퍼블릭 접근 허용누구나 S3에 직접 접근 가능

목표 아키텍처 (CloudFront + WAF)

목표: CloudFront CDN + WAF 보호
사용자 브라우저
전 세계 어디서든
WAF
웹 공격 차단
SQL 인젝션, XSS
Rate Limiting
CloudFront CDN
엣지 로케이션
캐싱 + HTTPS
글로벌 배포
S3 버킷 (원본)
OAC로 접근 제한
CloudFront만 허용
항목목표 상태효과
접근 방식CloudFront 도메인으로 접근글로벌 CDN 캐싱, 빠른 응답
보안WAF가 웹 공격 차단SQL 인젝션, XSS, DDoS 방어
S3 접근OAC로 CloudFront만 허용S3 직접 접근 차단
S3 직접 접근 vs CloudFront 접근 차이

S3 정적 웹 호스팅 직접 접근:

  • URL: http://shopeasy-frontend-ACCOUNT_ID.s3-website.ap-northeast-2.amazonaws.com
  • HTTP만 지원 (HTTPS 불가)
  • 캐싱 없음 - 매 요청마다 S3에서 파일을 가져옴
  • 웹 공격 방어 없음

CloudFront 접근:

  • URL: https://d1234abcdef.cloudfront.net
  • HTTPS 기본 지원
  • 전 세계 엣지 로케이션에서 캐싱 - 빠른 응답
  • WAF 연결로 웹 공격 차단 가능

실습: CloudFront + WAF 구성

실습: ShopEasy 프론트엔드에 CloudFront CDN + WAF 적용하기
비용 안내

CloudFront: 프리 티어에서 매월 1TB 데이터 전송, 10,000,000건 HTTP/HTTPS 요청 무료 (12개월). 실습 규모에서는 비용이 거의 발생하지 않습니다.

WAF: Web ACL 월 $5, 규칙당 월 ~$1, 요청 100만 건당 $0.60. 관리형 규칙(Managed Rules)은 규칙 그룹당 추가 비용이 발생합니다. 실습 후 삭제하면 비용을 최소화할 수 있습니다.

  1. Step 1: CloudFront 배포 생성

    S3 프론트엔드 버킷을 원본(Origin)으로 하는 CloudFront 배포를 생성합니다. OAC(Origin Access Control)를 사용하여 S3에 CloudFront를 통해서만 접근하도록 설정합니다.

    CloudFront 배포 생성

    • AWS 콘솔 → CloudFront 검색 → CloudFront 서비스 선택
    • "배포 생성(Create distribution)" 클릭

    설정 값

    항목
    원본 도메인(Origin domain)shopeasy-frontend-ACCOUNT_ID.s3.ap-northeast-2.amazonaws.com
    원본 접근(Origin access)OAC (Origin Access Control) - "Origin access control settings (recommended)" 선택 후 새로 생성
    뷰어 프로토콜 정책(Viewer protocol policy)HTTP and HTTPS
    캐시 정책(Cache policy)CachingOptimized (권장)
    기본 루트 객체(Default root object)index.html
    가격 클래스(Price class)북미, 유럽, 아시아, 중동 및 아프리카에서 사용 (또는 모든 엣지 로케이션)
    설명(Description)ShopEasy Frontend CDN
    OAC(Origin Access Control)란?

    OAC를 사용하면 S3 버킷에 직접 접근하지 않고, CloudFront를 통해서만 접근하도록 제한할 수 있습니다. S3 정적 웹 호스팅의 퍼블릭 접근을 제거하고 CloudFront만 허용하는 것이 보안 모범 사례입니다.

    OAC는 이전의 OAI(Origin Access Identity)를 대체하는 새로운 방식으로, IAM 서비스 프린시펄 기반으로 더 안전합니다.

    배포 생성 후 대기 시간

    CloudFront 배포가 생성된 후 상태가 "배포됨(Deployed)"이 될 때까지 약 5~15분이 소요됩니다. 이 시간 동안 전 세계 엣지 로케이션에 설정이 전파됩니다. 상태가 "배포됨"이 될 때까지 기다린 후 다음 단계로 진행하세요.

    배포 생성 후 CloudFront 도메인 (예: d1234abcdef.cloudfront.net)을 확인합니다. 이 도메인으로 접속하여 프론트엔드가 정상 로딩되는지 확인합니다.

    CloudFront 콘솔에서 "배포 생성"을 클릭한 후:

    1. 원본 도메인 입력창을 클릭하면 S3 버킷 목록이 나타납니다. shopeasy-frontend-ACCOUNT_ID 버킷을 선택합니다.
    2. 원본 접근에서 "Origin access control settings (recommended)"를 선택합니다.
    3. "Create new OAC" 버튼을 클릭하고, 기본값으로 생성합니다. (이름: 자동 생성)
    4. 나머지 설정은 위 표의 값으로 입력합니다.
    5. 페이지 하단의 "배포 생성(Create distribution)" 버튼을 클릭합니다.
    6. 배포 생성 후 "S3 버킷 정책을 업데이트해야 합니다"라는 안내 배너가 나타납니다. "정책 복사" 버튼을 클릭하여 정책을 복사해 두세요. (Step 2에서 사용)
  1. Step 2: S3 버킷 정책 업데이트 (OAC용)

    S3 프론트엔드 버킷의 기존 퍼블릭 접근 정책을 CloudFront OAC 전용 정책으로 교체합니다. 이렇게 하면 S3 버킷에 직접 접근할 수 없고, CloudFront를 통해서만 접근할 수 있습니다.

    새 버킷 정책 (OAC용)

    json
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "AllowCloudFrontServicePrincipal",
          "Effect": "Allow",
          "Principal": {
            "Service": "cloudfront.amazonaws.com"
          },
          "Action": "s3:GetObject",
          "Resource": "arn:aws:s3:::shopeasy-frontend-ACCOUNT_ID/*",
          "Condition": {
            "StringEquals": {
              "AWS:SourceArn": "arn:aws:cloudfront::ACCOUNT_ID:distribution/DISTRIBUTION_ID"
            }
          }
        }
      ]
    }
    "정책 복사" 기능 활용

    CloudFront 배포 생성 시 "S3 버킷 정책을 업데이트하시겠습니까?"라는 안내가 나옵니다. "정책 복사" 버튼을 클릭하면 위 정책이 자동으로 생성되어 클립보드에 복사됩니다. ACCOUNT_ID와 DISTRIBUTION_ID가 자동으로 채워져 있으므로 직접 수정할 필요가 없습니다!

    S3 버킷 정책 적용 방법

    • S3 콘솔 → shopeasy-frontend-ACCOUNT_ID 버킷 선택
    • 권한(Permissions) 탭 클릭
    • 버킷 정책(Bucket policy) 섹션에서 "편집(Edit)" 클릭
    • 기존 정책을 삭제하고 새 OAC 정책을 붙여넣기
    • "변경 사항 저장(Save changes)" 클릭

    확인 사항

    • CloudFront 도메인 (https://d1234abcdef.cloudfront.net)으로 접속 → 정상 로딩
    • S3 웹 호스팅 URL로 직접 접속 → 접근 차단 (403 Forbidden)
    S3 정적 웹 호스팅 비활성화 (선택 사항)

    CloudFront OAC를 사용하면 S3의 REST API 엔드포인트를 통해 접근하므로, S3 정적 웹 호스팅 기능을 비활성화해도 됩니다. 다만 이전 챕터에서 S3 웹 호스팅 URL을 사용했다면, 비활성화 전에 모든 참조를 CloudFront URL로 변경해야 합니다.

    CloudFront 배포 상세 페이지 상단에 "S3 버킷 정책을 업데이트해야 합니다"라는 배너가 표시됩니다.

    1. "정책 복사" 버튼을 클릭합니다.
    2. S3 콘솔로 이동합니다.
    3. shopeasy-frontend-ACCOUNT_ID 버킷을 선택합니다.
    4. 권한(Permissions) 탭 → 버킷 정책(Bucket policy) → 편집(Edit)
    5. 기존 정책을 모두 선택(Ctrl+A)하고 삭제한 후, 복사한 정책을 붙여넣기(Ctrl+V)합니다.
    6. "변경 사항 저장"을 클릭합니다.
  1. Step 3: WAF Web ACL 생성 및 CloudFront에 연결

    WAF(Web Application Firewall)를 생성하여 CloudFront 배포에 연결합니다. 관리형 규칙으로 일반적인 웹 공격을 차단하고, Rate-based 규칙으로 DDoS 공격을 방어합니다.

    리전 주의! (매우 중요)

    WAF는 CloudFront에 연결할 때 반드시 글로벌(us-east-1) 리전에서 생성해야 합니다. WAF 콘솔에서 리소스 타입을 "Amazon CloudFront distributions"로 선택하면 자동으로 글로벌 리전이 적용됩니다.

    ap-northeast-2(서울)에서 생성한 WAF는 CloudFront에 연결할 수 없습니다!

    WAF Web ACL 생성

    • AWS 콘솔 → WAF & Shield 검색 → WAF 서비스 선택
    • 왼쪽 메뉴에서 "Web ACLs" 클릭
    • 리전을 "Global (CloudFront)"으로 선택
    • "Create web ACL" 클릭

    Web ACL 기본 설정

    항목
    리소스 타입(Resource type)Amazon CloudFront distributions
    이름(Name)ShopEasy-WAF
    설명(Description)ShopEasy 프론트엔드 웹 방화벽
    연결 리소스(Associated AWS resources)ShopEasy CloudFront 배포 선택 (Add AWS resources)

    규칙 추가 (Rules)

    규칙유형설명
    AWSManagedRulesCommonRuleSet관리형 (Managed rule groups → AWS managed rule groups)일반적인 웹 공격 차단 (SQL 인젝션, XSS 등 OWASP Top 10)
    AWSManagedRulesAmazonIpReputationList관리형악성 IP 차단 (봇, 스캐너 등)
    Rate-based rule사용자 지정 (Add my own rules → Rule builder)동일 IP에서 5분간 1,000회 초과 요청 시 차단

    기본 작업 (Default action)

    Allow - 규칙에 매치되지 않는 트래픽은 허용합니다.

    관리형 규칙(Managed Rules)이란?

    WAF의 관리형 규칙(Managed Rules)은 AWS가 자동으로 업데이트하는 규칙 세트입니다. OWASP Top 10 웹 취약점을 포함하여 최신 공격 패턴에 대응합니다.

    • AWSManagedRulesCommonRuleSet: 크로스 사이트 스크립팅(XSS), SQL 인젝션 등 일반적인 공격 차단
    • AWSManagedRulesAmazonIpReputationList: AWS가 수집한 악성 IP 목록 기반 차단

    직접 규칙을 작성하지 않아도 AWS가 관리하므로 편리하고 안전합니다.

    Web ACL 생성 단계별 안내:

    1. Step 1 - Describe web ACL: 이름, 설명 입력 후 CloudFront 배포 연결
    2. Step 2 - Add rules:
      • "Add rules" → "Add managed rule groups" 클릭
      • "AWS managed rule groups" 펼치기
      • "Core rule set" 토글 ON (AWSManagedRulesCommonRuleSet)
      • "Amazon IP reputation list" 토글 ON
      • "Add rules" 클릭하여 확인
      • 다시 "Add rules" → "Add my own rules and rule groups" 클릭
      • "Rule builder" 선택, 이름 입력 (예: RateLimit-1000)
      • Type: "Rate-based rule" 선택
      • Rate limit: 1000, Action: Block 설정
      • "Add rule" 클릭
    3. Step 3 - Set rule priority: 기본 순서 유지
    4. Step 4 - Configure metrics: 기본값 유지 (CloudWatch 메트릭 활성화)
    5. Step 5 - Review and create: 설정 확인 후 "Create web ACL" 클릭
  1. Step 4: WAF 동작 테스트

    WAF가 정상적으로 동작하는지 확인합니다. 정상 요청은 허용되고, 악성 요청은 차단되는지 테스트합니다.

    1. 정상 접속 확인

    CloudFront 도메인으로 접속하여 프론트엔드가 정상 로딩되는지 확인합니다.

    text
    https://CLOUDFRONT_DOMAIN/

    → 정상적으로 ShopEasy 프론트엔드가 표시되어야 합니다. (200 OK)

    2. XSS 공격 패턴 테스트

    URL에 XSS 공격 패턴을 포함하여 WAF가 차단하는지 확인합니다.

    text
    https://CLOUDFRONT_DOMAIN/?q=

    403 Forbidden 응답이 반환되어야 합니다. WAF가 XSS 공격을 차단한 것입니다!

    3. WAF 대시보드 확인

    • WAF 콘솔 → Web ACLs → ShopEasy-WAF 선택
    • Overview 탭에서 요청 수 확인:
      • AllowedRequests: 허용된 요청 수
      • BlockedRequests: 차단된 요청 수
    • 규칙별 매칭 현황 확인
    실무 팁: WAF 로그 및 추가 보호

    실무에서는 WAF 로그를 S3나 CloudWatch Logs로 전송하여 차단된 요청을 분석합니다. 또한 다음과 같은 추가 규칙을 적용하기도 합니다:

    • Bot Control: 악성 봇 트래픽 차단
    • Account Takeover Prevention: 계정 탈취 시도 감지
    • Geo-blocking: 특정 국가에서의 접근 차단
    • Custom rules: 비즈니스 로직에 맞는 사용자 정의 규칙

    브라우저에서 CloudFront 도메인으로 접속합니다:

    1. 정상 접속: https://d1234abcdef.cloudfront.net → ShopEasy 프론트엔드가 표시되면 성공
    2. XSS 테스트: 주소창에 https://d1234abcdef.cloudfront.net/?q=<script>alert('xss')</script> 입력 → 403 에러 페이지가 나오면 WAF가 정상 동작하는 것
    3. 대시보드: WAF 콘솔 → Web ACLs → ShopEasy-WAF → Overview 탭에서 AllowedRequests와 BlockedRequests 그래프를 확인합니다. 방금 테스트한 요청이 반영되는 데 몇 분이 걸릴 수 있습니다.

리소스 삭제 (실습 후)

비용 절감을 위한 리소스 삭제 순서

CloudFront와 WAF는 사용 중인 동안 비용이 발생합니다. 실습이 끝나면 다음 순서로 삭제합니다:

  1. WAF Web ACL 삭제: WAF 콘솔 → Web ACLs → ShopEasy-WAF 선택 → Associated AWS resources에서 CloudFront 연결 해제 → Web ACL 삭제
  2. CloudFront 배포 비활성화: CloudFront 콘솔 → 배포 선택 → "비활성화(Disable)" → 상태가 "비활성화됨(Disabled)"이 될 때까지 대기
  3. CloudFront 배포 삭제: 비활성화 완료 후 배포 삭제
  4. S3 버킷 정책 복원: 기존 퍼블릭 접근 정책으로 복원 (S3 직접 서비스가 필요한 경우)

삭제 순서가 중요합니다! WAF가 연결된 상태에서 CloudFront를 삭제할 수 없고, CloudFront가 활성화된 상태에서는 삭제할 수 없습니다.

확인 사항

  • CloudFront 배포가 생성되고 "배포됨(Deployed)" 상태이다
  • CloudFront 도메인(d1234.cloudfront.net)으로 프론트엔드에 접속할 수 있다
  • S3 버킷 정책이 OAC 전용으로 업데이트되었다
  • S3 직접 접속이 차단되고 CloudFront 도메인으로만 접속 가능하다
  • WAF Web ACL(ShopEasy-WAF)이 CloudFront에 연결되었다
  • 정상 요청은 허용되고 (200 OK), XSS 패턴은 차단된다 (403 Forbidden)
  • WAF 대시보드에서 AllowedRequests와 BlockedRequests를 확인할 수 있다
이번 챕터에서 달성한 것
  • CloudFront CDN을 통한 글로벌 콘텐츠 배포
  • OAC로 S3 직접 접근 차단 - 보안 강화
  • WAF 관리형 규칙으로 OWASP Top 10 웹 공격 차단
  • Rate-based 규칙으로 DDoS/무차별 공격 방어
  • 성능 + 보안을 동시에 달성!
다음 챕터 안내

다음 챕터(Chapter 23)는 마지막 챕터입니다. 지금까지 배포한 ShopEasy 인프라 전체를 모니터링하고, 실습에 사용한 모든 리소스를 정리(삭제)합니다. 리소스를 삭제하지 않으면 불필요한 비용이 계속 발생하므로 반드시 정리해야 합니다.