콘텐츠로 이동

Network Security

분류: Layer 3 - AWS 인프라 & 보안

인프라 수준에서 네트워크 트래픽을 필터링·차단·암호화하여 서비스를 보호하는 메커니즘.

애플리케이션 보안(L1 Web Security)만으로 부족한 이유

XSS, SQL Injection을 코드 레벨에서 막아도, 악의적인 IP가 포트 스캔으로 취약점을 탐색하거나, 대규모 DDoS로 서버를 마비시키는 공격은 애플리케이션 코드가 관여하기도 전에 인프라 레벨에서 처리해야 한다. “성벽(네트워크 보안)“이 없으면 “문지기(앱 보안)“가 아무리 뛰어나도 소용없다.

실제 사고 사례와 수치

인도 에듀테크 기업 Physics Wallah는 AWS WAF + Shield를 도입한 뒤 3개월간 3억 1,500만 건의 악성 요청을 차단하고, DDoS 이벤트 35건을 방어하며 대응 속도를 400% 개선했다. 도입 전에는 수동 대응으로 서비스가 수십 분씩 중단됐다.

암호화폐 거래소 Bitbank는 반복적인 L7 DDoS 공격에 Shield Standard만으로 대응하다 한계에 직면해 Shield Advanced로 전환했다. 전환 후 정교한 HTTP Flood 공격에도 자동 WAF 규칙 생성으로 대응 시간을 수 분에서 수십 초로 단축했다.

2025년 기준 DDoS 공격 트렌드: L7(HTTP Flood) 비중이 급증하여 전체 DDoS 공격의 절반 이상이 애플리케이션 레벨을 타겟으로 한다. L3/L4 방어만으로는 더 이상 충분하지 않다.

네트워크 레벨 공격 유형

  • DDoS: 수만 대의 봇넷이 동시에 요청을 보내 서버 자원을 고갈시킨다
  • 포트 스캐닝: nmap으로 열려 있는 포트를 탐색해 공격 벡터를 찾는다
  • IP 스푸핑: 출발지 IP를 위조하여 방화벽 규칙을 우회한다

프론트 출신이라면: 프론트에서 fetch 요청 시 갑자기 403이 뜨는 경우가 있는데, 이게 CORS 문제인 줄 알았다가 실제로는 WAF 규칙에 차단된 경우가 많다. 네트워크 보안을 이해하면 이런 상황에서 올바른 원인을 빠르게 찾을 수 있다.

긴 문서를 읽기 전에 이 체크리스트로 핵심을 먼저 파악한다.

  • Security Group vs NACL: SG는 리소스 단위(Stateful), NACL은 서브넷 단위(Stateless). 네트워크 구조는 vpc-subnet-sg.md 참고.
  • WAF 위치: CloudFront → ALB → API Gateway 중 어디에 WAF를 붙일지 결정. HTTP 내용(SQL Injection, XSS)을 검사해야 할 위치에 적용.
  • AWS Managed Rules: AWSManagedRulesCommonRuleSet + AWSManagedRulesSQLiRuleSet으로 OWASP Top 10의 80% 커버. 직접 규칙을 다 작성하지 않아도 된다.
  • Shield Standard vs Advanced: Standard는 무료로 L3/L4 DDoS 방어. Advanced($3,000/월)는 L7 DDoS 자동 대응 + 비용 보전 + 24/7 DRT 지원.
  • VPC Endpoint: ECR, S3, CloudWatch에 대한 요청은 VPC Endpoint로 인터넷을 거치지 않고 직접 연결 → 보안 + NAT Gateway 비용 절감.
  • 암호화 전송 강제: ALB는 HTTP → HTTPS 리다이렉트, S3는 aws:SecureTransport: false Deny 정책으로 전 구간 HTTPS 적용.
  • WAF 로그 분석: WAF 차단 로그를 CloudWatch나 S3에 저장하고, Athena로 분석하면 어떤 규칙이 얼마나 차단하는지 파악 가능.
  • 최소 권한 SG: 아웃바운드를 0.0.0.0/0 전체 허용이 아닌 실제 필요한 포트·대상만 허용하도록 점차 줄여간다.

비유: 건물 경비 vs 동네 입구 검문소

Security Group은 각 건물(EC2, RDS, Lambda 등) 앞의 경비원이다. 한 번 통과하면 이후 응답은 자동 허용(Stateful). NACL은 서브넷 입구의 검문소다. 들어올 때와 나갈 때 각각 별도로 검사한다(Stateless).

동작 원리: 패킷이 VPC에 들어올 때 평가 순서

인터넷
인터넷 게이트웨이 (IGW)
NACL 인바운드 규칙 평가 (서브넷 레벨)
↓ (허용된 경우)
Security Group 인바운드 규칙 평가 (인스턴스 레벨)
↓ (허용된 경우)
EC2 인스턴스 (애플리케이션)
↓ (응답)
Security Group 아웃바운드 — Stateful이므로 자동 허용
NACL 아웃바운드 규칙 평가 — Stateless이므로 명시적 허용 필요
인터넷

Stateful vs Stateless 핵심 차이

Security Group (Stateful):
인바운드 포트 80 허용 설정 시
→ 요청: 클라이언트 → EC2 (허용)
→ 응답: EC2 → 클라이언트 (자동 허용, 아웃바운드 규칙 불필요)
NACL (Stateless):
인바운드 포트 80 허용 설정만으로는 부족
→ 요청: 클라이언트 → EC2 (인바운드 규칙으로 허용)
→ 응답: EC2 → 클라이언트 (아웃바운드 규칙에서 Ephemeral Port 1024-65535 허용 필요)

📖 더 보기: Security Groups and NACLs 공식 비교 — 두 메커니즘의 동작 차이 공식 설명

왜 둘 다 필요한가 (Defense in Depth)

계층도구역할
서브넷 레벨NACL특정 IP 범위 차단, 서브넷 단위 명시적 deny
인스턴스 레벨Security Group포트/프로토콜 기반 허용, 기본값 모두 차단

실무에서는 SG로 대부분 처리하고, NACL은 침해 사고 발생 시 특정 IP를 서브넷 전체에서 즉시 차단하는 용도로 활용한다.

네트워크 구조(Subnet, Route Table, IGW, NAT Gateway, VPC Endpoint)는 vpc-subnet-sg.md를 참고하세요. 이 문서는 트래픽 필터링·차단·암호화 보안 메커니즘에 집중합니다.

실습: Security Group 최소 권한 설정

