F5 AI Gateway mTLS : NGINX Ingress Controller 연동 구성

이 포스트는 Kubernetes 클러스터에 배포된 NGINX Ingress Controller와 F5 AI Gateway 사이의 통신을 mTLS 구성하는 방법에 관해 설명합니다.
NGINX Ingress Controller의 EgressMTLS policy 리소스를 사용하여 NGINX Ingress Controller와 F5 AI Gateway 서비스 간 통신의 보안을 효과적으로 강화할 수 있습니다.

이 포스트에서는 NGINX Plus Ingress Controller를 사용했지만, EgressMTLS policy를 활용한 mTLS 구성은 NGINX Ingress Controller에서도 사용할 수 있습니다.

mTLS 구성 외에도 F5 AI Gateway와 NGINX Ingress Controller를 통합하여 활용하기 위한 다양한 구성 방법은 F5 AI Gateway Kubernetes NGINX Ingress Controller 통합 포스트를 참고하세요.

목차

1. mTLS란?
2. 버전 정보
3. F5 AI Gateway mTLS 인증서 생성
4. NGINX Ingress Controller, F5 AI Gateway mTLS 설정 적용
5. F5 AI Gateway mTLS 테스트
6. 결론

1. mTLS란?

mTLS(mutual TLS, 상호 TLS)는 클라이언트와 서버가 서로의 신원을 TLS 인증서를 통해 검증하는 보안 통신 방식입니다. 일반적인 TLS에서는 클라이언트가 서버의 인증서를 검증하는 단방향 인증만 수행하지만, mTLS는 클라이언트도 인증서를 제공하여 양방향 인증을 수행합니다.
mTLS의 주요 이점은 다음과 같습니다.

  1. 강화된 보안: 양쪽 모두 신원 확인으로 피싱 및 중간자 공격 방지
  2. 제로 트러스트 아키텍처: “모든 것을 검증하고, 아무것도 신뢰하지 않음” 원칙에 기반한 보안 모델 구현
  3. 데이터 무결성 보장: 통신 중 데이터 변조 방지
  4. 규제 준수: 금융, 의료 등 민감한 데이터를 다루는 산업의 보안 규정 준수 지원
TLS와 mTLS 비교
구분TLS (단방향)mTLS (상호 인증)
인증 방향클라이언트 → 서버 인증클라이언트 ↔ 서버 상호 인증
보안 수준일반적인 암호화 통신양방향 인증으로 더 강력한 보안
사용 예시웹사이트 접속(HTTPS)서비스 간 통신, API 보안

2. 버전 정보

  • Kubernetes: v1.32.2
  • NGINX Plus Ingress Controller: 5.0.0
  • F5 AI Gateway: v1.0.2
  • F5 AI Gateway Helm chart: aigw-0.1.1

3. F5 AI Gateway mTLS 인증서 생성

ai-gateway 네임스페이스에 F5 AI Gateway가 배포되었다 가정하고 진행합니다. 자체 서명 인증서 생성을 통해 mTLS 구성을 진행하겠습니다.

1. CA(Certificate Authority) 인증서, 키 생성
이 인증서는 클라이언트와 서버 인증서를 서명할 수 있는 권한을 가지고 있습니다.

$ openssl genrsa -out ca.key 2048
$ openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 -out ca.crt -subj "/CN=Internal CA"
  • genrsa -out ca.key 2048: 2048비트 RSA 개인 키를 생성합니다.
  • req -x509 -new -nodes -key ca.key -sha256 -days 365 -out ca.crt -subj "/CN=Internal CA": 위에서 생성한 개인 키(ca.key)를 사용해 자체 서명된 CA 인증서를 생성합니다. 이 인증서는 1년 동안 유효합니다.

2. NGINX Ingress Controller의 클라이언트 인증서를 생성합니다.
먼저 클라이언트 개인 키와 인증서를 생성합니다.

$ openssl genrsa -out client.key 2048
$ openssl req -new -key client.key -out client.csr -subj "/CN=nginx-ingress-client"
  • genrsa -out client.key 2048: 2048비트 RSA 개인 키를 생성합니다.
  • req -new -key client.key -out client.csr -subj "/CN=nginx-ingress-client": 위에서 생성한 개인 키(client.key)를 사용해 클라이언트 인증서 서명 요청 (CSR) 파일을 생성합니다. 이 CSR은 나중에 CA 인증서로 서명됩니다.

