NGINX Gateway Fabric: WAFPolicy로 F5 WAF 정책 적용
NGINX Gateway Fabric은 F5 WAF for NGINX와 연동하여 Gateway API로 구성된 애플리케이션 트래픽에 WAF 저책을 적용할 수 있습니다. WAFPolicy는 Gateway 또는 HTTPRoute와 같은 리소스를 대상으로 적용할 수 있으며, Gateway에 적용한 정책은 해당 Gateway에 연결된 Route에 상속됩니다.
이번 포스트에서는 하나의 Gateway에 두 개의 HTTPRoute를 연결하고 Gateway-level WAFPolicy를 구성합니다. 각 HTTPRoute에는 별도의 WAFPolciy를 구성하지 않고, Gateway에 적용된 공통 WAF 정책이 두 Route에 동일하게 적용되는 구성을 확인합니다.
정상 요청이 각 백엔드 애플리케이션으로 전달되는지 확인한 뒤 XSS 공격 패턴이 포함된 요청을 발생시켜 두 Route에서 동일하게 차단되는지 검증합니다. 이를 통해 여러 애플리케이션 Route가 하나의 Gateway를 공유하는 환경에서 공통 WAF 정책을 적용하는 구성을 살펴봅니다.
목차
1. 실습 목표
2. 환경 구성
3. 기존 NGF 환경 확인
4. 기존 NGF에 WAF 기능 활성화
5. 테스트 애플리케이션 배포
6. Gateway 생성
7. 복수 HTTPRoute 생성
8. WAF policy bundle 준비
8-1. WAF policy definition ConfigMap 생성
8-2. Bundle server 배포
9. Gateway-level WAFPolicy 생성
10. 동일 공격 요청으로 WAFPolicy 상속 검증
11. 결론
1. 실습 목표
- 기존 NGINX Gateway Fabric 환경에서 F5 WAF for NGINX 기능을 활성화합니다.
- 하나의 Gateway에 여러 HTTPRoute를 연결합니다.
- Gateway를 대상으로
WAFPolicy를 적용합니다. - 각 HTTPRoute에는 별도 WAFPolicy를 구성하지 않은 상태에서 Gateway-level 정책이 하위 Route에 적용되는지 확인합니다.
- 정상 요청과 공격 패턴이 포함된 요청을 비교하여 WAF 정책의 동작을 검증합니다.
2. 환경 구성
| 구성 요소 | 버전 |
| NGINX Gateway Fabric | 2.6.5 |
| NGINX Plus | 1.29.8 (r37.0.2) |
| Kubernetes | v1.36.2 |
| Helm | v3.20.0 |
3. 기존 NGF 환경 확인
먼저 GatewayClass가 정상적으로 등록되어 있는지 확인합니다.
$ kubectl get gatewayclass
NAME CONTROLLER ACCEPTED AGEnginx gateway.nginx.org/nginx-gateway-controller True 2d23h
이어서 NGINX Gateway Fabric의 Control Plane Pod 상태를 확인합니다.
$ kubectl get pods -n nginx-gateway
NAME READY STATUS RESTARTS AGEngf-nginx-gateway-fabric-76bcf4cc77-ft6h9 1/1 Running 0 2d23h
Helm으로 설치한 경우 Deployment 상태도 함께 확인할 수 있습니다.
$ kubectl get deployments -n nginx-gateway
NAME READY UP-TO-DATE AVAILABLE AGEngf-nginx-gateway-fabric 1/1 1 1 2d23h
마지막으로 Control Plane에서 사용하는 Service를 확인합니다.
$ kubectl get svc -n nginx-gateway
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEngf-nginx-gateway-fabric ClusterIP 10.108.114.119 <none> 443/TCP 2d23h
4. 기존 NGF에 WAF 기능 활성화
기존 NGINX Gateway Fabric 환경에서 F5 WAF for NGINX를 사용하려면 WAF가 포함된 NGINX Plus 이미지를 사용하고 WAF 기능을 활성화해야 합니다.
F5 WAF for NGINX는 NGINX Plus와 별도의 구독이 필요하며, WAF가 포함된 NGINX Plus 이미지는 private-registry.nginx.com을 통해 제공됩니다.
먼저 private-registry.nginx.com에서 이미지를 가져올 수 있도록 Registry 인증에 사용할 인증서와 key를 준비합니다.
$ mkdir -p /etc/docker/certs.d/private-registry.nginx.com$ cp <path-to-your-nginx-repo.crt> /etc/docker/certs.d/private-registry.nginx.com/client.cert$ cp <path-to-your-nginx-repo.key> /etc/docker/certs.d/private-registry.nginx.com/client.key
Registry 인증 정보를 기반으로 imagePullSecret을 생성한 뒤, 현재 설치된 NGINX Gateway Fabric의 Helm Release 이름을 확인합니다.
$ helm list -n nginx-gateway
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSIONngf nginx-gateway 2 2026-06-19 10:21:38.276932496 +0900 KST deployed nginx-gateway-fabric-2.6.5 2.6.5
Release 이름이 ngf인 경우 다음과 같이 WAF가 포함된 NGINX Plus 이미지를 지정하고 WAF 기능을 활성화합니다.
$ helm upgrade ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \ -n nginx-gateway \ --set nginx.image.repository=private-registry.nginx.com/nginx-gateway-fabric/nginx-plus-f5waf \ --set nginx.plus=true \ --set nginx.config.waf.enable=true \ --set nginx.imagePullSecret=nginx-plus-registry-secret
각 설정의 역할은 다음과 같습니다.
| 설정 | 설명 |
nginx.image.repository | F5 WAF for NGINX가 포함된 NGINX Plus 이미지 지정 |
nginx.plus=true | NGINX Plus Data Plane 사용 |
nginx.config.waf.enable=true | F5 WAF for NGINX 기능 활성화 |
nginx.imagePullSecret | Private Registry 인증에 사용할 Secret 지정 |
정상적으로 업그레이드되면 Helm Release의 Revision이 증가하고 STATUS가 deployed로 표시됩니다.
Pulled: ghcr.io/nginx/charts/nginx-gateway-fabric:2.6.5Digest: sha256:6a799f2a46f78db8790bd6e927ace8ee7699940654f3cee667ceeea465894ee9Release "ngf" has been upgraded. Happy Helming!NAME: ngfLAST DEPLOYED: Fri Jun 19 10:21:38 2026NAMESPACE: nginx-gatewaySTATUS: deployedREVISION: 3TEST SUITE: None
업그레이드 후 Helm values를 확인하여 WAF 관련 설정이 정상적으로 반영되었는지 확인합니다.
$ helm get values ngf -n nginx-gateway
다음과 같이 WAF 활성화와 NGINX Plus 이미지 설정이 확인되어야 합니다.
USER-SUPPLIED VALUES:nginx: config: waf: enable: true image: repository: private-registry.nginx.com/nginx-gateway-fabric/nginx-plus-f5waf imagePullSecret: nginx-plus-registry-secret plus: true
여기까지 구성하면 NGINX Gateway Fabric에서 F5 WAF for NGINX 기능을 사용할 수 있는 상태가 됩니다. 이후 Gateway와 HTTPRoute를 생성하고
WAFPolciy를 연결하여 실제 애플리케이션 트래픽에 WAF 정책을 적용합니다.NGINX Gateway Fabric을 설치할 때, Helm 방식이 아닌 Mainfast 방식을 사용하였다면,
NginxProxy리소스를 수정하여 WAF를 활성화 시킬 수 있습니다.
5. 테스트 애플리케이션 배포
Gateway와 WAFPolicy 동작을 확인하기 위해 서로 다른 두 개의 테스트 애플리케이션을 배포합니다.
각 애플리케이션은 nginxdemos/nginx-hello:plain-text 이미지를 사용하며, 각각 별도의 Deployment와 ClusterIP Service로 구성합니다. 이후 두 Service를 서로 다른 HTTPRoute의 Backeend로 연결합니다.
apps.yaml 파일을 생성하고 다음 내용을 작성합니다.
apiVersion: apps/v1kind: Deploymentmetadata: name: app1spec: replicas: 1 selector: matchLabels: app: app1 template: metadata: labels: app: app1 spec: containers: - name: app1 image: nginxdemos/nginx-hello:plain-text ports: - containerPort: 8080apiVersion: v1kind: Servicemetadata: name: app1spec: selector: app: app1 ports: - name: http port: 80 targetPort: 8080apiVersion: apps/v1kind: Deploymentmetadata: name: app2spec: replicas: 1 selector: matchLabels: app: app2 template: metadata: labels: app: app2 spec: containers: - name: app2 image: nginxdemos/nginx-hello:plain-text ports: - containerPort: 8080apiVersion: v1kind: Servicemetadata: name: app2spec: selector: app: app2 ports: - name: http port: 80 targetPort: 8080
각 Deployment는 Container의 8080/TCP 포트에서 요청을 처리하고, Service는 80/TCP 포트로 요청을 받아 해당 Pod의 8080/TCP 포트로 전달됩니다.
작성한 리소스를 적용합니다.
$ kubectl apply -f apps.yaml
생성된 Deployment, Pod, Service 상태를 확인합니다.
$ kubectl get deployment,pods,svc
정상적으로 배포된 경우 다음과 같이 두 Deployment와 Pod가 실행되고, 각각의 ClusterIP Service가 생성됩니다.
NAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/app1 1/1 1 1 2d23hdeployment.apps/app2 1/1 1 1 2d23hNAME READY STATUS RESTARTS AGEpod/app1-8455b5554c-tqrwx 1/1 Running 0 2d23hpod/app2-657c5d4769-2lml5 1/1 Running 0 2d23hNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/app1 ClusterIP 10.111.215.35 <none> 80/TCP 2d23hservice/app2 ClusterIP 10.96.139.192 <none> 80/TCP 2d23h
두 Service는 이후 생성할 app1-route와 app2-route의 Backend로 사용합니다.
6. Gateway 생성
두 HTTPRoute가 공통으로 연결될 Gateway를 생성합니다.
Gateway는 클라이언트 트래픽이 유입되는 공통 진입점으로 사용되며, 이후 생성할 app1-route와 app2-route가 동일한 Gateawy를 참조하도록 구성합니다. Gateway가 nginx GatewayClass에 연결되면 NGINX Gateway Fabric이 해당 Gateway를 처리할 Data Plane을 구성합니다.
gateway.yaml 파일을 생성하고 다음 내용을 작성합니다.
apiVersion: gateway.networking.k8s.io/v1kind: Gatewaymetadata: name: shared-gatewayspec: gatewayClassName: nginx listeners: - name: http port: 80 protocol: HTTP
주요 설정은 다음과 같습니다.
| 항목 | 설정 | 설명 |
gatewayClassName | nginx | NGINX Gateway Fabric이 관리하는 GatewayClass 지정 |
listeners.name | http | Listener 이름 |
listeners.port | 80 | HTTP 요청을 수신할 포트 |
listeners.protocol | HTTP | Listener에서 사용할 프로토콜 |
작성한 Gateway 리소스를 적용합니다.
$ kubectl apply -f gateway.yaml
Gateway 상태를 확인합니다.
$ kubectl get gateway shared-gateway$ kubectl describe gateway shared-gateway
정상적으로 구성된 경우 Gateway의 Programmed 상태가 True로 표시됩니다.
NAME CLASS ADDRESS PROGRAMMED AGEshared-gateway nginx True 2d23h
kubectl describe 결과에서는 Accepted=True와 Programmed=True 상태를 확인할 수 있습니다.
...Status: Conditions: Message: The Gateway is accepted Reason: Accepted Status: True Type: Accepted Message: The Gateway is programmed Reason: Programmed Status: True Type: Programmed...
Accepted=True는 Gateway 구성이 NGINX Gateway Fabric에 의해 정상적으로 수락되었음을 의미하며, Programmed=True는 해당 구성이 Data Plane에 반영되어 트래픽을 처리할 수 있는 상태임을 나타냅니다.
이후 두 개의 HTTPRoute를 생성하여 shared-gateway에 연결합니다.
7. 복수 HTTPRoute 생성
shared-gateway에 두 개의 HTTPRoute를 연결하고, 각 Route가 서로 다른 Backend Service로 요청을 전달하도록 구성합니다.
이번 구성에서는 app1-route와 app2-route를 생성하고 각각 다른 Hostname을 사용합니다. 두 HTTPRoute는 동일한 shared-gateway를 참조하므로 이후 Gateway에 적용할 WAFPolciy의 공통 적용 대상이 됩니다.
httproutes.yaml 파일을 생성하고 다음 내용을 작성합니다.
apiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata: name: app1-routespec: parentRefs: - name: shared-gateway hostnames: - "app1.example.com" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: app1 port: 80apiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata: name: app2-routespec: parentRefs: - name: shared-gateway hostnames: - "app2.example.com" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: app2 port: 80
주요 설정은 다음과 같습니다.
| 항목 | 설정 예시 | 설명 |
parentRefs.name | shared-gateway | HTTPRoute가 연결될 Gateway 지정 |
hostnames | app1.example.com | 해당 Route가 처리할 Hostname 지정 |
matches.path.type | PathPrefix | 지정된 경로 Prefix를 기준으로 요청 매칭 |
matches.path.value | / | 모든 하위 경로를 포함하도록 / 지정 |
backendRefs.name | app1 | 요청을 전달할 Backend Service 지정 |
backendRefs.port | 80 | Backend Service의 포트 지정 |
작성한 HTTPRoute를 적용합니다.
$ kubectl apply -f httproutes.yaml
생성된 HTTPRoute를 확인합니다.
$ kubectl get httproute
정상적으로 생성된 경우 다음과 같이 각 Route와 Hostname을 확인할 수 있습니다.
NAME HOSTNAMES AGEapp1-route ["app1.example.com"] 8m40sapp2-route ["app2.example.com"] 8m40s
HTTPRoute가 shared-gateway에 정상적으로 연결되었는지 확인합니다.
$ kubectl describe httproute app1-route$ kubectl describe httproute app2-route
정상적으로 연결된 경우 각 HTTPRoute의 Status에서 Accepted=True를 확인할 수 있습니다.
여기까지 구성하면 하나의 Gateway를 기준으로 서로 다른 두 Hostname과 Backend Service가 연결됩니다. 다음 단계에서는 두 Route에 공통으로 적용할 WAF Policy Bundle을 준비합니다.
8. WAF policy bundle 준비
NGINX Gateway Fabric의 WAFPolicy는 WAF Policy JSON 파일을 직접 참조하지 않고, F5 WAF for NGINX에서 사용할 수 있도록 컴파일된 Policy Bundle을 참조합니다.
따라서 WAF Policy JSON을 작성한 뒤 WAF Compiler를 사용하여 .tgz 형식의 Bundle로 컴파일하고, 생성된 Bundle을 WAFPolicy에서 접근할 수 있도록 HTTP로 제공합니다.
8-1. WAF policy definition ConfigMap 생성
먼저 WAF Policy JSON을 ConfigMap으로 생성합니다.
이번 정책에서는 All Signatures Signature Set을 사용하고, 탐지된 공격 시그니처에 대해 alarm과 block을 활성화합니다. 이후 XSS 패턴이 포함된 요청을 발생시켜 차단 여부를 확인합니다.
waf-policy-definitions.yaml 파일을 생성하고 다음 내용을 작성합니다.
apiVersion: v1kind: ConfigMapmetadata: name: waf-policy-definitionsdata: attack-signatures-blocking.json: | { "policy": { "name": "attack-signatures-blocking", "template": { "name": "POLICY_TEMPLATE_NGINX_BASE" }, "applicationLanguage": "utf-8", "enforcementMode": "blocking", "signature-sets": [ { "name": "All Signatures", "block": true, "alarm": true } ] } }
| 항목 | 설정 | 설명 |
template.name | POLICY_TEMPLATE_NGINX_BASE | 기본 WAF Policy Template 사용 |
applicationLanguage | utf-8 | 애플리케이션에서 사용할 문자 인코딩 |
enforcementMode | blocking | 위반이 탐지된 요청을 차단 |
signature-sets.name | All Signatures | 전체 공격 Signature Set 적용 |
alarm | true | Signature 탐지 시 이벤트 기록 |
block | true | Signature에 매칭되는 요청 차단 |
작성한 ConfigMap을 적용합니다.
$ kubectl apply -f waf-policy-definitions.yaml
생성된 ConfigMap을 확인합니다.
$ kubectl get configmap waf-policy-definitions
예상 출력은 다음과 같습니다.
NAME DATA AGEwaf-policy-definitions 1 53s
8-2. bundle server 배포
다음으로 WAF Policy JSON을 Policy Bundle로 컴파일하고, 생성된 Bundle을 HTTP로 제공하는 bundle-server를 배포합니다.
bundle-server Pod는 다음 순서로 동작합니다.
initContainer에서 WAF Compiler를 실행하여attack-signatures-blocking.json을attack-signatures-blocking.tgz로 컴파일합니다.- 생성된 Bundle을 공유 볼륨에 저장합니다.
- NGINX 컨테이너가 동일한 볼륨을
/usr/share/nginx/html에 마운트하여 Bundle 파일을 HTTP로 제공합니다.
bundle-server.yaml 파일을 생성하고 다음 내용을 작성합니다.
apiVersion: apps/v1kind: Deploymentmetadata: name: bundle-serverspec: replicas: 1 selector: matchLabels: app: bundle-server template: metadata: labels: app: bundle-server spec: imagePullSecrets: - name: nginx-plus-registry-secret initContainers: - name: compile-attack-signatures image: private-registry.nginx.com/nap/waf-compiler:5.13.1 args: - -p - /policies/attack-signatures-blocking.json - -o - /bundles/attack-signatures-blocking.tgz volumeMounts: - name: policies mountPath: /policies - name: bundles mountPath: /bundles containers: - name: bundle-server image: nginx:alpine ports: - containerPort: 80 volumeMounts: - name: bundles mountPath: /usr/share/nginx/html volumes: - name: policies configMap: name: waf-policy-definitions - name: bundles emptyDir: {}apiVersion: v1kind: Servicemetadata: name: bundle-serverspec: ports: - port: 80 targetPort: 80 protocol: TCP name: http selector: app: bundle-server
policies 볼륨에는 앞에서 생성한 ConfigMap의 WAF Policy JSON이 마운트되고, bundles 볼륨은 WAF Compiler와 NGINX 컨테이너가 함께 사용하는 공유 공간으로 사용됩니다.
작성한 리소스를 적용합니다.
$ kubectl apply -f bundle-server.yaml
Deployment, Pod, Service 상태를 확인합니다.
$ kubectl get deployments bundle-server$ kubectl get pods -l app=bundle-server$ kubectl get svc bundle-server
정상적으로 배포된 경우 다음과 같이 확인할 수 있습니다.
NAME READY UP-TO-DATE AVAILABLE AGEbundle-server 1/1 1 1 30sNAME READY STATUS RESTARTS AGEbundle-server-6645858f5-ddwsp 1/1 Running 0 46sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEbundle-server ClusterIP 10.97.208.228 <none> 80/TCP 52s
Pod가 시작될 때 initContainer가 먼저 WAF Policy를 컴파일하고 정상적으로 완료된 이후 NGINX 컨테이너가 실행됩니다. 따라서 Pod가 Running 상태라면 생성된 Policy Bundle을 bundle-server Service를 통해 제공할 수 있는 상태입니다.
이후 WAFPolicy에서는 bundle-server의 HTTP URL을 지정하여 생성된 attack-signatures-blocking.tgz Bundle을 참조합니다.
9. Gateway-level WAFPolicy 생성
준비한 WAF Policy Bundle을 사용하여 shared-gateway에 적용할 WAFPolicy를 생성합니다.
targetRefs에서 Gateway를 지정하면 해당 WAFPolicy는 Gateway-level 정책으로 동작합니다. 이번 구성에서는 shared-gateway를 대상으로 지정하여 연결된 app1-route와 app2-route에 동일한 WAF 정책이 적용되도록 구성합니다.
gateway-waf-policy.yaml 파일을 생성하고 다음 내용을 작성합니다.
apiVersion: gateway.nginx.org/v1alpha1kind: WAFPolicymetadata: name: gateway-waf-policyspec: type: HTTP targetRefs: - group: gateway.networking.k8s.io kind: Gateway name: shared-gateway policySource: httpSource: url: http://bundle-server.default.svc.cluster.local/attack-signatures-blocking.tgz # url의 형태는 "Service 이름.namespace.svc.cluster.local.앞에서 waf-compiler가 만든 WAF bundle 파일 이름" 입니다. securityLogs: - destination: type: stderr logSource: defaultProfile: log_blocked
주요 설정은 다음과 같습니다.
| 항목 | 설정 | 설명 |
type | HTTP | HTTP 트래픽에 적용할 WAFPolicy |
targetRefs.kind | Gateway | 정책 적용 대상의 리소스 종류 |
targetRefs.name | shared-gateway | WAFPolicy를 적용할 Gateway |
policySource.httpSource.url | http://bundle-server...tgz | 앞에서 생성한 WAF Policy Bundle의 위치 |
securityLogs.destination.type | stderr | Security Log 출력 위치 |
defaultProfile | log_blocked | 차단된 요청에 대한 Security Log 기록 |
적용한 WAFPolicy를 적용합니다.
$ kubectl apply -f gateway-waf-policy.yaml
생성된 WAFPolicy를 확인합니다.
$ kubectl get wafpolicy gateway-waf-policy
예상 출력은 다음과 같습니다.
NAME AGEgateway-waf-policy 7s
gateway-waf-policy의 targetRefs는 shared-gateway를 참조합니다. 따라서 이 정책은 개별 HTTPRoute가 아닌 Gateway를 대상으로 적용됩니다.
app1-route와 app2-route는 모두 동일한 shared-gateway에 연결되어 있으므로 두 Route에는 Gateway-level WAFPolicy가 공통으로 적용됩니다.
다음 단계에서는 두 Route에 정상 요청과 동일한 공격 요청을 전달하여 WAF 정책이 공통으로 적용되는지 검증합니다.
10. 동일 공격 요청으로 WAFPolicy 상속 검증
app1-route와 app2-route에 동일한 요청을 전달하여 Gateway-level WAFPolicy가 두 HTTPRoute에 공통으로 적용되는지 확인합니다.
Gateway에 적용된 WAFPolicy는 해당 Gateway에 연결된 HTTPRoute에 상속되므로, 별도의 Route-level WAFPolicy를 구성하지 않은 두 Route에는 동일한 WAF 정책이 적용됩니다.
먼저 각 HTTPRoute에 정상 요청을 전달합니다.
$ curl -H "Host: app1.example.com" http://127.0.0.1:8080/$ curl -H "Host: app2.example.com" http://127.0.0.1:8080/
정상적으로 구성된 경우 각 요청은 HTTPRoute에 연결된 Backend Service로 전달됩니다.
Server address: 10.244.49.159:8080Server name: app1-8455b5554c-tqrwxDate: 22/Jun/2026:02:50:58 +0000URI: /Request ID: 83859c7d3e2ef9578143db326c8206f9Server address: 10.244.49.163:8080Server name: app2-657c5d4769-2lml5Date: 22/Jun/2026:02:50:58 +0000URI: /Request ID: 13a977dcf08ef999965b3962ec403888
다음으로 XSS 패턴이 포함된 동일한 요청을 두 HTTPRoute에 전달합니다.
$ curl -H "Host: app1.example.com" \ "http://127.0.0.1:8080/?q=<script>alert(1)</script>"$ curl -H "Host: app2.example.com" \ "http://127.0.0.1:8080/?q=<script>alert(1)</script>"
Gateway-level WAFPolicy가 정상적으로 적용된 경우 두 요청 모두 F5 WAF for NGINX에서 차단되고 Request Rejected 응답을 반환합니다.
<html><head><title>Request Rejected</title></head><body>The requested URL was rejected. Please consult with your administrator.Your support ID is: 5853220945358267012</body></html>
두 HTTPRoute에서 동일한 공격 요청이 차단되는 것을 통해 shared-gateway에 적용한 WAFPolicy가 app1-route와 app2-route에 공통으로 상속되어 동작하는 것을 확인할 수 있습니다.
차단 응답에서 반환된 Support ID를 이용하여 Data Plane Pod의 Security Log도 확인합니다.
$ kubectl logs shared-gateway-nginx-7dd5fb469d-dl8sg -n default --all-containers=true | grep 5853220945358267012
Security Log에서는 요청의 차단 여부와 적용된 WAF 정책, 탐지된 Violation 및 Attack Signature를 확인할 수 있습니다.
request_status="blocked"outcome="REJECTED"outcome_reason="SECURITY_WAF_VIOLATION"policy_name="attack-signatures-blocking"support_id="5853220945358267012"severity="Critical"violations="Illegal meta character in value,Attack signature detected,Violation Rating Threat detected,Bot Client Detected"sig_names="XSS script tag end (Parameter) (2),XSS script tag (Parameter),alert() (Parameter)..."
request_status="blocked"와 outcome="REJECTED"를 통해 요청이 WAF에 의해 차단되었음을 확인할 수 있으며, policy_name에서는 앞에서 구성한 attack-signatures-blocking 정책이 적용된 것을 확인할 수 있습니다.
11. 결론
이번 구성에서는 NGINX Gateway Fabric에서 F5 WAF for NGINX 기능을 활성화하고, 하나의 Gateway에 연결된 두 HTTPRoute를 대상으로 Gateway-level WAFPolicy를 적용했습니다.
WAFPolicy는 개별 HTTPRoute가 아닌 shared-gateway를 대상으로 구성했지만, app1-route와 app2-route 모두에서 동일한 WAF 정책이 적용되는 것을 확인했습니다. Gateway-level WAFPolicy는 해당 Gateway에 연결된 Route에 상속되므로 여러 Route에 공통 보안 정책을 적용할 수 있습니다.
정상 요청은 각 HTTPRoute에 연결된 Backend Service로 전달되었으며, XSS 패턴이 포함된 요청은 두 Route에서 모두 차단되었습니다. Security Log에서도 request_status="blocked", outcome="REJECTED"와 함께 적용된 정책 및 탐지된 Attack Signature를 확인할 수 있었습니다.
이와 같은 Gateway-level WAFPolicy 구성을 사용하면 여러 애플리케이션 Route가 하나의 Gateway를 공유하는 환경에서 동일한 WAF 정책을 반복해서 구성하지 않고 공통으로 적용할 수 있습니다. 필요에 따라 특정 Route에 별도의 Route-level WAFPolicy를 적용하면 해당 Route에서 Gateway-level 정책을 대체하는 구성도 가능합니다.
NGINX STORE에 문의하여 더 자세한 정보를 확인하세요.