Terminal window
# 보안 그룹 생성
aws ec2 create-security-group \
--group-name api-server-sg \
--description "API Server Security Group" \
--vpc-id vpc-xxxxxxxx
# 예상 출력
{
"GroupId": "sg-0a1b2c3d4e5f67890"
}
# HTTPS만 허용 (0.0.0.0/0 → 443)
aws ec2 authorize-security-group-ingress \
--group-id sg-0a1b2c3d4e5f67890 \
--protocol tcp \
--port 443 \
--cidr 0.0.0.0/0
# ALB에서만 8080 허용 (IP 범위 대신 SG 참조)
aws ec2 authorize-security-group-ingress \
--group-id sg-api \
--protocol tcp \
--port 8080 \
--source-group sg-alb # ALB의 SG ID

비유: 공항 보안 검색대

Security Group/NACL이 “비행기 탑승구 입구(IP/포트 레벨)“라면, WAF는 공항 보안 검색대(HTTP 내용 레벨)다. 짐(HTTP 요청)을 열어서 안에 무기(SQL Injection, XSS)가 있는지 실제 내용을 검사한다.

WAF가 트래픽을 검사하는 위치

인터넷 사용자
CloudFront ← WAF 적용 가능
ALB ← WAF 적용 가능
API Gateway← WAF 적용 가능
백엔드 서비스 (EC2, ECS, Lambda)

Web ACL → Rule Group → Rule → Statement 계층 구조

Web ACL (web-acl-my-api)
├── Rule Group (AWSManagedRulesCommonRuleSet)
│ ├── Rule: NoUserAgent_HEADER
│ ├── Rule: SizeRestrictions_BODY
│ └── Rule: CrossSiteScripting_BODY
├── Rule Group (AWSManagedRulesSQLiRuleSet)
│ └── Rule: SQLi_BODY
└── Custom Rule (block-specific-ip)
└── Statement: IPSet match → Block

규칙 평가 순서 (Priority 낮은 숫자부터)

Priority 0: IP 차단 규칙 (Block) → 매칭되면 즉시 Block, 평가 종료
Priority 1: Rate Limit 규칙 (Block) → IP당 초당 요청 초과 시 Block
Priority 2: Managed Rules (Allow/Block)
Priority 99: Default Action → 위 규칙에 모두 해당 안 되면 Allow

왜 이렇게 설계되었나

AWS Managed Rules로 OWASP Top 10(SQL Injection, XSS, 알려진 악성 IP 등) 80%를 커버하고, 나머지 20%를 커스텀 규칙으로 보완하는 방식이다. 보안팀이 모든 공격 패턴을 직접 정의하지 않아도 된다.

📖 더 보기: AWS WAF 동작 원리 공식 문서 — Web ACL 처리 흐름 상세 설명

비용 구조

항목비용
Web ACL$5/월
규칙(Rule)$1/개/월
요청 처리$0.60/백만 건
Managed Rule Group$1~10/그룹/월

월 트래픽별 WAF+Shield 비용 시뮬레이션

아래는 Web ACL 1개, 규칙 10개(AWSManagedRulesCommonRuleSet 포함 기준), Managed Rule Group 2개($5/월)를 사용하는 일반적인 외부 API 서비스의 예상 비용이다. Shield Advanced는 별도 항목으로 분리하여 표기한다.

구분100만 req/월1억 req/월10억 req/월
Web ACL$5$5$5
규칙 10개$10$10$10
Managed Rule Group 2개$5$5$5
요청 처리 ($0.60/백만)$0.60$60$600
WAF 소계$20.60$80$620
Shield Advanced (선택, 고정비)+$3,000+$3,000+$3,000
Shield Advanced 포함 합계$3,020$3,080$3,620

출처: AWS WAF Pricing, AWS Shield Pricing

의사결정 기준: 트래픽이 10억 req/월 수준이면 WAF 요청 비용($600)이 고정비를 압도한다. Shield Advanced($3,000/월 고정)는 트래픽 규모와 무관하게 SLA 보장과 DRT 지원이 필요한 B2C 서비스에 한해 적용을 검토한다. 순수 트래픽 규모만으로는 Shield Advanced 도입을 정당화하기 어렵다.

실습: WAF Web ACL 생성 및 ALB 연결

Terminal window
# Web ACL 생성 (ALB용은 REGIONAL, CloudFront용은 CLOUDFRONT)
aws wafv2 create-web-acl \
--name my-api-web-acl \
--scope REGIONAL \
--default-action Allow={} \
--rules '[
{
"Name": "AWSManagedRulesCommonRuleSet",
"Priority": 1,
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesCommonRuleSet"
}
},
"OverrideAction": {"None": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "CommonRuleSet"
}
}
]' \
--visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=my-api-web-acl \
--region ap-northeast-2
# 예상 출력
{
"Summary": {
"Name": "my-api-web-acl",
"Id": "abcd1234-...",
"ARN": "arn:aws:wafv2:ap-northeast-2:123456789:regional/webacl/my-api-web-acl/abcd1234"
}
}
# ALB에 Web ACL 연결
aws wafv2 associate-web-acl \
--web-acl-arn arn:aws:wafv2:ap-northeast-2:123456789:regional/webacl/my-api-web-acl/abcd1234 \
--resource-arn arn:aws:elasticloadbalancing:ap-northeast-2:123456789:loadbalancer/app/my-alb/...

동작 원리: 베이스라인 학습 → 이상 탐지 → 자동 완화

정상 트래픽 패턴 학습 (지속적)
실시간 트래픽 모니터링
이상 감지 (패킷 검증, SYN Flood 탐지, 속도 분산 분석)
자동 완화 (L3/L4: 1초 이내, L7: WAF 연동)

Shield Standard의 DDoS 완화 기법:

  1. 패킷 검증: IP, TCP, UDP, ICMP, DNS, NTP 프로토콜 형식 위반 패킷 즉시 차단
  2. TCP SYN Proxy: SYN Flood 공격 시 SYN Cookie를 전송해 실제 클라이언트인지 검증한 후에만 연결 허용
  3. 속도 제한 (Rate Limiting): 특정 IP에서 비정상적으로 많은 패킷이 오면 자동 차단

Standard vs Advanced 선택 기준

Shield StandardShield Advanced
비용무료 (모든 계정 기본 적용)$3,000/월 + 데이터 전송 비용
L3/L4 DDoS✅ 자동 완화✅ 자동 완화
L7 DDoS❌ (WAF로 별도 처리)✅ WAF 자동 규칙 생성
DRT 지원✅ (DDoS Response Team 24/7)
비용 보호✅ (DDoS로 인한 AWS 비용 환불)
공격 보고서✅ 상세 분석 리포트

Advanced가 필요한 경우: 외부 사용자 대상 서비스, SLA 보장이 필수인 B2C 서비스, 과거 DDoS 피해 이력이 있는 서비스.

📖 더 보기: AWS Shield Standard vs Advanced 공식 문서 — DDoS 완화 기법 상세 설명

비유: 번역 통역사

TLS Termination은 ALB가 암호화된 대화(HTTPS)를 클라이언트로부터 받아서 복호화(번역)한 다음, 백엔드 서버에는 평문(HTTP)으로 전달하는 구조다. 통역사(ALB)가 암호화/복호화를 대신 처리해주므로 백엔드 서버는 암호화에 신경 쓸 필요가 없다.