클라이언트 인증서 서명 요청(client.csr)을 CA 인증서(ca.crt)로 서명하여 최종적인 클라이언트 인증서(client.crt)를 생성합니다.

$ openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365 -sha256
  • x509 -req -in client.csr: 클라이언트 CSR 파일을 기반으로 서명된 인증서를 생성합니다.
  • -CA ca.crt -CAkey ca.key: 서명 과정에서 사용할 CA 인증서(ca.crt)와 개인 키(ca.key)를 지정합니다.
  • -CAcreateserial: 서명된 인증서의 시리얼 번호를 생성합니다.
  • -out client.crt: 서명된 클라이언트 인증서를 client.crt로 저장합니다.

3. AI Gateway 서버 인증서 생성
이 인증서는 AI Gateway 서버가 신뢰할 수 있는 인증 기관(CA)에서 발급한 것임을 증명합니다.

$ openssl genrsa -out server.key 2048
$ openssl req -new -key server.key -out server.csr -subj "/CN=aigw.ai-gateway.svc.cluster.local"
  • genrsa -out server.key 2048: 2048비트 RSA 개인 키를 생성합니다.
  • req -new -key server.key -out server.csr -subj "/CN=aigw.ai-gateway.svc.cluster.local": AI Gateway 서버의 CSR을 생성합니다. 서버의 Common Name (CN)은 클러스터에 배포된 AI Gateway의 서비스 주소인 aigw.ai-gateway.svc.cluster.local로 설정합니다.

4. 서버 인증서에 대한 SAN 설정 생성
AI Gateway 서버 인증서에 Subject Alternative Name (SAN) 을 설정하여 여러 DNS 이름을 지원하도록 합니다. 이를 통해 인증서가 특정 도메인에만 유효하게 설정됩니다.

$ cat > server_ext.cnf << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = aigw.ai-gateway.svc.cluster.local
EOF
  • subjectAltName: 인증서가 적용될 추가 도메인 이름을 설정합니다. 여기서는 ai-gateway 네임스페이스에 배포된 서비스 이름인 aigw를 대상으로 aigw.ai-gateway.svc.cluster.local 를 설정했습니다.

5. SAN 포함 서버 인증서 서명
서버 CSR을 CA 인증서로 서명하여 최종적인 서버 인증서를 생성합니다.

$ openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -sha256 -extfile server_ext.cnf
  • -extfile server_ext.cnf: SAN을 포함한 추가 설정 파일을 지정하여 서버 인증서에 SAN을 추가합니다.
  • -out server.crt: 서명된 서버 인증서를 server.crt로 저장합니다.

이제 생성한 인증서들을 사용하여 Kubernetes Secret을 생성합니다.

1. NGINX Ingress Controller의 클라이언트 인증서를 aigw-nic-client-tls Secret으로 생성합니다.

$ kubectl create secret tls aigw-nic-client-tls --cert=client.crt --key=client.key -n ai-gateway

# 레이블 설정(생략 가능)
$ kubectl label secrets aigw-nic-client-tls aigw=mtls -n ai-gateway

2. AI Gateway 서버 인증서를 aigw-server-tls Secret으로 생성합니다.

$ kubectl create secret tls aigw-server-tls --cert=server.crt --key=server.key -n ai-gateway

# 레이블 설정(생략 가능)
$ kubectl label secrets aigw-server-tls aigw=mtls -n ai-gateway

3. CA 인증서를 internal-ca Secret으로 생성합니다. nginx.org/ca 타입으로 생성해야 합니다.

apiVersion: v1
kind: Secret
metadata:
  name: internal-ca
  namespace: ai-gateway
  labels:
    aigw: mtls
type: nginx.org/ca
data:
  ca.crt: LS0t...(내용 생략)...S0K

인증서를 사용해 생성한 Secret은 다음과 같습니다.

$ kubectl get secrets -n ai-gateway -l aigw=mtls

NAME                  TYPE                DATA   AGE
aigw-nic-client-tls   kubernetes.io/tls   2      3h26m
aigw-server-tls       kubernetes.io/tls   2      3h26m
internal-ca           nginx.org/ca        1      169m

4. NGINX Ingress Controller, F5 AI Gateway mTLS 설정 적용

1. NGINX Ingress Controller와 F5 AI Gateway 사이의 통신에 mTLS 적용을 위해 EgressMTLS policy를 배포합니다.

apiVersion: k8s.nginx.org/v1
kind: Policy
metadata:
  name: aigw-mtls
  namespace: ai-gateway
