배경#

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/startVQA 챌린지 토큰 발급
POST /ai/challenge/verify챌린지 응답 검증
POST /ai/telemetry/ingest브라우저 텔레메트리 수집
POST /ai/precheck대기열 진입 전 사전 검증

판정 액션#

액션HTTP 응답설명
NONE200정상 통과
CHALLENGE428VQA 챌린지(Catch Ball 미니게임) 요구
THROTTLE200 + 지연T1: 200ms / T2: 1800ms 지연
GATE429일시 차단
BLOCK403영구 차단 + 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"

관측성#

항목설정
MetricsPrometheus :9090 (요청 수, 지연, 판정 분포)
TracesOpenTelemetry → Collector → Tempo
Logs구조화 JSON → Loki

정리#

구성요소언어역할담당
Authz AdapterGoEnvoy ↔ AI 브릿지, IP 관리, 토큰 검증인프라 (본인)
AI Defense APIPython행동 분석, 봇 판정, 챌린지 발급AI 팀
EnvoyFilterYAMLext_authz 연동, 경로 필터링인프라 (본인)
Helm ChartsYAML배포 설정, 환경별 values인프라 (본인)

Istio의 ext_authz 확장 포인트를 활용하여 앱 코드 수정 없이 Mesh 레벨에서 AI 봇 탐지를 투명하게 적용한 구조다. Fail-Open 정책으로 가용성을 보장하면서, Critical API만 선별 평가하여 지연을 최소화했다.


참고 레포#