TLS 종단 위치별 동작

[클라이언트] ──HTTPS──→ [CloudFront] ──HTTPS──→ [ALB] ──HTTP──→ [EC2]
TLS Termination 발생
(여기서 복호화)

ACM으로 무료 인증서 발급

Terminal window
# 도메인 인증서 요청 (DNS 검증 방식)
aws acm request-certificate \
--domain-name api.mycompany.com \
--validation-method DNS \
--region ap-northeast-2
# 예상 출력
{
"CertificateArn": "arn:aws:acm:ap-northeast-2:123456789:certificate/abcd-1234"
}
# ALB HTTPS 리스너에 인증서 연결 (콘솔 또는 Terraform)
# ACM은 자동 갱신 (만료 60일 전부터 시도)

TLS Termination(ALB에서 복호화) vs End-to-End(백엔드까지 암호화)

TLS TerminationEnd-to-End
백엔드 부하낮음 (암호화 작업 없음)높음
인증서 관리ALB만 관리모든 인스턴스 관리 필요
VPC 내부 보안ALB-EC2 구간 평문VPC 내부도 암호화
적합한 경우일반적인 웹 서비스금융, 의료 등 규정 준수 필요

HTTPS 강제 리다이렉트 설정 (ALB 리스너 규칙)

// HTTP (포트 80) 리스너 규칙 — 모든 HTTP 요청을 HTTPS로 리다이렉트
{
"Actions": [
{
"Type": "redirect",
"RedirectConfig": {
"Protocol": "HTTPS",
"Port": "443",
"StatusCode": "HTTP_301"
}
}
],
"Conditions": [{ "Field": "path-pattern", "Values": ["/*"] }]
}

Mixed Content 에러의 원인: HTTPS 페이지에서 HTTP 리소스(이미지, API 호출 등)를 로드할 때 발생. 프론트에서 fetch("http://api.example.com/...")를 호출하면 브라우저가 차단한다. 플랫폼 엔지니어가 HTTPS 강제 리다이렉트와 ALB 설정을 올바르게 해두면 이런 문제를 방지할 수 있다.

📌 VPC 네트워크 격리 패턴(3계층 서브넷, NAT Gateway, VPC Endpoint)은 vpc-subnet-sg.md에서 다룹니다. 이 문서는 트래픽 필터링과 보안 정책(WAF, Shield, NACL, TLS)에 집중합니다.

AWS 네트워크 보안 전체 아키텍처 (텍스트 다이어그램)

인터넷
[CloudFront] ← WAF 적용 (L7: SQLi/XSS/Bot 차단)
│ Shield Standard 자동 적용 (L3/L4 DDoS)
[ALB] ← WAF 적용 (REGIONAL scope)
│ HTTPS 리스너 (ACM 인증서, TLS Termination)
│ HTTP → HTTPS 301 리다이렉트
▼ ← NACL 검문 (서브넷 레벨, Stateless)
[Public Subnet]
▼ ← Security Group 검문 (인스턴스 레벨, Stateful)
[Private Subnet]
├── ECS / EC2 (애플리케이션)
│ Security Group: ALB SG에서 8080만 허용
└── [Isolated Subnet]
RDS / ElastiCache
Security Group: ECS SG에서 5432/6379만 허용
인터넷 접근 완전 차단

도구별 책임 범위 요약

계층도구막는 것못 막는 것
L3/L4Shield StandardSYN Flood, UDP FloodL7 HTTP Flood
L3/L4NACLIP 범위 차단HTTP 내용 검사
L3/L4Security Group포트 기반 접근 제어HTTP 내용 검사
L7WAFSQLi, XSS, Rate Limit인증/인가 우회
L7Shield AdvancedL7 DDoS 자동 완화비즈니스 로직 공격

실무 기본 조합: Security Group + WAF(ALB 앞단) → 외부 노출 서비스 최소 요건

ALB 앞단에 WAF 적용 (Terraform)