spec:
  egressMTLS:
    tlsSecret: aigw-nic-client-tls  # NGINX Ingress Controller의 클라이언트 인증서 secret
    trustedCertSecret: internal-ca  # CA 인증서 secret
    verifyServer: on
    serverName: on
    sslName: aigw.ai-gateway.svc.cluster.local  # AI Gateway 서버 인증서의 SAN(DNS.1) 또는 CN
    protocols: TLSv1.3
$ kubectl apply -f aigw-mtls.yaml -n ai-gateway

2. mTLS 설정이 적용된 NGINX Ingress Controller의 VirtualServer 리소스를 배포합니다.

apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
  name: aigw-mtls
  namespace: ai-gateway
spec:
  host: aigw.example.com
  upstreams:
    - name: aigw
      service: aigw
      port: 80
      connect-timeout: 240s
      read-timeout: 240s
      send-timeout: 240s
      client-max-body-size: 512k
      tls: # upstream 대상 mTLS 활성화(NGINX Ingress Controller - AI GW 통신에 TLS 활성화)
        enable: true
    
  routes:
    - path: /
      policies: # 앞 단계에서 배포한 Policy 리소스 이름 명시
        - name: aigw-mtls
      action:
        proxy:
          upstream: aigw
$ kubectl apply -f aigw-mtls-vs.yaml -n ai-gateway

3. AI Gateway Pod에 생성한 Secret을 통해 인증서를 마운트 합니다.
Helm을 사용해 Kubernetes 클러스터에 F5 AI Gateway를 배포하여, values.yaml의 값을 아래와 같이 수정했습니다.

aigw:
  # -- Enable the core (aigw) application
  enabled: true

...

  tls:
    # -- Enable serving HTTPS for the aigw deployment
    enabled: true

    # -- Name of the secret that contains the TLS data
    # AI Gateway 서버 인증서의 Secret 이름 명시
    secretName: aigw-server-tls

...

  # CA 인증서를 AI Gateway Pod에 마운트
  # -- Additional volume mounts for the aigw deployment
  volumeMounts:
    - name: internal-ca-volume
      readOnly: true
      mountPath: "/etc/internal-ca"

  # -- Additional volumes for the aigw deployment
  volumes:
    - name: internal-ca-volume
      secret:
        secretName: internal-ca
$ helm upgrade aigw oci://private-registry.f5.com/aigw/aigw -f values.yaml

다음과 같은 출력을 확인할 수 있습니다. 인증서, 키 파일의 디렉터리를 확인할 수 있습니다.

* Required: enable TLS in the AIGW configuration, pointing to the certificate `/tls/server.crt` and key `/tls/server.key`

    server:
      ...
      tls:
        enabled: true
        serverCertPath: /tls/server.crt
        serverKeyPath: /tls/server.key

4. AI Gateway의 설정 파일을 수정하여 TLS, mTLS 설정을 적용합니다.

apiVersion: v1
kind: ConfigMap
metadata:
  annotations:
    meta.helm.sh/release-name: aigw
    meta.helm.sh/release-namespace: ai-gateway
  labels:
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/version: v1.0.0
    helm.sh/chart: aigw-0.1.0
  name: aigw-config
  namespace: ai-gateway
data:
  aigw.yaml: |
    version: 1

    server:
      address: :4141
      tls:
        enabled: true
        serverCertPath: /tls/server.crt  # helm upgrade 이후 출력된 인증서 디렉터리 
        serverKeyPath: /tls/server.key
      mtls:
        enabled: true
        clientCertPath: /etc/internal-ca/ca.crt  # values.yaml 파일에서 마운트한 path 지정

    logging:
      level: debug

    routes:
      - path: /v1/chat/completions
        policy: chat-policy
        schema: v1/chat_completions  
        timeoutSeconds: 240
      - path: /v1/models
        policy: chat-policy
        schema: v1/models

    policies:
      - name: chat-policy
        profiles:
          - name: chat-profile

    profiles:
      - name: chat-profile
        models:
          - name: hermes3:8b
          - name: deepseek-r1:1.5b
        services:
          - name: ollama/hermes
            selector:
              type: input.model
              values:
                - hermes3:8b
          - name: ollama/deepseek
            selector:
              type: input.model
              values:
                - deepseek-r1:1.5b

    services:
      - name: ollama/hermes
        type: hermes3:8b
        executor: ollama
        config:
          endpoint: "http://192.168.200.129:11434/api/chat"
      - name: ollama/deepseek
        type: deepseek-r1:1.5b
        executor: ollama
        config:
          endpoint: "http://192.168.200.129:11434/api/chat"

    processors:
      - name: prompt-injection
        type: external
        config:
          endpoint: http://aigw-processors-f5.ai-gateway.svc.cluster.local
          namespace: f5
          version: 1
        params:
          threshold: 0.8
          reject: true

