Istio ext_authz Adapter 설계 및 구현
배경#
AI 방어팀이 실시간 봇 탐지와 사후 분석 처리 두 가지를 구현해야 했는데, 앱 코드에 직접 넣으면 모든 서비스에 SDK를 심어야 하고 유지보수가 어려웠다. Istio의 ext_authz 확장 포인트를 활용하면 앱 코드 수정 없이 Mesh 레벨에서 투명하게 요청을 가로채서 AI로 보낼 수 있어서, 이 방식을 AI 팀에 제안했고 합작으로 개발했다.
역할 분담#
| 담당 | 작업 |
|---|---|
| 인프라 (본인) | Istio ext_authz 연동 설계, Go gRPC 어댑터 개발, EnvoyFilter 작성, Helm 배포 구성 |
| AI 팀 | Critical API 선정, 판정 스펙 설계, AI Defense API(Python FastAPI) 개발, 행동 분석 엔진 |
핵심 아이디어: Envoy가 모든 요청을 이미 프록시하고 있으니까, 거기에 ext_authz hook을 걸어서 AI 판정을 받자.
아키텍처#
전체 요청 흐름#
[브라우저]
↓ HTTPS
[Istio IngressGateway (Envoy)]
↓ ext_authz gRPC (Critical API만)
[Authz Adapter (Go :9001)]
↓ POST /ai/evaluate
[AI Defense API (Python :8000)]
↓ Redis (세션/블랙리스트)
↓ Brain Decision Engine
↓
응답: NONE | CHALLENGE | THROTTLE | BLOCK
↓
[Authz Adapter]
├─ NONE → 200 (통과)
├─ CHALLENGE → 428 (챌린지 요구)
├─ THROTTLE → 200 + 지연
└─ BLOCK → 403 + Redis 블랙리스트 등록
↓
[Envoy → Backend API]
방어 계층 구조#
Layer 1: CloudFront + AWS WAF (Edge - L7 DDoS, 대량 차단)
Layer 2: Istio EnvoyFilter WAF (Mesh - SQLi/XSS/CmdInj 탐지)
Layer 3: Istio Rate Limiting (Mesh - 경로별 요청 제한)
Layer 4: ext_authz + AI Defense (Mesh - 행동 기반 봇 탐지) ← 이 글
Authz Adapter (Go)#
역할#
Istio의 ext_authz 프로토콜을 구현한 Go gRPC 서버. Envoy와 AI Defense API 사이의 브릿지 역할을 한다.
핵심 기능#
1. Envoy ext_authz gRPC 서버#
// Envoy가 요청마다 gRPC로 호출
func (h *Handler) Check(ctx context.Context, req *authv3.CheckRequest) (*authv3.CheckResponse, error) {
// 1. 요청 헤더에서 IP, 경로, X-Bot-Token 추출
// 2. 화이트리스트 확인 (팀 IP)
// 3. 블랙리스트 확인 (Redis DB 5)
// 4. AI Defense API 호출
// 5. 결과에 따라 허용/차단/챌린지 응답
}
2. Critical API 필터링#
모든 요청을 AI에 보내면 비용/지연이 크므로, 티켓팅 핵심 API 7개만 평가한다:
/api/queue/entry ← 대기열 진입
/api/seat/select ← 좌석 선택
/api/payment/process ← 결제 처리
/api/booking/confirm ← 예매 확정
/api/user/signup ← 회원가입
/api/auth/login ← 로그인
/api/order/create ← 주문 생성
나머지 경로는 ext_authz를 거치지 않고 바로 통과한다.
3. IP 블랙리스트/화이트리스트 (Redis)#
Redis DB 3: CDN Edge 블랙리스트 (Lambda가 관리, TTL 30일)
Redis DB 5: 실시간 블랙리스트 (Adapter가 관리, TTL 7일)
- BLOCK 판정 시 Redis DB 5에 IP 등록 → 이후 요청은 AI 호출 없이 즉시 차단
- 팀원 IP 22개는 화이트리스트로 항상 통과
4. X-Bot-Token 검증#
프론트엔드(Next.js, Vercel)에서 getBotToken()으로 X-Bot-Token을 생성하여 요청 헤더에 포함시키고, Adapter가 이를 검증한다.
[프론트엔드 (Next.js)]
→ getBotToken()으로 X-Bot-Token 생성
→ 요청 헤더: X-Bot-Token: <token>
↓
[Authz Adapter]
→ 토큰 유효성 검증
→ 없거나 유효하지 않으면 → 403
5. Fail-Open 정책#
AI Defense API가 응답하지 않으면(타임아웃 800ms) 요청을 통과시킨다. 보안보다 가용성을 우선한 설계 — 티켓팅 오픈 시점에 방어 시스템 장애로 정상 사용자가 차단되면 안 되기 때문.
AI Defense API (Python)#
AI 팀이 개발한 FastAPI 기반 봇 탐지 엔진. 인프라 관점에서의 연동 구조를 정리한다.
API 엔드포인트#
| 엔드포인트 | 역할 |
|---|---|
POST /ai/evaluate | 요청 평가 → 행동 판정 (Adapter가 호출) |
POST /ai/challenge/start | VQA 챌린지 토큰 발급 |
POST /ai/challenge/verify | 챌린지 응답 검증 |
POST /ai/telemetry/ingest | 브라우저 텔레메트리 수집 |
POST /ai/precheck | 대기열 진입 전 사전 검증 |
판정 액션#
| 액션 | HTTP 응답 | 설명 |
|---|---|---|
| NONE | 200 | 정상 통과 |
| CHALLENGE | 428 | VQA 챌린지(Catch Ball 미니게임) 요구 |
| THROTTLE | 200 + 지연 | T1: 200ms / T2: 1800ms 지연 |
| GATE | 429 | 일시 차단 |
| BLOCK | 403 | 영구 차단 + IP 블랙리스트 |
세션 상태 관리#
Redis DB 0: 세션 상태
- 사용자별 요청 이력
- 행동 패턴 누적
- 봇 신뢰도 점수
Redis DB 5: 블랙리스트
- BLOCK 판정된 IP
- TTL 7일
Istio 연동 (EnvoyFilter)#
ext_authz 클러스터 정의#
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: ext-authz-cluster
namespace: istio-system
spec:
configPatches:
- applyTo: CLUSTER
patch:
operation: ADD
value:
name: authz-adapter
type: STRICT_DNS
connect_timeout: 0.8s
lb_policy: ROUND_ROBIN
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options: {}
load_assignment:
cluster_name: authz-adapter
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: authz-adapter.staging-ai.svc.cluster.local
port_value: 9001
Lua 경로 매칭 + ext_authz 트리거#
- applyTo: HTTP_FILTER
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.lua
typed_config:
inlineCode: |
function envoy_on_request(request_handle)
local path = request_handle:headers():get(":path")
-- Critical API 경로만 ext_authz 트리거
if matches_critical_path(path) then
request_handle:headers():add("x-need-authz", "true")
end
end
배포 구성#
Helm Values#
# values-authz-adapter.yaml
replicaCount: 2
image:
repository: ghcr.io/goorm-gongbang/authz-adapter
ports:
grpc: 9001
metrics: 9090
env:
AI_DEFENSE_URL: "http://ai-defense.staging-ai.svc.cluster.local:8000/ai/evaluate"
AI_DEFENSE_TIMEOUT: "800ms"
REDIS_ADDR: "redis.staging-data.svc.cluster.local:6379"
OTEL_ENABLED: "true"
관측성#
| 항목 | 설정 |
|---|---|
| Metrics | Prometheus :9090 (요청 수, 지연, 판정 분포) |
| Traces | OpenTelemetry → Collector → Tempo |
| Logs | 구조화 JSON → Loki |
정리#
| 구성요소 | 언어 | 역할 | 담당 |
|---|---|---|---|
| Authz Adapter | Go | Envoy ↔ AI 브릿지, IP 관리, 토큰 검증 | 인프라 (본인) |
| AI Defense API | Python | 행동 분석, 봇 판정, 챌린지 발급 | AI 팀 |
| EnvoyFilter | YAML | ext_authz 연동, 경로 필터링 | 인프라 (본인) |
| Helm Charts | YAML | 배포 설정, 환경별 values | 인프라 (본인) |
Istio의 ext_authz 확장 포인트를 활용하여 앱 코드 수정 없이 Mesh 레벨에서 AI 봇 탐지를 투명하게 적용한 구조다. Fail-Open 정책으로 가용성을 보장하면서, Critical API만 선별 평가하여 지연을 최소화했다.
참고 레포#
- 202-goormgb-authz-adapter — Go gRPC ext_authz 어댑터
- 201-goormgb-ai — AI Defense API (Python FastAPI)