# WAF Web ACL
resource "aws_wafv2_web_acl" "api_waf" {
name = "api-waf"
scope = "REGIONAL"
default_action {
allow {}
}
rule {
name = "AWSManagedRulesCommonRuleSet"
priority = 1
override_action {
none {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesCommonRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "CommonRuleSet"
sampled_requests_enabled = true
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "api-waf"
sampled_requests_enabled = true
}
}
# ALB에 WAF 연결
resource "aws_wafv2_web_acl_association" "api_waf_alb" {
resource_arn = aws_lb.api.arn
web_acl_arn = aws_wafv2_web_acl.api_waf.arn
}

VPC Flow Logs로 의심 트래픽 감지

Terminal window
# VPC Flow Logs 활성화
aws ec2 create-flow-logs \
--resource-type VPC \
--resource-ids vpc-xxxxxxxx \
--traffic-type ALL \
--log-destination-type cloud-watch-logs \
--log-group-name /aws/vpc/flowlogs \
--deliver-logs-permission-arn arn:aws:iam::123456789:role/FlowLogsRole
# CloudWatch Logs Insights 쿼리로 REJECT 트래픽 분석
# fields @timestamp, srcAddr, dstAddr, dstPort, action
# | filter action = "REJECT"
# | sort @timestamp desc
# | limit 100

보안 TF: 신규 서비스에 WAF 적용 — Step-by-step 시나리오

실제 업무에서 신규 ALB에 WAF를 안전하게 적용할 때 아래 순서를 따른다.

Phase 1: 준비 (Count 모드 배포)

Terminal window
# 1-1. Web ACL 생성 — 전체 Managed Rules를 Count 모드로 시작
aws wafv2 create-web-acl \
--name prod-api-waf \
--scope REGIONAL \
--default-action Allow={} \
--rules file://waf-count-mode-rules.json \
--visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=prod-api-waf \
--region ap-northeast-2
# 1-2. ALB에 연결
aws wafv2 associate-web-acl \
--web-acl-arn arn:aws:wafv2:ap-northeast-2:123456789:regional/webacl/prod-api-waf/id \
--resource-arn arn:aws:elasticloadbalancing:...:loadbalancer/app/prod-alb/...

Phase 2: 2주간 트래픽 관찰 — False Positive 식별

Terminal window
# Sampled Requests로 매칭된 요청 확인 (Count 모드라 실제 차단 없음)
aws wafv2 get-sampled-requests \
--web-acl-arn arn:aws:wafv2:ap-northeast-2:123456789:regional/webacl/prod-api-waf/id \
--rule-metric-name AWSManagedRulesCommonRuleSet \
--scope REGIONAL \
--time-window StartTime=$(date -d '24 hours ago' +%s),EndTime=$(date +%s) \
--max-items 50
# CloudWatch에서 규칙별 매칭 수 확인
# 콘솔: WAF → Web ACL → prod-api-waf → Overview 탭
# → CountedRequests 메트릭에서 어떤 규칙이 가장 많이 매칭되는지 파악

Phase 3: 예외 규칙 추가 후 Block 모드 전환

Terminal window
# CI/CD 서버, 파트너 IP 등 신뢰 IP를 IP Set으로 관리
aws wafv2 create-ip-set \
--name trusted-ips \
--scope REGIONAL \
--ip-address-version IPV4 \
--addresses "10.0.0.0/8" "203.0.113.100/32" # 내부망 + CI/CD IP
# Block 모드로 전환 (Managed Rule의 OverrideAction을 Block으로 변경)
# 콘솔: Web ACL → Rules → AWSManagedRulesCommonRuleSet → Edit → Override action: None (개별 규칙 Action 사용)

Phase 4: 운영 모니터링

Terminal window
# WAF 차단 메트릭 CloudWatch Alarm 설정 (급격한 증가 = 공격 또는 False Positive)
aws cloudwatch put-metric-alarm \
--alarm-name waf-block-spike \
--metric-name BlockedRequests \
--namespace AWS/WAFV2 \
--dimensions Name=WebACL,Value=prod-api-waf Name=Region,Value=ap-northeast-2 Name=Rule,Value=ALL \
--statistic Sum \
--period 300 \
--threshold 1000 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 1 \
--alarm-actions arn:aws:sns:...:waf-alert-topic

보안 TF: WAF 규칙 설계 및 관리

WAF Managed Rules는 기본값으로 일부 정상 요청을 차단할 수 있다. 초기에는 Count 모드로 운영하면서 어떤 요청이 매칭되는지 관찰한 뒤, Block 모드로 전환하는 것이 안전하다.

Terminal window
# Sampled Requests로 최근 차단된 요청 확인
aws wafv2 get-sampled-requests \
--web-acl-arn arn:aws:wafv2:... \
--rule-metric-name CommonRuleSet \
--scope REGIONAL \
--time-window StartTime=1700000000,EndTime=1700100000 \
--max-items 100

Terraform으로 보안 그룹 코드화

resource "aws_security_group" "api_server" {
name = "api-server-sg"
vpc_id = var.vpc_id
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
security_groups = [aws_security_group.alb.id] # ALB SG만 허용
description = "Allow traffic from ALB only"
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
description = "Allow all outbound"
}
}

Security Group vs NACL vs WAF 비교

비교 항목Security GroupNACLWAF
동작 레이어L3/L4 (IP/Port)L3/L4 (IP/Port)L7 (HTTP)
Stateful
적용 대상인스턴스/ENI서브넷CloudFront/ALB/APIGW
기본 동작모두 차단 (Deny All)모두 허용규칙에 따라
Deny 규칙❌ (허용만 가능)
HTTP 내용 검사
주요 용도포트 기반 접근 제어IP 범위 차단웹 공격 차단

WAF vs Shield vs Network Firewall 비교

비교 항목WAFShieldNetwork Firewall
목적웹 공격 차단 (OWASP)DDoS 완화L3-L7 심층 패킷 검사
방어 대상HTTP 취약점대용량 트래픽모든 프로토콜
비용$5/월 + 요청당무료~$3,000/월$0.395/시간
필수 여부외부 노출 서비스 필수Standard 기본 포함엔터프라이즈 환경

도구 선택 판단 트리 (실무 기준)

Q1. HTTP 요청 내용(Body, 헤더, URL)을 검사해야 하는가?
→ YES: WAF 필수 (SQL Injection, XSS, Rate Limit)
→ NO : Q2로 이동
Q2. IP/포트 레벨 트래픽 제어가 필요한가?
→ 인스턴스 단위 제어: Security Group
→ 서브넷 전체 IP 범위 차단(침해 대응): NACL
Q3. DDoS 방어가 필요한가?
→ L3/L4 대용량 DDoS: Shield Standard (무료, 자동 적용)
→ L7 DDoS + SLA 보장 + DRT 지원: Shield Advanced ($3,000/월, B2C 대형 서비스)
Q4. 멀티프로토콜(TCP/UDP/ICMP) 심층 검사가 필요한가?
→ YES: AWS Network Firewall (엔터프라이즈 환경)
→ NO : WAF + SG 조합으로 충분
실무 기본 조합: Security Group + WAF (ALB 앞단)
→ 외부 노출 서비스 최소 요건
→ Shield Standard는 자동 적용이므로 별도 설정 불필요

WAF 도입 시 단계별 접근 (프로덕션 안전 배포)

1단계: Count 모드 (2주) — 차단 없이 로그만 수집
→ CloudWatch에서 어떤 요청이 매칭되는지 관찰
→ 정상 트래픽인데 매칭되는 False Positive 식별
2단계: 예외 규칙 추가 — False Positive 제거
→ 특정 URI(/api/editor), 특정 IP(CI/CD 서버) 허용 규칙 추가
→ Priority 0에 Allow 규칙으로 Managed Rules보다 먼저 평가되도록
3단계: Block 모드 전환
→ Count 모드 메트릭과 Block 모드 메트릭을 비교하며 모니터링
→ 초반 1주일은 알람 임계값을 낮게 설정하여 이상 징후 빠르게 포착

네트워크 보안 vs 애플리케이션 보안

네트워크 보안이 막는 것:
- 특정 IP 또는 IP 범위 접근 차단
- SQL Injection 패턴이 포함된 HTTP 요청 차단
- 초당 10,000건 이상의 Rate Limit 초과 요청 차단
- DDoS 공격 트래픽 완화
애플리케이션 보안이 막는 것:
- 인증/인가 로직 우회 시도
- 세션 하이재킹
- 비즈니스 로직 공격 (재고보다 많이 주문 등)
- 정상 사용자처럼 보이는 봇

❌ 정상 요청이 WAF에서 403으로 차단됨

섹션 제목: “❌ 정상 요청이 WAF에서 403으로 차단됨”

증상

HTTP/1.1 403 Forbidden
x-amzn-RequestId: abcd1234
x-amzn-waf-action: Block

프론트엔드에서 API 호출 시 갑자기 403이 발생하고, CloudWatch에서 WAF 차단 메트릭이 증가한다.

원인

AWS Managed Rules가 요청 내용(Body, 헤더, URL 파라미터)을 SQL Injection 또는 XSS로 오탐지(False Positive)한 경우. 예를 들어 HTML 에디터에서 <script> 태그가 포함된 본문을 전송하거나, URL에 특수문자가 포함된 경우.

해결

Terminal window
# 1. Sampled Requests에서 차단된 요청 확인
aws wafv2 get-sampled-requests \
--web-acl-arn arn:aws:wafv2:ap-northeast-2:123456789:regional/webacl/my-api-web-acl/id \
--rule-metric-name AWSManagedRulesCommonRuleSet \
--scope REGIONAL \
--time-window StartTime=$(date -d '1 hour ago' +%s),EndTime=$(date +%s) \
--max-items 10
# 2. 차단 규칙을 Count 모드로 전환하여 실제 차단 없이 모니터링
# (콘솔 → WAF → Web ACL → Rules → Rule 편집 → Override action: Count)
# 3. 특정 URI에 대한 예외 규칙 추가 (예: /api/editor는 XSS 규칙 제외)
aws wafv2 update-web-acl \
--name my-api-web-acl \
--scope REGIONAL \
--id abcd1234 \
--rules '[
{
"Name": "AllowEditorEndpoint",
"Priority": 0,
"Action": {"Allow": {}},
"Statement": {
"ByteMatchStatement": {
"SearchString": "/api/editor",
"FieldToMatch": {"UriPath": {}},
"TextTransformations": [{"Priority": 0, "Type": "NONE"}],
"PositionalConstraint": "STARTS_WITH"
}
},
"VisibilityConfig": { ... }
}
]'

