- Published on
CloudFront 403 The request could not be satisfied 해결
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서론
CloudFront를 붙인 뒤 브라우저에 403 ERROR와 함께 **The request could not be satisfied**가 뜨면, 대부분 “권한 문제”라고 단정하기 쉽습니다. 하지만 CloudFront의 403은 오리진(S3/ALB/EC2) 권한, WAF/Shield 차단, 서명된 URL/쿠키, 캐시된 에러, 헤더/쿼리스트링 전달 정책 등 다양한 레이어에서 발생합니다. 게다가 CloudFront는 에러를 캐시할 수 있어, 한 번 잘못된 설정이 배포되면 고친 뒤에도 계속 403이 보이기도 합니다.
이 글은 “어디서 403이 만들어지는지”를 먼저 규명하고, 원인별로 가장 자주 놓치는 설정을 짧은 루프(관측 → 가설 → 검증)로 해결하는 방법을 정리합니다.
1) 먼저 확인: 403을 만든 주체가 CloudFront인가, 오리진인가
같은 403이라도 CloudFront가 직접 거절한 것인지, 오리진이 403을 반환했는지부터 갈라야 합니다. 가장 빠른 방법은 응답 헤더를 보는 것입니다.
1-1. curl로 헤더 확인
curl -I https://d111111abcdef8.cloudfront.net/path
아래 신호를 확인하세요.
Via: 1.1 ... cloudfront/X-Cache:가 보이면 CloudFront를 거친 응답X-Cache: Error from cloudfront면 CloudFront 레이어에서 에러가 생성/캐시되었을 가능성이 큼X-Amz-Cf-Id가 있으면 CloudFront 응답임Server: AmazonS3가 보이면서 403이면 S3가 403을 준 것일 가능성이 큼
1-2. CloudFront 표준 로그/실시간 로그에서 힌트 찾기
표준 로그를 켜면 x-edge-result-type, x-edge-detailed-result-type로 원인을 좁힐 수 있습니다.
AccessDenied,Forbidden류: 오리진 권한 또는 WAFInvalidRequest류: 헤더/쿼리 전달 정책, 서명, 프로토콜/호스트 문제
2) 가장 흔한 원인: S3 오리진 권한(OAC/OAI) 불일치
S3를 오리진으로 쓰는 경우, CloudFront 403의 1순위는 버킷 정책이 CloudFront 접근을 허용하지 않는 것입니다. 특히 요즘은 OAI보다 **OAC(Origin Access Control)**을 권장하는데, OAC로 전환하면서 버킷 정책을 OAI 형태로 남겨두면 403이 납니다.
2-1. OAC 사용 시 S3 버킷 정책 예시
아래는 CloudFront 배포(Distribution)에서만 S3를 읽을 수 있게 하는 대표 패턴입니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipalReadOnly",
"Effect": "Allow",
"Principal": { "Service": "cloudfront.amazonaws.com" },
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::YOUR_ACCOUNT_ID:distribution/YOUR_DISTRIBUTION_ID"
}
}
}
]
}
체크 포인트:
Principal이cloudfront.amazonaws.com인지AWS:SourceArn이 정확한 Distribution ARN인지Resource가bucket/*까지 포함되는지
2-2. S3 퍼블릭 차단(Public Access Block)과의 관계
OAC/OAI를 쓰는 구성에서는 S3 퍼블릭 차단을 켜도 됩니다. 중요한 건 버킷이 퍼블릭이냐 아니냐가 아니라, CloudFront 서비스 프린시펄이 접근 가능한지입니다.
2-3. “특정 경로만 403”이면 객체 키/대소문자/인덱스 문서 확인
S3는 키가 대소문자를 구분합니다.
/index.html은 있는데/Index.html은 없음- SPA 라우팅에서
/app/settings같은 경로가 S3에 객체로 없는데, CloudFront에서 403/404로 보일 수 있음
정적 사이트라면 Custom Error Response로 403/404를 /index.html로 매핑하는 구성이 필요할 수 있습니다.
3) ALB/NLB/EC2 오리진: 보안그룹·Host 헤더·인증 레이어 점검
ALB를 오리진으로 쓰면 403은 종종 **애플리케이션 레벨(예: Nginx, 인증 미들웨어)**에서 발생합니다.
3-1. CloudFront → ALB 네트워크 경로
- ALB 보안그룹 인바운드가 CloudFront IP를 허용하지 않아서 403이 나는 경우도 있지만, 보통은 5xx/timeout이 더 흔합니다.
- 403이라면 오히려 애플리케이션이 Host 기반 라우팅 또는 인증/인가에서 거절했을 가능성이 큽니다.
3-2. Host 헤더 전달(Origin Request Policy)
ALB가 Host 헤더로 가상호스트를 구분한다면, CloudFront가 오리진에 어떤 Host를 보내는지 중요합니다.
- 오리진이 기대하는 Host:
api.example.com - CloudFront가 보내는 Host:
d111111abcdef8.cloudfront.net
이 불일치로 앱이 403을 반환하기도 합니다.
해결 방향:
- CloudFront Origin Request Policy에서 필요한 헤더(특히
Host,Authorization)가 전달되는지 확인 - 또는 ALB/앱이 CloudFront 도메인을 허용하도록 설정
4) WAF 차단: CloudFront 403의 “조용한” 주범
AWS WAF를 CloudFront에 붙였거나(또는 ALB에 붙였거나), 매니지드 룰을 켜둔 상태에서 특정 요청만 403이 나면 WAF를 의심해야 합니다.
4-1. WAF 로그로 Block 규칙 확인
- WAF Logging을 S3/Kinesis Firehose로 활성화
terminatingRuleId,action=BLOCK확인
자주 걸리는 패턴:
AWSManagedRulesCommonRuleSet에서 SQLi/XSS 오탐SizeRestrictions로 큰 헤더/쿠키 차단- Bot Control/Rate Based Rule로 IP 차단
4-2. CloudFront 기본 에러 화면이라도 WAF가 원인일 수 있음
WAF가 CloudFront 레이어에서 차단하면, 사용자 입장에서는 CloudFront 403 화면만 보입니다. 이때는 CloudFront 로그보다 WAF 로그가 결정적입니다.
5) Signed URL/Cookie, Geo restriction, Viewer protocol 정책
5-1. Signed URL/쿠키 설정 실수
- 프라이빗 콘텐츠 배포에서 서명이 없으면 403
- 키 페어/정책 만료시간 오류
검증:
- 동일 리소스를 서명된 URL로 요청했을 때만 200이면 서명 정책 문제
5-2. Geo Restriction(지역 제한)
국가 제한을 걸어두면 해당 지역에서 403이 납니다.
- 특정 국가/리전에서만 재현된다면 Geo restriction 또는 WAF의 Geo match를 확인
5-3. Viewer Protocol Policy
Redirect HTTP to HTTPS 또는 HTTPS only 정책 자체는 보통 403이 아니라 리다이렉트/접속 실패로 드러납니다. 하지만 앱/오리진이 X-Forwarded-Proto 기반으로 접근 제어를 한다면, 프로토콜 관련 헤더 전달 정책과 함께 점검해야 합니다.
6) “고쳤는데도 계속 403”이면: 캐시된 에러 무효화
CloudFront는 4xx/5xx도 TTL에 따라 캐시할 수 있습니다. 설정을 수정했는데도 403이 계속 보이면 에러 캐시를 의심하세요.
6-1. Invalidations로 즉시 무효화
aws cloudfront create-invalidation \
--distribution-id YOUR_DISTRIBUTION_ID \
--paths "/*"
6-2. Custom Error Responses의 Error Caching Minimum TTL 확인
CloudFront 콘솔에서 배포의 Custom Error Responses에 Error Caching Minimum TTL이 과도하게 길면, 원인 수정 후에도 오래 지속됩니다.
7) 빠른 진단 체크리스트(현장용)
아래 순서로 보면 대부분 10~20분 내에 범위를 줄일 수 있습니다.
curl -I로X-Cache/Server확인 → CloudFront 생성 에러인지, 오리진 403인지- CloudFront 로그의
x-edge-detailed-result-type확인 - S3 오리진이면 OAC/OAI와 버킷 정책부터 검증
- ALB 오리진이면 Host/Authorization 헤더 전달 정책과 앱 접근제어 확인
- WAF가 있으면 WAF 로그에서 BLOCK 규칙 확인
- 수정 후에도 재현되면 invalidation + error caching TTL 확인
8) 재현/검증에 유용한 명령 모음
8-1. 특정 헤더를 넣어 오리진 동작 확인
curl -i https://d111111abcdef8.cloudfront.net/api \
-H 'Host: api.example.com' \
-H 'Authorization: Bearer YOUR_TOKEN'
헤더를 넣었을 때만 200이면, CloudFront의 Origin Request Policy에서 해당 헤더가 오리진으로 전달되지 않는 구성일 가능성이 큽니다.
8-2. 캐시 우회(디버그용 쿼리 스트링)
curl -I "https://d111111abcdef8.cloudfront.net/path?cb=$(date +%s)"
쿼리스트링을 캐시 키에 포함하도록 설정되어 있다면, 캐시된 403과 분리해 테스트할 수 있습니다.
9) 연관 이슈: 403이 로드밸런서/쿠버네티스에서 시작되는 경우
EKS 환경에서 CloudFront → ALB Ingress로 연결된 구조라면, 403의 기원이 CloudFront가 아니라 Ingress/ALB Controller 설정인 경우도 있습니다. 특히 인증 헤더 전달, 경로 매칭, 리스너 규칙, 보안정책에서 403이 발생할 수 있습니다. 이 경우 아래 글이 진단에 도움이 됩니다.
또한 OIDC/AssumeRole 기반으로 배포 자동화 중 권한이 꼬여 CloudFront/S3 정책 반영이 누락되는 케이스도 있으니, CI/CD에서 IAM/OIDC를 쓰고 있다면 다음 글도 함께 점검해보세요.
결론
CloudFront의 403: The request could not be satisfied는 “CloudFront가 문제”라기보다 CloudFront 앞/뒤의 정책과 전달 규칙이 맞물리면서 생기는 경우가 대부분입니다. 가장 효율적인 접근은 (1) 에러 생성 주체를 가르고, (2) S3라면 OAC/OAI-버킷정책, ALB라면 Host/Authorization 전달과 앱 접근제어, (3) WAF/Geo/서명 정책을 로그로 확인한 뒤, (4) 에러 캐시 무효화까지 마무리하는 것입니다.
이 루틴대로 점검하면, 막막한 403을 “어떤 레이어의 어떤 정책이 거절했는지”까지 구체적으로 좁혀 재발 방지 설정으로 연결할 수 있습니다.