WAF - CloudFlare

김재근·2025년 4월 12일
post-thumbnail

Terraform으로 인프라를 구성하면서 WAF도 적용해보려 했지만,
AWS의 WAF는 시작부터 월 만원 이상이 나올 수 있다.
Nginx로 자체 구현하는 건 설정이 귀찮고 관리가 번거로워서,
이번에는 Cloudflare를 사용해 보기로 했다.

Cloudflare는 무료 플랜에서도 WAF, SSL, CDN, 캐싱, Rate Limiting 등
대부분의 웹 보안에 필요한 기능을 제공하며,
무엇보다 ALB 앞단에서 프록시로 작동하기 때문에 AWS 리소스를 보완하기에 적합하다.

[사용자 브라우저]
    ↓ HTTPS
[Cloudflare (WAF + Proxy + SSL)]
    ↓ HTTPS
[AWS ALB (ACM 인증서)]
    ↓
[EC2, ECS, 서비스 백엔드]

기존에는 Route53 + ALB + ACM으로 HTTPS 구성만 해놓은 상태였고,
여기에 Cloudflare를 얹어서 보안과 관리 편의성을 강화하는 방식으로 진행했다.


사전 준비: 기존 AWS 인프라

  • Route 53에서 도메인 구매
  • ACM 인증서 발급
  • ALB 생성 후 HTTPS 리스너에 인증서 연결
  • Route53 호스팅 영역에서 A 레코드로 ALB와 도메인 연결
  • HTTPS 정상 통신 확인

Cloudflare 가입 및 도메인 연결

https://cloudflare.com 가입 (구글 계정 가능)

도메인 입력 후 Free 플랜으로 시작하고

다음과 같은 네임서버(NS) 2개를 제공받는다.

lia.ns.cloudflare.com  
marek.ns.cloudflare.com

AWS Route 53 콘솔 → 도메인 등록 탭에서
기존 4개의 네임서버를 모두 삭제하고, 위 두 개만 등록한다.

전파에는 최대 24시간이 걸릴 수 있지만, 보통 10분 내에 Active 상태로 전환된다.


DNS 레코드 등록 (ALB 연결)

Cloudflare → DNS 탭 → + Add Record

항목
TypeCNAME
Name@ (루트 도메인)
TargetALB의 DNS 주소 (예: app-alb-1234.ap-northeast-2.elb.amazonaws.com)
Proxy☁️ Proxied (주황색 구름)

A 레코드는 IP 주소가 필요하므로 ALB 같은 DNS 주소는 CNAME으로 등록해야 한다.


SSL 설정

Cloudflare → SSL/TLS 탭 → Settings

Full(Strict) 모드로 설정한다.
이 모드는 Cloudflare ↔ ALB 구간도 HTTPS로 통신하며, ACM 인증서를 검증한다.

ACM 인증서를 발급받고 ALB에 연결한 상태라면, 문제 없이 적용된다.


보안 및 캐싱 설정 (WAF 포함)

Cloudflare에서 다양한 보안 기능을 무료로 제공한다.

  • 주요 설정들
항목추천 값
WAF RulesetOWASP 기본 활성화
Rate Limiting/login, /admin 등에 적용
Bot Fight ModeON
Browser Integrity CheckON
Challenge Passage24시간
Always Use HTTPSON
Minimum TLS Version1.2

캐싱을 설정하면 서버가 일시적으로 다운돼도 정적 리소스를 사용자에게 제공할 수 있다.

Challenge Passage는 사용자의 브라우저 인증 상태를 유지하는 시간이다.
기본은 30분이지만 일반 서비스에서는 24시간 정도면 괜찮지 않을까...?


ALB DNS가 바뀌는 경우

Terraform으로 ALB를 삭제했다가 다시 생성하면
ALB의 DNS 이름이 바뀐다.

이 경우 Cloudflare는 이전 레코드를 계속 바라보기 때문에 다음과 같은 에러가 발생할 수 있다:

→ 이때는 Cloudflare DNS 레코드에 새 ALB DNS 이름을 수동으로 갱신하면, 수 분 내에 정상화된다.


하지만

이걸 매번 수동으로 바꾸는 건 귀찮다.

Terraform에서 Cloudflare까지 함께 관리하면 이런 반복 작업 없이 자동화가 가능하다.

Cloudflare는 API 토큰Zone ID만 있으면 Terraform으로 DNS 레코드를 만들고 관리할 수 있다.
ALB를 다시 만들어도 DNS가 자동 반영되므로 훨씬 안정적이다.

Cloudflare 대시보드 → Overview 탭 → Zone ID 복사

# API Token과 Zone_id는 .tfvars 파일에 넣자.

# CloudFlare Provider 설정
provider "cloudflare" {
  api_token = var.cloudflare_api_token
}

# API Token 변수
variable "cloudflare_api_token" {
  type = string
}

# Zone_id 변수
variable "cloudflare_zone_id" {
  description = "CloudFlare Zone ID"
  type        = string
}

# CloudFlare DNS 레코드 설정
resource "cloudflare_record" "alb" {
  zone_id = var.cloudflare_zone_id
  name    = "@"
  type    = "CNAME"
  content = aws_lb.app.dns_name # AWS쪽에서 생성된 ALB의 DNS이름
  proxied = true
}

기존 레코드가 이미 있다면 삭제 후 apply 해도 되고,

terraform import로 기존 레코드를 state에 연결해도 된다. (삭제 후 apply 추천)

profile
FullStack + DevOps 개발자입니다.

0개의 댓글