이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
- Gateway, WAF, load balancer, service mesh는 어떤 보안 책임을 맡고 무엇을 맡지 못하는가?
- 인프라에서 차단한 요청과 애플리케이션에서 거부한 요청을 어떻게 연결해야 하는가?
- X-Forwarded-* header, TLS termination, WAF false positive는 Spring 애플리케이션 책임과 어떻게 만나는가?
개요
Gateway, WAF, load balancer, CDN, service mesh는 애플리케이션 앞에서 공통 보안과 운영 기능을 제공한다. TLS termination, rate limit, IP allowlist, bot mitigation, generic attack detection, routing, request size 제한, 관측이 대표적이다.
하지만 인프라 계층은 애플리케이션의 비즈니스 권한 모델을 모른다. 어떤 사용자가 어떤 주문을 볼 수 있는지, 어떤 고객센터 작업이 승인되었는지, 어떤 결제 상태 전이가 가능한지는 서버 코드와 데이터가 판단해야 한다.
WAF는 유용한 1차 방어선이지만 false positive와 bypass 가능성이 있다. 따라서 WAF에 막히지 않는 요청도 애플리케이션에서 안전해야 하고, WAF가 막은 요청도 로그와 trace로 조사할 수 있어야 한다.
이 문서의 핵심은 “앞단에서 막아 준다”가 아니라 “앞단과 애플리케이션이 각자의 책임과 로그를 연결한다”는 것이다.
공격 시나리오
- 공격자는 WAF가 보지 못하는 JSON field 조작으로 Mass Assignment를 시도한다.
- Gateway rate limit가 IP 기준만 보니 여러 IP로 credential stuffing을 분산한다.
X-Forwarded-For를 직접 보내 서버가 공격자 IP를 신뢰하게 만든다.- TLS termination 뒤 내부 HTTP 구간에서 민감 header를 가로챈다.
- WAF false positive로 정상 결제가 막히자 운영자가 rule을 전체 비활성화한다.
- gateway route 오타로 internal endpoint가 public internet에 노출된다.
취약한 요청/응답 예시
GET /api/admin/reports HTTP/1.1
Host: api.example.com
X-Forwarded-For: 10.0.0.5
Authorization: Bearer member-tokenif (request.getHeader("X-Forwarded-For").startsWith("10.")) {
return adminReportService.export();
}클라이언트가 보낼 수 있는 header를 내부 IP 증명으로 믿으면 gateway를 우회한 요청에서 권한이 깨질 수 있다.
주제별 핵심 판단
- Gateway는 routing, TLS termination, coarse rate limit, 공통 header 정책을 맡을 수 있다.
- WAF는 generic attack pattern 탐지와 차단을 돕는다.
- 애플리케이션은 인증, 객체 권한, 업무 상태 전이, 입력 의미 검증을 다시 수행한다.
X-Forwarded-*는 신뢰된 proxy에서 온 경우에만 신뢰한다.- WAF false positive는 rule tuning과 예외 범위 관리가 필요하다.
- gateway/WAF log와 application log는 trace id로 연결되어야 한다.
- internal endpoint는 네트워크 격리와 애플리케이션 인증을 모두 고려한다.
개선된 요청/응답 예시
gateway:
trustedProxies=10.0.0.0/8
injectHeaders=X-Request-Id,X-Forwarded-Proto
stripClientHeaders=X-Forwarded-For,X-Internal-Auth@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/api/admin/reports")
public Report export(Authentication authentication) {
audit.record("admin_report_exported", authentication.getName());
return adminReportService.export();
}인프라는 client supplied internal header를 제거하고, 애플리케이션은 role과 업무 권한을 별도로 확인한다.
방어 설계
- 각 계층의 책임 표를 만든다. CDN, WAF, gateway, Spring Security, Service, Repository를 나눈다.
- gateway route inventory와 Spring endpoint inventory를 비교한다.
- trusted proxy 목록을 명시하고 client supplied forwarding header를 제거한다.
- TLS termination 이후 내부 구간 보호 여부를 정한다.
- WAF rule은 detection mode, blocking mode, exception, owner를 관리한다.
- WAF false positive는 전체 rule 비활성화가 아니라 좁은 exception으로 조정한다.
- edge rate limit와 business abuse detection을 분리한다.
- 모든 계층에 같은 trace id를 전달한다.
Spring/HTTP 예시
server:
forward-headers-strategy: framework@Bean
ForwardedHeaderFilter forwardedHeaderFilter() {
return new ForwardedHeaderFilter();
}level=WARN event=waf_request_blocked result=blocked rule=crs-942 provider=waf path=/api/search traceId=918ac2a0
level=WARN event=input_validation_failed result=blocked field=query reason=sql_meta_chars path=/api/search traceId=918ac2a0forwarded header는 trusted proxy 설정과 함께 다뤄야 한다. trace id가 연결되면 WAF와 app log를 같은 사건으로 볼 수 있다.
운영 로그와 감사 지점
level=INFO event=gateway_route_changed result=allowed route=/api/admin/** auth=required reviewer=platform:lee traceId=918ac2a0level=WARN event=waf_rule_exception_added result=allowed rule=crs-942 path=/api/search scope=parameter:q owner=team-search expires=2026-08-01 traceId=918ac2a0- gateway route 변경은 코드 배포처럼 리뷰한다.
- WAF exception에는 scope와 만료일을 둔다.
- trusted proxy 변경은 보안 이벤트로 남긴다.
- edge block과 app deny를 같은 dashboard에서 본다.
- internal endpoint public exposure scan을 정기 실행한다.
실전 판단 기준
- WAF는 business authorization을 모른다.
- IP allowlist는 header spoofing과 proxy 경계를 확인해야 한다.
- false positive가 많으면 운영자가 WAF를 꺼 버릴 위험이 있다.
- gateway와 application의 route 정의가 달라지면 보호 구멍이 생긴다.
- 내부망은 신뢰할 수 있는 단일 경계가 아니다.
- edge rate limit만으로 credential stuffing과 business abuse를 막기 어렵다.
테스트 포인트
- client가 보낸
X-Forwarded-For가 신뢰되지 않는지 확인한다. - gateway route와 Spring endpoint 보호 정책이 일치하는지 확인한다.
- WAF를 우회한 정상 형식의 권한 공격이 애플리케이션에서 거부되는지 확인한다.
- WAF false positive 예외가 특정 path/parameter로 제한되는지 확인한다.
- internal endpoint가 public network에서 접근되지 않는지 확인한다.
- trace id가 gateway, WAF, app log에 모두 남는지 확인한다.
위험 신호!
- “WAF가 있으니 입력 검증 생략”이라고 설명한다.
- client supplied internal header를 서버가 신뢰한다.
- gateway route 변경에 보안 리뷰가 없다.
- WAF rule exception에 owner와 만료일이 없다.
- 내부 API가 인증 없이 network boundary만 믿는다.
- edge log와 app log를 연결할 trace id가 없다.
확인 질문
확인 질문
- Gateway/WAF가 맡을 수 있는 것은 무엇인가?
- 공통 차단, routing, TLS termination, coarse rate limit, generic attack detection, 관측이다.
- 애플리케이션이 다시 확인해야 하는 것은 무엇인가?
- 인증, 객체 권한, 업무 상태 전이, 입력 의미 검증, 감사 로그다.
- WAF false positive는 어떻게 관리해야 하는가?
- rule 전체 비활성화가 아니라 좁은 exception, owner, 만료일, 재검토로 관리한다.