❌ VPC Flow Logs에서 REJECT가 보이는데 원인 불명

섹션 제목: “❌ VPC Flow Logs에서 REJECT가 보이는데 원인 불명”

증상

VPC Flow Logs CloudWatch Insights 쿼리 결과:

timestamp srcAddr dstAddr dstPort action
2026-04-08 10:23 203.0.113.45 10.0.1.45 5432 REJECT
2026-04-08 10:23 10.0.0.100 10.0.1.45 5432 REJECT

내부 서비스(10.0.0.100)에서 RDS(10.0.1.45:5432)로의 요청도 REJECT되는 상황.

원인

Security Group과 NACL 중 어느 쪽이 차단하는지 구분이 안 되는 경우. 두 가지를 순서대로 확인해야 한다.

해결

Terminal window
# 1. RDS 보안 그룹의 인바운드 규칙 확인
aws ec2 describe-security-groups \
--group-ids sg-rds \
--query 'SecurityGroups[].IpPermissions'
# ECS 보안 그룹에서 5432가 허용되어 있는지 확인
# → 없다면 SG 문제
# 2. 서브넷의 NACL 규칙 확인
aws ec2 describe-network-acls \
--filters Name=association.subnet-id,Values=subnet-rds
# 인바운드/아웃바운드 양방향 규칙 모두 확인
# → NACL은 Stateless이므로 아웃바운드(Ephemeral Port 1024-65535)도 허용 필요
# 3. 빠른 구분법: SG는 인스턴스 레벨, NACL은 서브넷 레벨
# 같은 서브넷 내 다른 인스턴스에서는 접근이 되는가?
# → YES: NACL은 정상, SG 문제
# → NO : NACL 문제

❌ ACM 인증서 갱신 실패 — 서비스가 HTTPS로 응답 안 함

섹션 제목: “❌ ACM 인증서 갱신 실패 — 서비스가 HTTPS로 응답 안 함”

증상

Certificate status: Failed
Renewal status: Failed - Domain validation is failing for domain api.example.com

ALB에 붙어있던 ACM 인증서가 만료되어 브라우저에서 NET::ERR_CERT_DATE_INVALID 오류 발생.

원인

DNS 검증 방식을 사용 중인 경우, ACM이 자동 갱신을 위해 Route 53에 CNAME 레코드를 생성해야 하는데 해당 레코드가 삭제되었거나 TTL이 너무 낮은 경우. 또는 Route 53이 아닌 외부 DNS를 사용하는 경우 CNAME 레코드를 수동으로 갱신해야 한다.

해결

Terminal window
# 1. 인증서 상태 확인
aws acm describe-certificate \
--certificate-arn arn:aws:acm:ap-northeast-2:123456789:certificate/abcd \
--query 'Certificate.{Status: Status, RenewalStatus: RenewalSummary.RenewalStatus}'
# 예상 출력 (정상)
{
"Status": "ISSUED",
"RenewalStatus": "SUCCESS"
}
# 예상 출력 (실패)
{
"Status": "EXPIRED",
"RenewalStatus": "FAILED"
}
# 2. DNS 검증 CNAME 레코드 재확인
aws acm describe-certificate \
--certificate-arn arn:aws:acm:... \
--query 'Certificate.DomainValidationOptions[].ResourceRecord'
# 3. Route 53에 CNAME 레코드 재등록 (자동 등록이 안 된 경우)
# 콘솔: ACM → 인증서 → "Route 53에서 레코드 생성" 버튼 클릭
# 4. 비상 조치: 새 인증서 발급 후 ALB에 교체
aws acm request-certificate \
--domain-name api.example.com \
--validation-method DNS

❌ ALB Health Check 실패로 타겟 그룹에서 인스턴스 제외됨

섹션 제목: “❌ ALB Health Check 실패로 타겟 그룹에서 인스턴스 제외됨”

증상

ALB Target Group 콘솔에서 모든 타겟이 unhealthy 상태. 서비스는 실제로 정상 실행 중인데 외부에서 502 Bad Gateway 응답.

원인

EC2/ECS 인스턴스의 Security Group이 ALB의 Health Check 포트를 허용하지 않는 경우. ALB는 VPC 내부 IP에서 Health Check를 보내므로, SG 인바운드에 ALB의 SG 또는 ALB 서브넷 CIDR를 허용해야 한다.

해결

Terminal window
# ALB가 사용하는 보안 그룹 확인
aws elbv2 describe-load-balancers \
--query 'LoadBalancers[].SecurityGroups'
# EC2 SG에 ALB SG로부터의 Health Check 포트 허용
aws ec2 authorize-security-group-ingress \
--group-id sg-api-server \
--protocol tcp \
--port 8080 \
--source-group sg-alb # ALB의 Security Group ID
# ECS의 경우 태스크 보안 그룹도 동일하게 설정 필요

6.7 클라우드 보안 원리의 전이 — 멀티 클라우드 WAF/DDoS 비교

섹션 제목: “6.7 클라우드 보안 원리의 전이 — 멀티 클라우드 WAF/DDoS 비교”

WAF와 DDoS 방어의 핵심 원리(L3/L4 네트워크 레이어 차단 + L7 HTTP 내용 검사 + Rate Limiting + Managed Rules)는 클라우드 벤더에 관계없이 동일하다. 아래 표는 세 클라우드의 동일 개념을 대응 도구로 매핑한다.

