파일 URL 버킷 노출 문제 해결 및 CloudFront 정적 URL 적용

호기성세균·2025년 4월 3일
0

트러블슈팅

목록 보기
22/24
post-thumbnail

1. 발생 문제

1.1 URL 문제

사용자가 파일을 다운로드할 수 있는 URL이 다음과 같이 생성되고, 그대로 사용자에게 노출됨

https://test-bucket.s3.ap-northeast-2.amazonaws.com/2025-03-27/uuid-파일명.pdf

이 URL에는 S3 버킷명, 리전 정보, 파일 경로가 그대로 노출

  • S3 버킷 이름은 글로벌 유일 식별자이기 때문에 한 번 노출되면 해당 리소스를 직접적으로 겨냥한 공격 가능해짐 → DDos 대상이 됨
  • 많은 기업들이 S3 버킷을 공개로 설정한 채, URL을 직접 외부에 노출했다가
    파일/개인정보가 유출된 사건이 다수 있었음. 대부분이 버킷명을 통해 공격자가 버킷 스캐닝을 시도했고,
    권한 설정이 미흡했던 점을 통해 내부 문서까지 다운로드
  • 향후 S3 버킷 변경 시 모든 URL 변경 필요
  • URL에 s3.amazonaws.com 이라는 AWS 내부 주소가 박혀 있으면, 사용자나 클라이언트가 "외부 클라우드에 던져진 파일인가?" 하는 불안감을 가짐 → 회사 브랜드의 신뢰도에도 악영향

1.2 버킷 정책 문제

기존 버킷 정책은 다음과 같음

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Statement1",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::test-bucket/*"
    }
  ]
}
  • 이 정책의 의미는 "누구나, 어떤 인증 없이도, 이 S3 버킷 안의 모든 파일에 대해,
    모든 S3 작업을 할 수 있도록 허용한다
    "는 뜻. → 공공재 버킷이 아닌 이상 말도 안되는 설정
  • 파일 다운로드, 파일 업로드, 기존 파일 삭제, 파일 목록 조회, 봇/크롤러에 의한 자동 스캔 모두 허용

2. 해결 방안들 & 장단점 비교

방식설명장점단점
① S3 Pre-signed URL서버에서 임시 URL 발급 (10분~1시간 등)보안 우수/ 만료 가능/ 사용자 제어 용이속도 느림/ CDN 없음/ 복잡한 구현
② CloudFront Signed URLCloudFront에서 서명 기반 접근 제어고속 + 보안/ 만료 + 경로 제어 가능구현 복잡/ 키 관리 필요
③ CloudFront 정적 URL (공개 접근)CloudFront + OAC + 커스텀 도메인빠름/ CDN 활용/ URL 고정/ 퍼블릭 URL접근 제어는 별도로 없음 (공개 URL로 사용 시)

3. CloudFront 정적 URL 방식을 선택한 이유

요구사항:

  • 파일은 항상 접근 가능해야 하며 제한시간 없이 URL을 제공해야 함
  • ❗️기존 코드를 최대한 적게 건드려야 함❗️(클라이언트 측에 수정사항이 나오면 안됨)
  • 사용자 증가에 따라 S3교체 등 확장성 있게 구축해야함
  • 빠르게 파일에 접근할 수 있어야함
  • 사용자에 따라 접근 제어 필요 없음

문제점 :

  • Pre-signed → 클라이언트 측에 수정사항이 나오면 안됨./퍼블릭 콘텐츠이어야 함
  • CloudFront Signed URL → 너무 복잡하고 관리 포인트 많음. 기존 코드를 최대한 유지하는게 목표
  • CloudFront 공개 URL이 가장 단순하고 빠르며, 브랜딩 + 유지보수 + 퍼포먼스 면에서 최적

4. 적용 과정 상세 정리

