‘Hot‐Link & Bandwidth Abuse’ 문제를 막는 방법 - lets-go-trip/treaXure-backend GitHub Wiki
“만약 악의적인 사용자가 우리 서비스에 이미지를 올린 뒤, 해당 S3 URL을 외부 사이트에 퍼가서 마음대로 트래픽을 발생시키면 전송료가 폭증할 텐데, 이런 ‘핫링크 남용’ 문제를 어떻게 막아야 할까?”
-
Hot‑Link(핫링크): 외부 사이트가 우리 CDN/S3 경로를 직접
<img src>
로 호출해 트래픽을 소비하는 행위 -
위험
- 전송료 폭증: CloudFront·S3 데이터 전송 요금 증가
- 서비스 품질 저하: 캐시 히트율↓, 엣지 PoP 부하↑
- 콘텐츠 도용: 저작권·브랜드 이미지 훼손
징후 | 지표 | 확인 방법 |
---|---|---|
특정 IP·ASN 대량 요청 | CloudFront Requests, WAF Rate metric | CloudWatch / WAF 실시간 |
Referrer NULL·타 도메인 | CloudFront Access‑Log cs(Referer) | Athena 쿼리 |
회피형 User‑Agent (bot) | ua 필드 탐색 | Amazon Kinesis Firehose → S3 분석 |
전송요금 급등 | Cost Explorer CloudFront-DataTransfer-Out-Bytes | Cost Anomaly Detection 경보 |
계층 | 기법 | 특징 | 장·단점 | 권장 상황 |
---|---|---|---|---|
전송(Edge) | Signed URL / Cookie | 만료·IP범위 포함 서명 토큰 | 캐시 재활용률 관리 필요 | 로그인 사용자, 개인 콘텐츠 |
WAF Rate‑Based Rule | 분당 n회 이상 블록 | 공유IP 환경 오탐 가능 | DDoS·스크래핑 완화 | |
오리진(S3) | Origin Access Control(OAC) | S3를 Private 유지 | 설정 단순, 공개 차단 | 모든 환경(기본) |
애플리케이션 | Download Token DB 저장 | 세밀한 권한·통계 | 서버 라운드트립 필요 | 비공개 다운로드, 영수증 등 |
비용통제 | Budgets & Auto‑WAF Action | 한도 초과 시 자동 차단 | 초기 설정 필요 | 소규모 팀 비용 폭주 방지 |
-
키쌍 생성: RSA 2048 → CloudFront Key Group 업로드
-
백엔드(Spring)에서
CloudFrontUrlSigner
로 URL 서명- 정책 예:
ResourcePath:/user/*
,Expires:+120s
,IP:203.0.113.0/24
- 정책 예:
-
쿠키 방식:
CloudFront-Signature
,Key-Pair-Id
,Policy
3종 세트 → 브라우저 Set‑Cookie쿠키 이름 역할 주요 내용 CloudFront-Key-Pair-Id 어떤 공개 키로 검증할지 지정 • Key group 또는 Trusted key group 에 등록된 공개 키 ID. • CloudFront는 이 ID로 대응하는 공개 키를 찾아 서명을 검증합니다. CloudFront-Policy(또는 CloudFront-Expires) 요청 허용 조건을 담은 정책(Policy) 자체 • Base64-URL 인코딩된 JSON 문서. • 포함 정보 — Resource(허용 경로 패턴), DateLessThan(만료 시각, Unix epoch), IpAddress(선택) 등. • Custom Policy를 쓰면 CloudFront-Policy가, Canned Policy를 쓰면 대신 CloudFront-Expires(만료 타임스탬프)만 전달됩니다. CloudFront-Signature 정책 무결성 서명 • 위 Policy(또는 “경로+만료” 문자열)를 RSA-SHA1로 서명한 값.• 사이트 간 복사·변조를 막고, CloudFront가 정책이 진짜임을 입증합니다. 요약 흐름
- 백엔드가 정책 → SHA1 해시 → RSA 개인키로 서명 → 세 쿠키를 Set-Cookie 헤더로 반환.
- 브라우저가 CloudFront 도메인에 요청 → 세 쿠키 자동 전송.
-
CloudFront는
Key-Pair-Id
에 해당하는 공개 키로Signature
를 검증하고,Policy
조건(경로, IP, 만료)을 모두 만족하면 오리진(S3 등)에 요청을 프록시합니다.
-
캐시 고려:
- Signed URL: 객체별 서명값 달라 캐시 적중률↓
- Signed Cookie: 동일 객체 동일 쿠키로 캐시 히트율↑
-
TTL 전략: Public 이미지(썸네일) 10‑30 min, Private 파일 1‑5 min
IF request.header['referer'] NOT contains "app.example.com"
THEN block (403)
- Rate‑Based Rule: 2분당 2000 requests/IP 초과 시 1시간 차단
-
Header Tamper 방지: 추가로
User‑Agent
길이·정규식 필터
- AWS Budgets – ‘DataTransfer‑CF’ 5 USD 초과 시 SNS 주제 발행
- Lambda Budget Action → WAF Rule Priority 0 ‘Block‑All’ enable
- 복구 절차: 원인 분석 후 Rule disable → 캐시 무효화
- S3 버킷 Public Access Block 유지 & OAC 연결
- CloudFront 배포 Behaviour
/images/*
→ Cache Policy:Signed‑Cookie
- RSA Private Key 안전보관 (Parameter Store SecureString)
- 백엔드
/images/token
API 구현 – 403 on quota exceed - WAF WebACL 연동 & 테스트 (Referrer + Rate)
- Cost Anomaly Detection 활성화,
cloudfront
DIMENSION 추적 - 월간 트래픽 리포트 Athena→QuickSight 대시보드
- AWS Docs » Serving private content with CloudFront signed URLs and signed cookies
- AWS Samples » cloudfront‑signed‑url‑spring‑boot (GitHub)
- AWS WAF Developer Guide » Managing rate‑based rules
요약 — Signed URL/Cookie로 1차 인증, WAF와 Budgets로 2차 한도 방어를 구축하면, 공유 URL이 퍼져도 몇 분 내 무효화되고, 전송료 폭주 시 자동 차단까지 가능하다.