개념AWSGCPAzure
L3/L4 DDoS 방어Shield Standard (무료, 자동)Cloud Armor 기본 포함DDoS Network/IP Protection (유료)
L7 WAFAWS WAF (별도 설정)Cloud Armor (동일 제품에 통합)Azure Front Door WAF / App Gateway WAF
Managed RulesAWSManagedRulesCommonRuleSet 등Google Preconfigured WAF RulesMicrosoft Default Rule Set (DRS)
Rate LimitingWAF Rate-based RuleCloud Armor Rate LimitingWAF Custom Rule (Rate Limit)
비용 구조$5 Web ACL + $0.60/백만 req$5 정책 + $0.75/백만 req고정 $300~400/월 + 요청당 변동
글로벌 배포CloudFront WAF (엣지)글로벌 외부 LB (Google PoP)Azure Front Door (엣지)
L7 DDoS 자동 완화Shield Advanced ($3,000/월)Adaptive Protection (ML 기반 자동)Azure DDoS + WAF 연동 (Network Protection 필요)
DRT/긴급 지원Shield Advanced DRT (24/7)Cloud Armor EnterpriseDDoS Rapid Response (DRR)

출처: AWS WAF 공식 문서 · GCP Cloud Armor 공식 문서 · Azure DDoS Protection 공식 문서 · Azure Front Door WAF

전이 가능한 핵심 통찰

  1. WAF는 항상 엣지에 배치한다: CloudFront(AWS), 글로벌 외부 LB(GCP), Front Door(Azure) 모두 원본 서버에 도달하기 전에 HTTP 내용을 검사한다. “어디에 붙이느냐”라는 질문의 답은 벤더와 무관하게 “트래픽이 원본에 닿기 전 가장 바깥 레이어”다.
  2. GCP는 WAF+DDoS가 단일 제품(Cloud Armor)에 통합되어 있다. AWS는 WAF와 Shield를 별도로 설정해야 하고, Azure는 DDoS Protection Plan + WAF SKU를 별도로 활성화해야 한다. 통합 수준이 다르므로 운영 복잡도가 다르다.
  3. Rate Limiting 키 설계는 동일한 트레이드오프를 가진다: IP 기반이면 NAT 환경에서 정상 사용자를 차단할 위험이 있고, 사용자 ID 기반이면 인증된 요청에만 적용 가능하다. 어떤 벤더를 쓰든 동일한 설계 판단이 필요하다.

6.8 WAF False Positive 인시던트 대응 타임라인

섹션 제목: “6.8 WAF False Positive 인시던트 대응 타임라인”

WAF를 Block 모드로 운영하면 정상 요청이 차단(False Positive)될 수 있다. 아래는 실제 운영 환경에서 발생하는 False Positive 인시던트의 탐지부터 복구까지 절차를 시계열로 정리한 것이다.

T+0분 — 알람 수신
CloudWatch 알람(BlockedRequests 급증) 또는 PagerDuty 노티.
사용자 제보: "API 403 오류 발생"
→ 즉시 WAF 대시보드 확인 (콘솔 → WAF → Web ACL → Overview)
T+5분 — WAF 로그 확인
차단된 요청 샘플링으로 어떤 규칙이 발동했는지 식별.
# 최근 1시간 차단 요청 샘플 조회
aws wafv2 get-sampled-requests \
--web-acl-arn arn:aws:wafv2:ap-northeast-2:123456789:regional/webacl/prod-api-waf/id \
--rule-metric-name AWSManagedRulesCommonRuleSet \
--scope REGIONAL \
--time-window StartTime=$(date -v-1H +%s),EndTime=$(date +%s) \
--max-items 20
→ 출력에서 RuleMatchDetails.RuleId 확인: 예) "CrossSiteScripting_BODY"
→ 차단된 URI, 요청 본문 패턴 확인
T+10분 — IP/패턴 식별 및 영향 범위 분류
① 특정 IP의 악의적 요청인가? → 실제 공격일 가능성 → Block 유지
② 정상 사용자의 특정 요청 패턴인가? → False Positive 확정
예: HTML 에디터 본문에 <script> 포함, URL 파라미터에 특수문자
T+15분 — 임시 조치: 해당 규칙을 Count 모드로 전환
Block에서 Count로 전환하면 차단 없이 로그만 수집 → 즉시 서비스 정상화.
# 콘솔: WAF → Web ACL → Rules → CrossSiteScripting 규칙 → Edit
# → Override action: Count (즉시 적용, 수 초 이내 반영)
또는 특정 URI에 Allow 예외 규칙 추가 (Priority 0으로 Managed Rules보다 먼저 평가):
aws wafv2 update-web-acl \
--name prod-api-waf --scope REGIONAL --id <id> \
--rules '[{"Name":"AllowEditorEndpoint","Priority":0,
"Action":{"Allow":{}},"Statement":{"ByteMatchStatement":{
"SearchString":"/api/editor","FieldToMatch":{"UriPath":{}},
"TextTransformations":[{"Priority":0,"Type":"NONE"}],
"PositionalConstraint":"STARTS_WITH"}},"VisibilityConfig":{
"SampledRequestsEnabled":true,"CloudWatchMetricsEnabled":true,
"MetricName":"AllowEditor"}}]'
T+30분 — 정상화 확인 및 알람 해제
BlockedRequests 메트릭이 기준값 이하로 복귀 확인.
사용자에게 서비스 정상 복구 알림.
Count 모드 로그를 24~48시간 추가 수집하여 패턴 분석.
T+다음날 — 항구적 예외 규칙 추가 후 Block 모드 복구
분석된 정상 패턴을 화이트리스트 규칙으로 등록.
대상 URI, 특정 헤더 조합, 또는 신뢰 IP Set 기반으로 예외 설정.
규칙 재활성화(Block 모드) 후 모니터링 강화.

False Positive 예방 원칙