기타 설정 항목에 대한 자세한 설명은 F5 AI Gateway 설정 기초 가이드 포스트를 참고하세요.

설정 적용 후 AI Gateway Pod의 로그에서 TLS, mTLS 설정 적용을 확인할 수 있습니다.

F5 AI Gateway mTLS

NGINX Ingress Controller Pod 내부의 설정 파일에 구성한 설정이 적용된 것을 확인할 수 있습니다.

NGINX Ingress Controller mTLS

5. F5 AI Gateway mTLS 테스트

적용된 설정을 확인하기 위해 테스트 Pod를 실행하여 생성한 클라이언트 인증서/키 파일 및 CA 인증서 파일을 통해 mTLS 적용 여부를 확인하겠습니다.

1. 테스트용 Ubuntu pod를 실행합니다.

$ kubectl run mtls-test --image=ubuntu --namespace=ai-gateway -- sleep 3600

2. 인증서, 키 파일을 Pod로 복사합니다.

kubectl cp ./client.crt ai-gateway/mtls-test:/client.crt
kubectl cp ./client.key ai-gateway/mtls-test:/client.key
kubectl cp ./ca.crt ai-gateway/mtls-test:/ca.crt

3. Pod에 접속합니다.

$ kubectl exec -it -n ai-gateway mtls-test -- bash

4. Pod에 openssl 패키지를 설치합니다.

root@mtls-test:/# apt update && apt install -y openssl

5. openssl s_client로 인증을 시도합니다. aigw:80은 AI Gateway의 Service 이름입니다.

root@mtls-test:/# openssl s_client -connect aigw:80 \
  -cert client.crt -key client.key \
  -CAfile ca.crt \
  -servername aigw.ai-gateway.svc.cluster.local
>   -servername aigw.ai-gateway.svc.cluster.local
CONNECTED(00000003)
depth=1 CN = Internal CA
verify return:1
depth=0 CN = aigw.ai-gateway.svc.cluster.local
verify return:1
---
Certificate chain
 0 s:CN = aigw.ai-gateway.svc.cluster.local
   i:CN = Internal CA
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: May 13 01:58:11 2025 GMT; NotAfter: May 13 01:58:11 2026 GMT


......

SSL handshake has read 1507 bytes and written 2214 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)

......

    0930 - 14 8a ed e3 59 f2 54 a5-33 99 7b 8e bc 2d 38 6d   ....Y.T.3.{..-8m
    0940 - 1c 69 51 89 3d d8 c8 59-82 5e ea 9c 6b cc eb 01   .iQ.=..Y.^..k...
    0950 - 53 00 42 aa 3e 8d 71 97-8a b7 58                  S.B.>.q...X

    Start Time: 1747119853
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: no
    Max Early Data: 0

위와 같이 결과를 확인할 수 있습니다.

Postman을 통해 NGINX Ingress Controller로 요청을 전송하여 AI Gateway를 거쳐 정상적으로 응답을 반환하는 것을 확인할 수 있습니다.

6. 결론

이번 포스트에서는 F5 AI Gateway와 NGINX Ingress Controller 간의 mTLS(mutual TLS) 기반 보안 통신을 구성하는 과정을 단계적으로 설명하였습니다.

NGINX Ingress Controller의 EgressMTLS 정책을 활용하면 AI Gateway와의 트래픽에 대해 클라이언트 인증서를 통한 양방향 인증을 적용할 수 있으며, 이는 다음과 같은 보안적 이점을 제공합니다:

  • 데이터 전송 구간에 대한 강력한 암호화 및 무결성 보장
  • 서비스 간 상호 인증을 통한 신뢰 기반 통신 확보
  • 불특정 외부 서비스로의 오용 또는 비인가 접근 차단

운영 중인 AI 서비스에 강력한 보안이 필요하신가요? NGINX STORE를 통해 문의하여 F5 AI Gateway with NGINX Integration 서비스를 통해 AI 서비스를 보호하세요.

NGINX STORE를 통한 솔루션 도입 및 기술지원 무료 상담 신청

* indicates required