1. CloudFront 배포 생성

  • Origin
    • CloudFront가 요청을 받아서 어디로 전달할지를 지정하는 대상
    • 이 경우 S3 버킷 URL을 넣어줍니다.
    • 클라이언트가 https://media.test.com/abc.jpg 요청
      → CloudFront가 내부적으로 Origin에 등록한 S3 버킷으로 요청 전달
  • Origin path
    • CloudFront가 오리진 요청 시, 자동으로 붙여줄 경로 prefix(강제)
    • 예를 들어 /static이라고 적으면:
      • 클라이언트 요청: https://media.test.com/images/logo.png
      • 내부 요청: https://test-bucket.s3.ap-northeast-2.amazonaws.com/static/images/logo.png
    • 버킷 안에 특정 폴더(/cdn-files/, /prod-assets/ 등)만 CloudFront로 연결하고 싶을 때 사용
  • 이름
    • 이건 내부에서 CloudFront 콘솔에 표시되는 오리진 식별자 이름
    • 실제 작동에 영향 없음/ 보통 도메인 그대로 넣거나, 의미 있는 키워드로 바꿈

  • Origin Access Control (OAC) 생성 및 연결
    • 원본 액세스 제어 설정(Origin Access Control)을 사용하면,CloudFront가 S3에 안전하게 접근하도록 제한할 수 있고, 퍼블릭 액세스를 완전히 차단하면서도 안정적인 파일 서비스가 가능하다.”
    • CloudFront가 S3에 요청할 때 서명된 요청(Signature v4) 를 보냄 → S3는 이 요청을 보고 CloudFront에서 왔는지, 어떤 배포에서 왔는지 검증함 → 버킷 정책에서 Principal: Service cloudfront.amazonaws.com + Condition: SourceArn 을 통해 오직 해당 배포만 허용 가능
  • Origin Shield
    • CloudFront 캐시 계층 위에 있는, "중앙 집중식 캐싱 허브" 역할의 추가 계층. CloudFront는 전 세계 여러 Edge Location에서 요청을 처리하고 캐싱하는데, 각 Edge가 바로 오리진(S3, EC2, API 등) 으로 요청을 보내면 중복 요청이 많아짐.
      → Origin Shield를 켜면, 모든 Edge Location이 오리진에 접근하기 전에 하나의 중앙 캐시 노드(Origin Shield Region) 를 거치게 됨.
    • Origin Shield OFF
      [Edge - 서울] ────→ S3
      [Edge - 도쿄] ────→ S3
      [Edge - 프랑크푸르트] ──→ S3
      
      요청이 각 Edge → S3로 분산됨. 동일 파일에 대한 중복 요청이 S3에 몰릴 수 있음
    • Origin Shield ON
      [Edge - 도쿄] ────→ Origin Shield (서울) ─→ S3
      [Edge - 부산] ────→ Origin Shield (서울) ─→ S3
      [Edge - 미국] ────→ Origin Shield (서울) ─→ S3
      
      모든 요청이 Origin Shield(서울)로 집중 → 오리진(S3) 요청 수 최소화
    • 오리진의 부하 분산/ 파일 업데이트가 자주 없는경우(캐시 효율 극대화)/ 글로벌 사용자가 많고 오리진이 민감하고 무거운 서비스일 때 유용함. 하지만 추가 금액이 발생하니 서비스의 특성을 고려해 도입하는 것이 좋음.

  • 대체 도메인 이름(CNAME) 추가
    • CloudFront의 기본 배포 도메인은 이렇게 생김 : https://d1234abcd.cloudfront.net/my-image.png
      근데 이건 1. 사용자 입장에서 직관적이지 않고 2. 회사 브랜드도 안 보이고 3. 도메인 관리/보안 통제도 어렵고 4. 외부 노출 시 “AWS 썼구나” 바로 드러남
    • 그래서 회사 고유의 도메인 또는 서브도메인을 붙이는 게 바로 Alternate Domain Name (CNAME) 설정
    • 단, 대체 도메인으로 등록하려고 하는 도메인에 대한 SSL 인증서 필수임
      → 여기서 주의해야할 점은 us-east-1 리전에서 해당 도메인용 SSL 발급해야함