단계조치
초기 배포반드시 Count 모드 2주 → 트래픽 패턴 관찰 후 Block 전환
규칙 추가 시새 규칙은 항상 Count 모드로 먼저 적용, 1주일 후 Block 전환
운영 중BlockedRequests 알람 임계값을 정상 수준의 3배로 설정
인시던트 후Post-mortem 문서화 + 예외 규칙 Terraform 코드화로 IaC 관리
  • 외부 노출 ALB/CloudFront에 WAF가 적용되어 있는가?

    Terminal window
    # ALB에 연결된 WAF 확인
    aws wafv2 get-web-acl-for-resource \
    --resource-arn arn:aws:elasticloadbalancing:ap-northeast-2:123456789:loadbalancer/app/prod-alb/...
    # "WebACL" 키가 없으면 미적용
  • 보안 그룹이 0.0.0.0/0 인바운드를 허용하지 않는가? (443, 80 제외)

    Terminal window
    # 0.0.0.0/0 인바운드 허용 SG 목록 조회
    aws ec2 describe-security-groups \
    --filters Name=ip-permission.cidr,Values='0.0.0.0/0' \
    --query 'SecurityGroups[].{GroupId: GroupId, GroupName: GroupName, Ports: IpPermissions[].FromPort}' \
    --output table
    # 22(SSH), 3389(RDP) 포트가 0.0.0.0/0으로 열려있으면 즉시 수정
  • 모든 외부 트래픽이 HTTPS인가? (HTTP → HTTPS 301 리다이렉트 설정)

    Terminal window
    # ALB 리스너 목록 확인 (포트 80 리스너가 Redirect인지 확인)
    aws elbv2 describe-listeners \
    --load-balancer-arn arn:aws:elasticloadbalancing:...:loadbalancer/app/prod-alb/... \
    --query 'Listeners[].{Port: Port, Protocol: Protocol, DefaultActions: DefaultActions[].Type}'
    # 포트 80의 Action이 "redirect"인지 확인
  • VPC Flow Logs가 활성화되어 있는가?

    Terminal window
    aws ec2 describe-flow-logs \
    --filter Name=resource-id,Values=vpc-xxxxxxxx \
    --query 'FlowLogs[].{FlowLogStatus: FlowLogStatus, LogDestination: LogDestination}'
    # FlowLogStatus: ACTIVE 이어야 함. 없으면 미활성화
  • Private 서브넷의 DB/캐시 리소스가 인터넷에 노출되지 않았는가?

    Terminal window
    # RDS 인스턴스 퍼블릭 접근 여부 확인
    aws rds describe-db-instances \
    --query 'DBInstances[].{DBId: DBInstanceIdentifier, PubliclyAccessible: PubliclyAccessible}'
    # PubliclyAccessible: true 이면 위험 → 즉시 수정
  • WAF 규칙이 Count 모드로 검증 후 Block 모드로 전환되었는가?

    Terminal window
    # Web ACL 규칙의 현재 Action 모드 확인
    aws wafv2 get-web-acl \
    --name prod-api-waf \
    --scope REGIONAL \
    --id abcd-1234 \
    --query 'WebACL.Rules[].{Name: Name, OverrideAction: OverrideAction}'
    # OverrideAction.Count가 있으면 아직 Count 모드
  • ACM 인증서 DNS 검증 CNAME 레코드가 유지되고 있는가?

    Terminal window
    # 인증서 상태 및 갱신 상태 확인
    aws acm list-certificates \
    --query 'CertificateSummaryList[].{Domain: DomainName, Status: Status}' \
    --output table
    # Status가 ISSUED가 아닌 인증서 상세 확인
    aws acm describe-certificate \
    --certificate-arn arn:aws:acm:... \
    --query 'Certificate.{Status: Status, RenewalStatus: RenewalSummary.RenewalStatus}'
  • AWS Network Firewall: L3~L7 심층 패킷 검사(DPI). 도메인 필터링, Suricata 호환 규칙 지원. 엔터프라이즈 환경에서 SG/NACL/WAF의 상위 계층 보안.
  • GuardDuty: VPC Flow Logs, CloudTrail, DNS 로그를 ML로 분석하여 위협 탐지. 포트 스캐닝, C&C 서버 통신, 자격증명 유출 등을 탐지.
  • AWS Config Rules: 보안 그룹에 0.0.0.0/0:22 (SSH) 허용 여부를 자동으로 감사하는 managed rule 제공.
  • Zero Trust Network Architecture: “내부 네트워크는 안전하다”는 전제를 버리고, 모든 요청을 검증하는 보안 모델. VPC 내부 트래픽도 mTLS로 인증하는 방향으로 진화 중.
  • AWS PrivateLink: 인터넷 없이 다른 VPC 또는 AWS 서비스에 접근. NAT Gateway 대비 비용 절감 + 보안 강화.
  • 현재 VPC의 보안 그룹 규칙 전수 점검
Terminal window
# 0.0.0.0/0 인바운드 허용 SG 목록 조회 (SSH/RDP 포트 포함 여부)
aws ec2 describe-security-groups \
--filters Name=ip-permission.cidr,Values='0.0.0.0/0' \
--query 'SecurityGroups[].{GroupId: GroupId, GroupName: GroupName, Ports: IpPermissions[].FromPort}' \
--output table
# 예상 출력
------------------------------------------------------
| DescribeSecurityGroups |
+----------------+------------------+----------------+
| GroupId | GroupName | Ports |
+----------------+------------------+----------------+
| sg-0a1b2c3d | alb-sg | 80, 443 |
| sg-0e5f6g7h | bastion-sg | 22 | 위험! 제한 필요
+----------------+------------------+----------------+
  • WAF Web ACL 하나 생성 → ALB에 연결 → 테스트 요청으로 차단 확인
Terminal window
# WAF 차단 테스트 (SQL Injection 패턴)
curl -v "https://api.mycompany.com/search?q=' OR '1'='1"
# 예상 출력 (WAF가 차단한 경우)
# HTTP/1.1 403 Forbidden
# x-amzn-waf-action: Block
# 정상 요청
curl -v "https://api.mycompany.com/health"
# HTTP/1.1 200 OK
  • VPC Flow Logs 활성화 → 의심 트래픽 필터링 실습
Terminal window
# VPC Flow Logs 활성화
aws ec2 create-flow-logs \
--resource-type VPC \
--resource-ids vpc-xxxxxxxx \
--traffic-type REJECT \
--log-destination-type cloud-watch-logs \
--log-group-name /aws/vpc/flowlogs
# CloudWatch Logs Insights 쿼리
# (콘솔 → CloudWatch → Logs Insights)
# fields @timestamp, srcAddr, dstAddr, dstPort, action
# | filter action = "REJECT"
# | stats count(*) by srcAddr
# | sort count desc
# | limit 20
# 예상 출력
# srcAddr count(*)
# 203.0.113.45 1547 ← 포트 스캔 의심
# 198.51.100.99 342
  • ACM 인증서 발급 → ALB에 HTTPS 설정
Terminal window
# 인증서 발급 요청
aws acm request-certificate \
--domain-name api.mycompany.com \
--validation-method DNS \
--region ap-northeast-2
# 인증서 상태 확인 (DNS CNAME 등록 후 수 분 소요)
aws acm describe-certificate \
--certificate-arn arn:aws:acm:... \
--query 'Certificate.{Status: Status, DomainName: DomainName}'
# 예상 출력 (검증 완료)
{
"Status": "ISSUED",
"DomainName": "api.mycompany.com"
}
  1. 네트워크 보안은 SG(인스턴스 레벨, Stateful) → NACL(서브넷 레벨, Stateless) → WAF(HTTP 레벨, 내용 검사) 3계층으로 구성된다
  2. WAF는 ALB/CloudFront 앞단에서 Web ACL → Rule Group → Rule → Statement 순서로 HTTP 요청을 검사하며, Managed Rules가 OWASP Top 10의 80%를 자동 커버한다
  3. Shield Standard는 무료로 L3/L4 DDoS를 1초 이내에 자동 완화하고, Advanced는 대부분의 서비스에 불필요하다 ($3,000/월)
  4. TLS Termination은 ALB에서 처리하고 인증서는 ACM으로 무료 관리 — HTTP → HTTPS 리다이렉트와 Mixed Content 에러 방지가 플랫폼 엔지니어의 역할이다
  5. VPC 네트워크 격리(Public/Private/Isolated 서브넷, NAT Gateway, VPC Endpoint)는 vpc-subnet-sg.md 참고 — 이 문서는 WAF·Shield·NACL·TLS 트래픽 필터링에 집중한다

