[AWS-Security] 6.3. AWS 웹 애플리케이션 방화벽으로 악성 트래픽 차단
1. AWS WAF
1.1. 기존 방화벽의 한계와 WAF의 필요성
사용자가 짧은 메시지(최대 140자)를 업로드하는 트위터와 같은 웹 사이트를 운영한다고 가정한다.
- 정상 요청 : 일반 사용자는 서버에 아주 작은 크기(최대 1KB)의 HTTP 요청을 보낸다.
- 공격 상황 (Dos) : 악의적인 공격자가 작정하고 1GB가 넘는 큰 데이터를 서버에 밀어넣는다. 그럼 이 거대한 데이터를 처리하느라 과부하가 걸려 다운될 것이다. (DoS 공격의 한 형태)
한계 : 공격자가 정상적인 포트(80, 443)와 정상적인 IP로 접속했기 때문에, Security Group이나 NACL은 이 공격을 막아내지 못한다.
- 해결책 : HTTP 요청의 내용물(크기, 본문 내용 등)까지 뜯어보고 필터링할 수 있는 AWS WAF가 사용된다.
1.2. 실습 1단계: WAF 규칙(Rule) 생성
“요청 본문(Body)의 크기가 1KB(1,000 Byte)보다 크면 차단”이라는 구체적인 규칙을 size_contraint_rules.json이라는 파일로 작성한다.
- size_constraint_rules.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// 페이로드 크기를 1,000바이트로 제한하는 WAF 규칙 [{ "Name": "PayloadSizeConstraintRule", "Priority": 1, // 낮은 숫자(우선순위)가 먼저 평가 "Statement": { "SizeConstraintStatement": { "FieldToMatch": { "Body": {} // 검사할 대상이 '요청의 본문(Body)'임을 명시 }, "ComparisonOperator": "GT", // '크다(Greater Than)'라는 비교 연산자 "Size": 1000 // 크기 임계값을 1,000바이트로 설정 } }, "Action": { "Block": {} // 이 규칙에 걸리면(1000바이트 초과 시) 요청을 '차단(Block)' }, "VisibilityConfig": { // CloudWatch에 차단 로그(지표)를 남기기 위한 설정 "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "PayloadSizeConstraintRule" } }]
1.3. 실습 2단계: 신규 웹 ACL 생성 및 적용
위에서 생성한 규칙 파일(size_constraint_rules.json)을 통해, 실제 방화벽 역할을 할 ‘웹 ACL’을 생성한다.
1
2
3
4
5
6
7
8
# AWS WAF에서 신규 웹 ACL 생성
$ aws wafv2 create-web-acl \
--name SizeConstraintWebAcl \
--scope REGIONAL \ # ALB나 API Gateway에 붙일 때는 'REGIONAL', CloudFront에 붙일 때는 'CLOUDFRONT'
--default-action "Allow={}" \ # 기본적으로 허용(Allow) (차단 규칙에 걸리지 않는 이외 경우)
--description "Blocks requests with BODY > 1KB" \
--visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=TestWebAclMetrics \
--rules file://size_constraint_rules.json # 1단계에서 생성한 규칙 파일
1.4. WAF 적용 대상의 차이점
- Security Group이나 NACL은 EC2 인스턴스나 서브넷에 직접 연결해서 사용한다.
- 하지만, WAF(웹 ACL)은 인스턴스에 직접 연결할 수 없다.
- 애플리케이션의 맨 앞단에서 트래픽을 받아주는 CloudFront(CDN), ALB(애플리케이션 로드밸런서), API Gateway에 연결하여 사용해야 한다.
2. AWS 관리형 규칙
2.1. 관리형 규칙이란
- AWS 또는 AWS Marketplace의 제휴 공급사(Fortinet, Cyber Security Cloud 등)가 대신 생성하고 유지 관리해 주는 방화벽 규칙의 집합이다.
- 주로 특정 공격 집합을 만들어 진다. (Windows 운영체제 전용 규칙, WordPress 애플리케이션 전용 규칙, OWASP Top 10 방어용 규칙 등)
2.2. 관리형 규칙 추가 실습
여기서는 AWS의 알려진 악의적인 입력(Known Bad Inputs) 관리형 규칙 그룹을 추가한다.
2.2.1. 1단계: 사용 가능한 관리형 규칙 찾기
터미널에서 list-available-managed-rule-groups 명령을 통해 사용하려는 규칙 그룹의 정확한 이름과 벤더사명을 확인한다.
1
2
3
4
5
6
7
8
$ aws wafv2 list-available-managed-rule-groups --scope REGIONAL
# 응답(Response) 예시 중 일부
{
"VendorName": "AWS",
"Name": "AWSManagedRulesKnownBadInputsRuleSet",
"Description": "Contains rules that allow you to block request patterns that are known to be invalid..."
}
2.2.2. 2단계: 규칙 구성 파일(JSON) 작성
찾아낸 벤더사명(“AWS”)과 규칙 이름(“AWSManagedRulesKnownBadInputsRuleSet”)을 사용하여 managed_rules_configuration.json이라는 구성 파일을 생성한다.
- managed_rules_configuration.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 관리형 규칙 그룹을 참조하는 WAF 규칙 구성 [{ "Name": "EnableAWSManagedRuleGroup", "Priority": 1, "Statement": { "ManagedRuleGroupStatement": { // 이전 단계에서 찾은 벤더사명 및 규칙 이름을 사용합니다. "VendorName": "AWS", "Name": "AWSManagedRulesKnownBadInputsRuleSet" } }, "VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "ManagedRuleGroupStatement" } }]
2.2.3. 새 웹 ACL 생성
작성한 구성 파일을 사용하여 새 웹 ACL을 생성한다. 생성한 새 웹 ACL이 적용되면, 알려진 악의적인 입력 요청을 알아서 차단해 준다.
1
2
3
4
5
6
7
8
# 기존 규칙 구성 파일을 사용해 웹 ACL 생성
$ aws wafv2 create-web-acl \
--name ManagedRuleGroupWebAcl \
--scope REGIONAL \
--default-action "Allow={}" \
--description "Enables one of the AWS Managed Rule Groups" \
--visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=TestWebAclMetrics \
--rules file://managed_rules_configuration.json # 2단계에서 만든 JSON 파일
2.2.4. AWS WAF용 AWS 관리형 규칙 그룹
| 관리형 규칙 그룹 이름 | 주요 방어 목적 (설명) |
|---|---|
| CommonRuleSet | OWASP 간행물 및 CVE에 설명된 광범위한 취약점 악용 방어 (가장 일반적) |
| AdminProtectionRuleSet | 노출된 관리 페이지에 대한 외부 접근 차단 |
| KnownBadInputsRuleSet | 유효하지 않거나 취약점으로 악용되는 요청 패턴 차단 |
| SQLiRuleSet | SQL 인젝션 공격 같은 데이터베이스 악용 방지 |
| Linux/Unix/Windows/PHP/WordPress | 각 특정 운영체제나 애플리케이션(예: WordPress) 환경에 특화된 취약점 악용 방어 |
| AmazonIpReputationList | 봇(Bot)이나 기타 위협과 관련된 소스(악성 IP) 차단 |
이외에도 AWS Marketplace에서 제휴 공급사(보안 저문 기업)가 제공하는 더욱 고도화된 규칙 그룹을 구독하여 사용할 수도 있다.
2.3. AWS WAF 요금 구조
- 웹 ACL 자체 비용 : 월 5달러
- 규칙(Rule) 추가 비용 : 각 규칙당 월 1달러 (관리형 규칙 그룹도 1개당 월 1달러로 계산됨)
- 트래픽 처리 비용 : 웹 ACL에서 처리한 100만 건당 0.6달러 부과
- Marketplace 추가 비용 : 제휴 공급사의 관리형 규칙을 쓸 경우 해당 공급사가 정한 추가 요금이 청구됨
보다 최신 비용 정보를 확인하려면, AWS 요금 계산기 웹 사이트에서 요금 계산기를 이용할 수 있다.
- https://aws.amazon.com/waf/pricing
- https://calculator.aws/#/
3. 사용자 지정 AWS WAF 규칙으로 실제 공격 차단
3.1. 활용 사례 1: AWS WAF를 사용한 처리율 제한 (Rate Limiting)
소셜 미디어 웹 사이트에 평소 1,000 RPM(분당 요청 수)의 트래픽이 들어오는데, 갑자기 공격자가 10,000 RPM을 쏟아부어 서비스 거부(DoS) 상태를 만들었다고 가정한다.
- 해결책 : WAF의 처리율 제한(Rate limiting) 기능을 사용하여, 각 IP 주소가 5분 동안 보낼 수 있는 최대 요청 수를 제한한다. (예: 5분 당 100개 제한)
- 효과 : 일반 사용자는 5분 동안 100번이나 새로고침할 일이 없으므로 전혀 영향을 받지 않지만, 공격자의 무자비한 요청은 100개 이후 모든 WAF 단에서 차단된다.
[구현 단계]
- 규칙 정의 (JSON 파일 작성)
- rate_limit_rules.json 파일을 생성한다. SizeConstraint 대신 RateBasedStatement를 사용한다.
rate_limit_rules.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// 처리율 제한 WAF 규칙은 IP 주소별로 5분당 100개의 요청으로 제한 [{ "Name": "rate-limit-rule", "Priority": 1, "Statement": { "RateBasedStatement": { "Limit": 100, // 5분 동안 단일 IP 주소에서 100개의 요청이 있을 때 일치하도록 설정 "AggregateKeyType": "IP" } }, "Action": { "Block": {} // 제한 초과 시 차단 }, "VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "rate-limit-rule" } }]
- 웹 ACL 생성 및 연결
1 2 3 4 5 6 7 8 9 10 11 12 13
# 기존 규칙 파일을 사용해 AWS WAF에서 웹 ACL 생성 $ aws wafv2 create-web-acl \ --name RateLimitWebAcl \ --scope REGIONAL \ --default-action "Allow={}" \ --description "Rate limit for social media site" \ --visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=TestWebAclMetrics \ --rules file://rate_limit_rules.json # WAF 웹 ACL을 API Gateway 단계와 연결 $ aws wafv2 associate-web-acl \ --web-acl-arn "arn:aws:waf:us-east-1:123456789012:web-acl-123" \ --resource-arn "arn:aws:apigateway:us-east-1::/restapis/abc123/stages/production" # ALB를 쓴다면 ALB의 ARN을 입력
3.2. 활용 사례 2: 악성 봇을 잡는 AWS WAF 허니팟
악의적인 클롤러가 내 웹 사이트의 콘텐츠를 무단으로 긁어가는(스크래핑) 것을 차단하고 싶다.
허니팟(Honeypot)은 악의적인 사용자가 가짜 리소스에 접근하도록 유인해 식별하고 차단하는 함정이다. 
- 웹 사이트에 일반 사용자는 절대 누를 수 없는 숨겨진 가짜 링크(허니팟)를 생성한다.
- 나쁜 봇은 숨겨진 링크나 robots.txt가 금지한 링크를 찾아내서 클릭한다.
- 이 함정 링크를 누르는 순간 Lambda 함수가 실행되어 해당 봇의 IP를 WAF의 차단 목록에 등록한다.
- 악성 봇의 모든 요청은 WAF에 의해 영구 차단된다.
[구현 단계]
- 차단할 IP를 담을 IP Set과 웹 ACL 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
# AWS WAF에서 IP 집합 생성
$ aws wafv2 create-ip-set \
--name "MyIpSet" \
--scope REGIONAL \
--ip-address-version IPV4 \
--addresses 192.0.2.0/32 # 초기화를 위해 가짜 IP를 하나 등록
# IP 집합 내 IP의 요청을 차단하는 WAF 규칙 (honeypot_rules.json)
# (이전과 형태는 같고 "IPSetReferenceStatement"를 사용하여 방금 만든 IP Set의 ARN을 참조하도록 작성)
# AWS WAF에서 웹 ACL 생성
$ aws wafv2 create-web-acl ... --rules file://honeypot_rules.json
# (생성 후 associate-web-acl로 사이트에 연결)
- API Gateway & Lambda 생성 (가짜 링크를 만들고, 누군가 접속하면 IP를 차단 목록에 등록하는 Lambda 함수 연결)
1
2
3
4
# 허니팟에 대한 API Gateway 엔드포인트 생성
$ aws lambda create-function ... --function-name honeypot-lambda ...
$ aws apigateway create-resource --path-part 'totally-not-a-honeypot' ... # 함정 경로 생성
$ aws apigateway put-integration ... --uri aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:.../invocations # Lambda 연결
- Lambda 파이썬 코드 작성 (차단 로직)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 호출 IP 주소를 AWS WAF IPSet에 등록하는 파이썬 Lambda 코드
import boto3
def register_ip_address(event, context):
# 1. API Gateway를 통해 들어온 요청 헤더에서 봇의 실제 IP 추출
source_ip = event['headers']['X-Forwarded-For'].split(',')[0].strip()
# 2. WAF 클라이언트를 열고 IP Set을 업데이트(차단 목록에 추가)
waf_client = boto3.client('wafv2')
waf_client.update_ip_set(
IPSetId=os.environ['IPSetId'],
...,
Updates=[{
'Action': 'INSERT',
'IPSetDescriptor': { 'Type': 'IPV4', 'Value': source_ip + '/32' } # 봇의 IP를 차단 목록에 삽입
}]
)
- 웹 사이트 배포
robots.txt
1 2 3
# robots.txt 파일 샘플 User-agent: * Disallow: /totally-not-a-honeypot
실제 정상적인 사용자는 볼 수 없도록 링크 없음 표시
1
<a href="/totally-not-a-honeypot" rel="nofollow" style="display:none">Secret Link Text</a>
4. AWS WAF를 사용하는 이유
Q1. 이것은 웹 사이트(또는 웹 애플리케이션)인가?
- No : WAF는 HTTP/HTTPS ‘웹 트래픽’을 이해하고 필터링하도록 특별히 설계된 방화벽이다. 웹 애플리케이션이 아니라면 WAF는 올바른 선택이 아니다.
- Yes : 다음 질문으로 넘어간다.
Q2. 애플리케이션 프런트엔드가 API Gateway, CloudFront 또는 ALB인가?
- No : WAF는 오직 이 세 가지 서비스 앞단에만 연결해서 사용할 수 있으며, EC2 인스턴스에 직접 연결할 수 없다.
(다만, 이 세 가지 리소스는 현대 웹 아키텍처의 필수 요소이므로 장기적인 도입을 고려하는 것이 좋다.) - Yes : 이제 AWS WAF를 사용해 애플리케이션을 보호할 수 있다.
Q3. 애플리케이션이 ‘AWS 관리형 규칙 그룹’ 중 하나에 적합한가?
WAF를 도입하기로 했다면, 가장 먼저 ‘관리형 규칙’부터 검토하는 것이 좋다. (다른 방화벽에 비해 매우 저렴한 비용으로 강력한 보안을 제공)
- Yes : AWS에서 제공하는 규칙을 활성화한다.
- 예시 비용: 매월 500만 개의 요청을 처리하는 웹사이트에
AWSManagedRulesCommonRuleSet(가장 일반적인 웹 공격 방어)을 적용하면 한 달 비용이 10달러 미만이다. - 심층 방어: SQL 데이터베이스를 사용하는 경우, 앱 내부에서 입력을 검증하더라도 혹시 모를 실수에 대비해
AWSManagedRulesSQLiRuleSet을 추가하면 이중 방어가 가능하다.
- 예시 비용: 매월 500만 개의 요청을 처리하는 웹사이트에
Q4. AWS WAF에 대한 추가적인 관리형 규칙을 찾고 있는가?
- Yes : AWS 기본 제공 규칙 외에 더 전문적인 방어가 필요하다면, AWS Marketplace를 통해 제휴 공급사(보안 전문 기업)가 만든 세밀한 관리형 규칙 그룹을 찾아 구독할 수 있다.
Q5. 여전히 방어하고 싶은 ‘추가 공격 벡터(경로)’가 있는가?
관리형 규칙으로도 방어되지 않는 특수한 보안 포인트가 있을 수 있다.
- Yes : 이때 비로소 앞 절(6.2.2)에서 다룬 ‘사용자 지정 WAF 규칙’을 직접 생성한다. (예: 5분당 100회 요청 제한으로 DoS 막기, 허니팟으로 나쁜 봇 차단하기 등)
- No : 설정이 완료되었다. 애플리케이션이 안전하게 보호된다.
초기 도입은 저렴하고 편리한 ‘관리형 규칙(기본 제공 -> 마켓플레이스)’으로 시작하고, 부족한 부분만 ‘사용자 지정 규칙’으로 보완하는 것이 가장 현명한 전략이다. 만약 WAF가 제공하는 기능으로도 원하는 보안 요구사항을 충족하지 못한다면, ‘제휴 공급사의 다른 유형 방화벽’을 고려해야 한다.