CloudFront에서 사용자 도메인(대체 도메인, CNAME)을 쓰려면, 해당 도메인에 대한 SSL 인증서를 반드시 us-east-1에서 발급받아야 한다.

CloudFront의 글로벌 특성과 ACM 리전 제약 때문

  • CloudFront는 "글로벌 서비스"
  • CloudFront는 AWS 리전에 종속되지 않음 (예: 서울 리전 없음)
  • 전 세계 엣지 로케이션에서 작동함

ACM은 "리전 기반 서비스"

  • AWS Certificate Manager(ACM)는 리전별 리소스
    즉, ap-northeast-2(서울)에서 발급한 인증서는 서울에서만 사용됨
  • CloudFront는 자체적으로 인증서를 복제/전파하지 않음. 오직 us-east-1 리전에 있는 인증서만 CloudFront와 연결 가능
    이건 CloudFront의 글로벌 배포 구조ACM이 리전마다 독립적으로 동작하는 구조가 서로 충돌하지 않게 하기 위한 아키텍처적 제한.

2. DNS 설정 (Route 53 기준)

  • AWS 콘솔 → Route 53 → 호스팅 영역test.com 도메인 클릭
  • 레코드 등록
    • 레코드 이름 : CloudFront에서 대체 도메인으로 등록한 도메인
    • 레코드 유형 : CNAME
    • 값 (Value) : CloudFront 배포 도메인 이름(ex. test.cloudfront.net)

3. S3 보안 설정

  • 버킷 정책에서 CloudFront 외 직접 접근 차단
  • 퍼블릭 액세스 차단 설정 (Block Public Access)
    • S3 보안의 1차 관문. 버킷 레벨에서 퍼블릭 권한을 강제로 차단하는 기능. 이 설정을 켜두면 실수로 버킷 정책에 "Principal": "*" 넣어도 외부에서는 접근 불가
  • S3 → 버킷 → 파일 업로드 버킷 선택 → 권한 → 버킷 정책 → 편집
    • 버킷 단위로 권한을 설정하는 JSON 기반 정책. 어떤 주체(Principal)가 어떤리소스에 대해 어떤행위(Action)를 할 수 있는지를 정의함.
{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::test-bucket/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/TESTDISTRIBUTIONID"
                }
            }
        }
    ]
}

4. 애플리케이션 변경

  • 업로드 후 반환되는 URL: https://media.test.com/{object-key}
  • DB 저장 시 fileUrl → CloudFront 기반 URL 저장

5. 이 문제를 해결함으로써 얻은 효과

변경 항목

Client
  ↓
CloudFront (media.test.com)
  ↓
S3 (비공개, CloudFront만 접근 가능)
항목개선 전개선 후
S3 퍼블릭 접근열려 있었음 (완전 공개)완전 차단 (Block all public access)
URLs3.amazonaws.com/버킷명/파일대체도메인/파일
버킷 정책누구나 접근CloudFront만 접근 가능
보호 계층없음CloudFront 경유 (OAC + 도메인 + HTTPS)
로그 추적어려움CloudFront 로그 추적 가능
확장성제한적캐시, 압축, 보안, 확장 구조 사용 가능

이 문제를 해결함으로써 얻은 효과

효과설명
보안 향상S3 버킷명, 리전 정보 완전 비공개. 구조 노출 없음
브랜딩 강화media.test.com 도메인 사용 → 신뢰감 증가
성능 향상전 세계 CloudFront 엣지에서 캐싱 → 빠른 다운로드
유지보수 용이S3 오리진 변경해도 URL은 그대로 → 서비스 URL 안정성 확보

파일 URL이 S3 버킷 주소로 노출되어 보안과 유지보수에 문제가 있었지만,
CloudFront + 커스텀 도메인을 사용함으로써 안정적이고 확장성 높은 파일 전달 구조를 확보.

profile
공부...열심히...

0개의 댓글