프론트 개발자가 네트워크 보안을 이해해야 하는 순간들

프론트엔드 개발 시 fetch 또는 axios로 API를 호출했을 때 갑자기 403이 오면, 처음에는 CORS 문제라고 생각하기 쉽다. 그런데 실제로는 세 가지 전혀 다른 원인일 수 있다:

403 응답의 원인별 구분:
1. CORS 에러 → 브라우저가 OPTIONS preflight를 차단
증상: 브라우저 콘솔에 "CORS policy" 메시지
해결: 서버에서 Access-Control-Allow-Origin 헤더 설정
2. WAF 차단 → HTTP 요청 내용이 공격 패턴과 매칭
증상: 응답 헤더에 x-amzn-waf-action: Block 포함
해결: WAF 로그 확인 → 해당 규칙 Count 모드로 전환 or 예외 추가
3. Security Group 차단 → 포트 접근 자체가 막힘
증상: 요청이 타임아웃 (응답 자체가 없음, 403이 아님)
해결: Security Group 인바운드 규칙 확인

특히 WAF False Positive는 프론트 개발자가 알고 있으면 디버깅이 훨씬 빠르다. 예를 들어 WYSIWYG 에디터(Quill, TipTap 등)에서 HTML 콘텐츠를 API로 전송할 때, WAF의 XSS 규칙이 <script> 태그나 onerror= 패턴을 보고 차단할 수 있다. 이런 경우 WAF 예외 규칙이 필요하다.

Mixed Content 에러와 플랫폼 엔지니어

HTTPS 페이지에서 HTTP API를 호출하면 브라우저가 Mixed Content 에러로 차단한다. 이것은 프론트 코드의 문제가 아니라 인프라 설정의 문제다:

❌ Mixed Content 에러가 발생하는 상황:
프론트: https://myapp.com (HTTPS)
API 호출: http://api.mycompany.com/users (HTTP)
→ 브라우저: Mixed Content 차단!
✅ 플랫폼 엔지니어가 설정해야 할 것:
ALB 포트 80 리스너 → HTTP 301 → HTTPS 리다이렉트
ACM 인증서 → ALB HTTPS 리스너에 연결
→ http://api... 로 요청해도 자동으로 https://api... 로 리다이렉트

Security Group은 React 컴포넌트 scope와 비슷하다

React에서 컴포넌트는 props로 받지 않으면 부모의 상태에 직접 접근할 수 없다. Security Group도 마찬가지다: 명시적으로 허용하지 않으면 같은 VPC 내 서비스라도 서로 접근할 수 없다.

React 컴포넌트:
Parent → 명시적 props 전달 없음 → Child는 부모 state 접근 불가
Security Group:
ECS Task → 명시적 인바운드 규칙 없음 → RDS는 연결 차단

두 경우 모두 “격리가 기본값”이고, “허용이 명시적”이다.

실무 아키텍처 패턴 — 네트워크 보안 전체 계층

섹션 제목: “실무 아키텍처 패턴 — 네트워크 보안 전체 계층”
[외부 → 내부 트래픽 흐름과 보안 계층]
인터넷 사용자
[CloudFront] ← Shield Standard (L3/L4 DDoS 자동 완화)
│ ← WAF (L7: SQLi/XSS/Bot/Rate Limit)
│ ← ACM 인증서 (HTTPS 종단)
[ALB] ← WAF (REGIONAL scope, CloudFront 없을 때)
│ ← HTTPS 리스너 (ACM 인증서)
│ ← HTTP → HTTPS 301 리다이렉트
▼ ← NACL 인바운드 검사 (서브넷 레벨, Stateless)
[Public Subnet: ALB, NAT Gateway]
▼ ← Security Group 검사 (인스턴스 레벨, Stateful)
[Private Subnet: ECS Task, EC2]
│ Security Group: ALB SG에서 8080만 허용
│ 아웃바운드: RDS SG 5432, CloudWatch 443, S3 VPC Endpoint
▼ ← Security Group 검사 (DB 레벨)
[Isolated Subnet: RDS, ElastiCache]
Security Group: ECS SG에서만 5432/6379 허용
Route Table: 0.0.0.0/0 경로 없음 (완전 격리)
[VPC Endpoint — 인터넷 우회 AWS 서비스 접근]
Private Subnet → S3 (Gateway, 무료)
Private Subnet → ECR (Interface, $0.01/시간)
Private Subnet → CloudWatch Logs (Interface)
Private Subnet → Secrets Manager (Interface)
[모니터링 및 탐지]
VPC Flow Logs → CloudWatch Logs → REJECT 패턴 분석
WAF Logs → S3 → Athena 쿼리 분석
GuardDuty → Flow Logs + CloudTrail ML 분석 → 위협 Findings

실무 최소 보안 체크리스트 (신규 서비스 배포 시)

Terminal window
# 1. RDS가 퍼블릭 접근 불가인지 확인
aws rds describe-db-instances \
--query 'DBInstances[].{DBId: DBInstanceIdentifier, PubliclyAccessible: PubliclyAccessible}'
# PubliclyAccessible: false 이어야 함
# 2. ECS Security Group이 ALB에서만 인바운드 허용인지 확인
aws ec2 describe-security-groups \
--group-ids sg-ecs-task \
--query 'SecurityGroups[].IpPermissions'
# Source가 sg-alb (IP 범위가 아닌 SG 참조)인지 확인
# 3. ALB에 WAF가 연결되어 있는지 확인
aws wafv2 get-web-acl-for-resource \
--resource-arn arn:aws:elasticloadbalancing:...:loadbalancer/app/prod-alb/...
# WebACL 키가 없으면 WAF 미적용
# 4. HTTP → HTTPS 리다이렉트 설정 확인
aws elbv2 describe-listeners \
--load-balancer-arn arn:aws:elasticloadbalancing:...:loadbalancer/app/prod-alb/... \
--query 'Listeners[?Port==`80`].DefaultActions[].Type'
# "redirect" 이어야 함. "forward"면 HTTP로 노출 중
# 예상 출력 (정상):
# [
# "redirect"
# ]

2025년 신기능 — AWS WAF Bot Control 고급 모드: 2025년에 Bot Control의 AI 기반 봇 탐지 정확도가 크게 향상됐다. 정상 사용자처럼 행동하는 정교한 봇도 행동 패턴 분석으로 탐지할 수 있게 됐다. 단, 고급 모드는 기본 요금($10/백만 요청)보다 추가 비용이 발생하므로 도입 전 비용 분석이 필요하다.