리눅스 기초 시리즈의 영광스러운 90번째 시간입니다! 지난 시간에는 Nginx와 tc를 활용해 서버의 질서를 잡는 '교통 정리' 기술인 트래픽 셰이핑을 배웠습니다. 이제 우리 인프라는 폭주하는 트래픽 앞에서도 침착하게 대응할 수 있는 내구성을 갖추게 되었습니다.
하지만 단순한 '양'의 공세보다 더 무서운 것은 정교하게 설계된 '질'의 공격입니다. SQL 인젝션, 크로스 사이트 스크립팅(XSS) 같은 애플리케이션 계층(L7) 공격은 일반적인 방화벽으로는 막아낼 수 없습니다. 오늘은 클라우드 환경에서 웹 애플리케이션을 타겟으로 한 지능형 공격을 차단하는 최후의 보루, WAF(Web Application Firewall)와 Google Cloud Armor를 저의 경험담과 함께 정리해 보겠습니다.
1. 나의 경험담: "조용히 다가온 SQL 인젝션의 공포"
IT 개발자로 일하며 제가 정성 들여 만든 유튜브 쇼츠 자동화 시스템의 DB가 누군가의 '실험' 대상이 된 적이 있었습니다. 서버의 네트워크 트래픽은 평소와 다름없었는데, DB 로그에는 이상한 쿼리들이 찍히기 시작했죠. 바로 SQL 인젝션 공격이었습니다. 공격자는 제 시스템의 취약점을 찾기 위해 아주 정교하게 조작된 HTTP 요청을 보내고 있었습니다.
당시 보안 사고의 징조를 감지하자마자 극심한 스트레스로 위염이 도졌습니다. 소화가 안 되어 아연과 마그네슘 영양제를 챙겨 먹으며 새벽 내내 로그를 분석했죠. 그때 저를 구원한 것이 바로 Cloud Armor였습니다. 클릭 몇 번과 코드 몇 줄로 미리 정의된 보안 규칙(OWASP Core Rule Set)을 적용하자, 그토록 집요하던 공격 시도들이 '403 Forbidden'이라는 시원한 응답과 함께 입구에서 컷당하기 시작했습니다. 영화 '하빈'의 안중근 의사가 거사를 위해 철저히 은신하듯, 저도 WAF라는 보이지 않는 방패 뒤로 제 소중한 데이터를 완벽히 숨길 수 있었습니다.
2. Before: "L3/L4 방화벽만으로는 부족한 보안"
많은 분이 리눅스의 iptables나 클라우드의 'Security Group'만으로 충분하다고 생각합니다. 하지만 이들은 IP와 포트 번호만 봅니다. 패킷 안에 숨겨진 악의적인 '문장(Payload)'은 읽지 못하죠. 편지 봉투의 주소만 보고 내용물에 독극물이 든 줄은 모르는 것과 같습니다.
전통적인 보안의 한계 (Before):
# 방화벽: "80번 포트 열려있네? 통과!"
공격자 요청: GET /login?user=' OR '1'='1' --
애플리케이션: "어? '1'='1'은 참이니까 로그인을 시켜줄게!"
결과: 데이터 유출 및 시스템 장악
"방화벽은 정상인데 왜 뚫린 거야?"
(▲ Before: 문지기가 신분증(IP)만 확인하고 가방 안의 위험물(SQL Injection)은 검사하지 않는 허술한 보안 상태였습니다.)
3. Action: Terraform으로 Google Cloud Armor 보안 정책 선언하기
현대적인 보안은 수동 클릭이 아니라 코드로 관리되어야 합니다. Terraform을 사용하여 가장 치명적인 공격인 SQL 인젝션과 XSS를 자동으로 차단하는 Cloud Armor 정책을 구성해 보겠습니다.
WAF 보안 정책 설정 (cloud_armor.tf):
resource "google_compute_security_policy" "waf_policy" {
name = "youtube-bot-waf-policy"
description = "SQLi and XSS protection"
Rule 1: SQL Injection 차단 (OWASP pre-defined rule)
rule {
action = "deny(403)"
priority = "1000"
match {
expr {
expression = "evaluatePredefinedExpr('sqli-v33-stable')"
}
}
description = "Block SQL Injection"
}
Rule 2: Cross-site Scripting(XSS) 차단
rule {
action = "deny(403)"
priority = "1010"
match {
expr {
expression = "evaluatePredefinedExpr('xss-v33-stable')"
}
}
description = "Block XSS"
}
Default Rule: 그 외 모든 트래픽 허용
rule {
action = "allow"
priority = "2147483647"
match {
versioned_expr = "SRC_IPS_V1"
config {
src_ip_ranges = ["*"]
}
}
description = "Default allow"
}
}
(▲ Action: 코드가 적용되는 순간, 구글의 거대한 엣지 네트워크가 제 서버 대신 패킷을 일일이 검사합니다. 위험한 패턴이 발견되면 제 서버에 도달하기도 전에 차단됩니다.)
4. After: "심층 방어로 완성된 무결점 보안"
WAF를 도입한 뒤 제 인프라는 '안심'을 넘어 '확신'의 단계로 접어들었습니다.
가져온 혁신적인 변화들:
- 비즈니스 연속성 보장: 이제 공격이 들어와도 서버의 로직(CPU/DB)에 부하가 걸리지 않습니다. WAF가 앞에서 대신 맞아주기 때문이죠.
- 컴플라이언스 준수: 정보보안 인증에서 가장 중요하게 보는 L7 보안 체계를 갖춤으로써 대외적인 신뢰도를 확보했습니다.
- 실시간 보안 가시성: 어떤 IP에서 어떤 패턴으로 공격을 시도했는지 대시보드에서 한눈에 파악할 수 있어, 추후 대응이 매우 용이해졌습니다.
5. 네트워크 방화벽 vs WAF 비교
| 구분 | 네트워크 방화벽 (L3/L4) | WAF (L7) |
| 검사 대상 | IP 주소, 포트, 프로토콜 | HTTP 헤더, 페이로드, 쿠키, URL |
| 주요 차단 공격 | 비인가 포트 접근, DDoS | SQLi, XSS, CSRF, 세션 하이재킹 |
| 동작 원리 | 패킷 필터링 | 콘텐츠 분석 및 패턴 매칭 |
| 비유 | 아파트 단지 입구 차단기 | 현관문 앞 지문 인식 보안 시스템 |
6. 마치며: 보안은 도구가 아니라 '태도'입니다.
리눅스 기초 90단계를 거치며 우리는 이제 시스템을 구축하고 운영하는 것을 넘어, 그 가치를 지키는 법을 배웠습니다. WAF와 Cloud Armor는 단순한 방어 도구가 아니라, 우리가 공들여 쌓은 디지털 자산에 대한 **'존중'**의 표현입니다. 완벽한 코드는 없을지라도, 완벽한 방패를 세우려는 노력은 멈추지 말아야 합니다.
오늘의 인사이트: "가장 훌륭한 수비는 공격자가 당신의 시스템에 발을 들이기 전에 그 의지를 꺾어버리는 것이다."
90번째 이야기를 마칩니다. 이제 우리 인프라는 그 어떤 창도 막아낼 수 있는 무적의 방패를 갖췄습니다. 다음 시간에는 리눅스 서버 운영의 화룡점정, '자동화의 자동화: Ansible과 AWX로 구현하는 에이전트리스 서버 통합 관리'에 대해 다뤄보겠습니다.
이 글이 여러분의 소중한 데이터를 지키는 데 영감을 주었나요? 혹시 Cloud Armor 적용 후 정상적인 사용자가 차단되는 '오탐(False Positive)' 문제로 고민 중이신가요?
정상 트래픽은 살리고 공격만 골라내는 'WAF 룰 튜닝 및 예외 처리 가이드'를 다음 포스팅 부록으로 준비해 드릴까요?