NGINX App Protect WAF 를 Docker에 배포

이 포스트에서는 Docker Compose를 사용하여 NGINX App Protect WAF v5 릴리스를 배포하는 방법을 설명합니다.

목차

1. 전제 조건
2. NGINX 이미지 빌드
2-1. 인증서 다운로드
2-2. 공식 NGINX 이미지 기반 Dockerfile
2-3. NGINX Open Source Dockerfile
2-4. NGINX Plus Dockerfile
2-5. 이미지 빌드
3. NGINX 구성
4. NGINX App Protect WAF 서비스 구성
4-1. F5 Container Registry용 Docker 설정
4-2. Docker Compose 파일
5. 배포 시작
6. 정책 및 로깅 프로필 번들 사용
7. 트러블슈팅
8. 결론

1. 전제 조건

2. NGINX 이미지 빌드

NGINX 및 NGINX App Protect 모듈이 포함된 Docker 이미지를 빌드하려면 아래 지침을 따르세요.

2-1. 인증서 다운로드

MyF5에 로그인하고 NGINX App Protect WAF 구독에서 다음 두 파일을 다운로드합니다.

nginx-repo.key
nginx-repo.crt

아래 제공된 예제 중 하나를 사용하여 Dockerfile을 생성하여 진행하세요.

2-2. 공식 NGINX 이미지 기반 Dockerfile

Note:
이 예에서는 공식 NGINX Open Source 이미지를 기반으로 활용하지만 중요한 요구 사항은 NGINX를 소스에서 컴파일하는 것이 아니라 공식 NGINX repository에서 패키지로 설치해야 한다는 것입니다.

# syntax=docker/dockerfile:1

# Base image
FROM nginx:1.25.4-bookworm

# Install NGINX App Protect WAF v5 module
RUN --mount=type=secret,id=nginx-crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
    --mount=type=secret,id=nginx-key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
    apt-get update \
    && apt-get install --no-install-recommends --no-install-suggests -y \
       apt-transport-https \
       lsb-release \
       ca-certificates \
       wget \
       gnupg \
    && wget https://cs.nginx.com/static/keys/nginx_signing.key \
    && gpg --no-default-keyring --keyring gnupg-ring:/etc/apt/trusted.gpg.d/nginx.gpg \
       --import nginx_signing.key \
    && chmod 644 /etc/apt/trusted.gpg.d/nginx.gpg \
    && printf "deb https://pkgs.nginx.com/app-protect-x-oss/debian `lsb_release -cs` nginx-plus\n" | \
       tee /etc/apt/sources.list.d/nginx-app-protect.list \
    && wget -P /etc/apt/apt.conf.d https://cs.nginx.com/static/files/90pkgs-nginx \
    && apt-get update \
    && apt-get install --no-install-recommends --no-install-suggests -y nginx=1.25.4-1~bookworm app-protect-module-oss  \
    && apt-get remove --purge --auto-remove -y apt-transport-https lsb-release gnupg wget \
    && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx-app-protect.list

2-3. NGINX Open Source Dockerfile

운영체제(OS)에 따라 적절한 Dockerfile 예제를 선택하세요.

# syntax=docker/dockerfile:1

# Supported OS_VER's are 3.16/3.17
ARG OS_VER="3.17"

# Base image
FROM alpine:${OS_VER}

# Install NGINX OSS and NGINX App Protect WAF v5 module
RUN --mount=type=secret,id=nginx-crt,dst=/etc/apk/cert.pem,mode=0644 \
    --mount=type=secret,id=nginx-key,dst=/etc/apk/cert.key,mode=0644 \
    apk add openssl curl ca-certificates \
    && printf "%s%s%s%s\n" \
        "http://nginx.org/packages/mainline/alpine/v" \
        `egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release` \
        "/main" \
        | tee -a /etc/apk/repositories \
    && wget -O /etc/apk/keys/nginx_signing.rsa.pub https://cs.nginx.com/static/keys/nginx_signing.rsa.pub \
    && printf "https://pkgs.nginx.com/app-protect-x-oss/alpine/v`egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release`/main\n" | \
        tee -a /etc/apk/repositories \
    && apk update \
    && apk add app-protect-module-oss \
    && ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log \
    && rm -rf /var/cache/apk/*

# Expose port
EXPOSE 80

# Define stop signal
STOPSIGNAL SIGQUIT

# Set default command
CMD ["nginx", "-g", "daemon off;"]

이미지를 빌드할 준비가 되었습니다.

2-4. NGINX Plus Dockerfile

운영체제(OS)에 따라 적절한 Dockerfile 예제를 선택하세요.

# syntax=docker/dockerfile:1

# Supported OS_VER's are 3.16/3.17
ARG OS_VER="3.17"

# Base image
FROM alpine:${OS_VER}

# Install NGINX Plus and NGINX App Protect WAF v5 module
RUN --mount=type=secret,id=nginx-crt,dst=/etc/apk/cert.pem,mode=0644 \
    --mount=type=secret,id=nginx-key,dst=/etc/apk/cert.key,mode=0644 \
    wget -O /etc/apk/keys/nginx_signing.rsa.pub https://cs.nginx.com/static/keys/nginx_signing.rsa.pub \
    && printf "https://pkgs.nginx.com/plus/alpine/v`egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release`/main\n" | \
        tee -a /etc/apk/repositories \
    && printf "https://pkgs.nginx.com/app-protect-x-plus/alpine/v`egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release`/main\n" | \
        tee -a /etc/apk/repositories \
    && apk update \
    && apk add app-protect-module-plus \
    && ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log \
    && rm -rf /var/cache/apk/*

# Expose port
EXPOSE 80

# Define stop signal
STOPSIGNAL SIGQUIT

# Set default command
CMD ["nginx", "-g", "daemon off;"]

이미지를 빌드할 준비가 되었습니다.

2-5. 이미지 빌드

Note:
NGINX App Protect WAF v5 이미지를 Docker Hub와 같은 public 컨테이너 레지스트리에 업로드하지 마십시오. 그렇게 하면 라이선스 계약을 위반하게 됩니다.

이미지를 빌드하려면 nginx-repo.crt, nginx-repo.key 및 Dockerfile이 포함된 디렉터리에서 다음 명령을 실행합니다. 여기서 nginx-app-protect-5는 이미지 태그의 예입니다.

$ sudo docker build --no-cache \
    --secret id=nginx-crt,src=nginx-repo.crt \
    --secret id=nginx-key,src=nginx-repo.key \
    -t nginx-app-protect-5 .

3. NGINX 구성

NGINX 구성에서:

1. main 컨텍스트에서 NGINX App Protect WAF v5 모듈을 로드합니다.

load_module modules/ngx_http_app_protect_module.so;

2. http 컨텍스트에서 Enforcer 주소를 구성하십시오.

app_protect_enforcer_address waf-enforcer:50000;

3. http/server/location 컨텍스트에서 NGINX App Protect WAF를 활성화합니다(proxy_pass/grpc_pass location을 사용하여 NGINX App Protect WAF만 활성화해야 합니다).

app_protect_enable on;

이 포스트에서는 /conf/ 디렉토리 아래에 다음 파일을 만들었습니다.

user  nginx;
worker_processes  auto;

# NGINX App Protect WAF
load_module modules/ngx_http_app_protect_module.so;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    # NGINX App Protect WAF
    app_protect_enforcer_address 127.0.0.1:50000;

    include /etc/nginx/conf.d/*.conf;
}

4. NGINX App Protect WAF 서비스 구성

4-1. F5 Container Registry용 Docker 설정

private-registry.nginx.com에서 F5 Container Registry와 상호 작용하도록 Docker를 구성합니다.

$ sudo mkdir -p /etc/docker/certs.d/private-registry.nginx.com
$ sudo cp <path-to-your-nginx-repo.crt> /etc/docker/certs.d/private-registry.nginx.com/client.cert
$ sudo cp <path-to-your-nginx-repo.key> /etc/docker/certs.d/private-registry.nginx.com/client.key

Note:
인증서 파일의 파일 확장자가 .crt에서 .cert로 변경되었습니다.

4-2. Docker Compose 파일

다음 구성으로 docer-compose.yml을 만듭니다.

version: "3.9"

services:
  nginx:
    container_name: nginx
    image: nginx-app-protect-5
    volumes:
      - app_protect_bd_config:/opt/app_protect/bd_config
      - app_protect_config:/opt/app_protect/config
      - app_protect_etc_config:/etc/app_protect/conf
      - /conf/nginx.conf:/etc/nginx/nginx.conf # based on the provided example
      - /conf/default.conf:/etc/nginx/conf.d/default.conf # based on the provided example
    networks:
      - waf_network
    ports:
      - "80:80"

  waf-enforcer:
    container_name: waf-enforcer
    image: "private-registry.nginx.com/nap/waf-enforcer:<version-tag>"
    environment:
      - ENFORCER_PORT=50000
    volumes:
      - app_protect_bd_config:/opt/app_protect/bd_config
    networks:
      - waf_network
    restart: always

  waf-config-mgr:
    container_name: waf-config-mgr
    image: "private-registry.nginx.com/nap/waf-config-mgr:<version-tag>"
    volumes:
      - app_protect_bd_config:/opt/app_protect/bd_config
      - app_protect_config:/opt/app_protect/config
      - app_protect_etc_config:/etc/app_protect/conf
    restart: always
    network_mode: none
    depends_on:
      waf-enforcer:
        condition: service_started

networks:
  waf_network:
    driver: bridge

volumes:
  app_protect_bd_config:
  app_protect_config:
  app_protect_etc_config:

5. 배포 시작

1. NGINX 및 WAF 서비스를 시작하려면 docker-compose.yml 파일이 포함된 디렉터리로 이동하여 다음을 실행합니다.

$ sudo docker compose up -d

2. 적용 기능을 확인하려면 다음 요청이 거부 되었는지 확인하세요.

$ curl "localhost/<script>"

3. (옵션) NGINX를 다시 로드하려면 다음을 실행합니다.

$ sudo docker exec nginx nginx -s reload

6. 정책 및 로깅 프로필 번들 사용

사용자 정의 정책 및 로깅 프로필 번들을 사용하려면 waf-config-mgr 컨테이너에서 이러한 파일에 액세스할 수 있어야 합니다.

  1. 가정: 번들 파일은 호스트 시스템의 /bundles에 있습니다.
  2. Docker Compose 구성: docker-compose.yml에서 waf-config-mgr 서비스 아래에 볼륨 마운트를 추가하여 호스트 디렉터리 /bundles를 컨테이너 내부의 동일한 경로에 연결합니다.
...
waf-config-mgr:
  container_name: waf-config-mgr
  image: "private-registry.nginx.com/nap/waf-config-mgr:1.0.0"
  volumes:
    - /bundles:/bundles # Mounting the host directory to the container
    - ... #existing volume mounts

이 볼륨 마운트를 설정하면 /bundles 디렉터리를 사용하여 NGINX 구성 내에서 번들 파일을 참조할 수 있습니다.

예를 들어:

app_protect_policy_file /bundles/custom_policy.tgz;
app_protect_security_log /bundles/custom_logging_profile.tgz syslog:server=localhost:5514;

7. 트러블슈팅

  • Container Failures: 컨테이너가 실패하거나, 다시 시작되거나, 실행이 중지되면 오류 메시지에 대해 sudo docker log [container_name]을 실행하여 로그에서 오류 메시지를 검사합니다. 컨테이너의 기본 이름은 다음과 같습니다.
    • nginx
    • waf-enforcer
    • waf-config-mgr
  • Permissions Issues: 기본적으로 waf-config-mgr 및 waf-enforcer 컨테이너는 101:101로 설정된 사용자 및 그룹 ID로 작동합니다. 이러한 ID로 번들 파일에 액세스할 수 있는지 확인하세요.

경우에 따라 서비스를 다시 시작하는 것만으로도 일시적인 문제가 해결될 수 있습니다. sudo docker compose down -v를 사용한 다음 sudo docker compose up -d를 사용하여 모든 서비스를 다시 시작합니다.

8. 결론

이 가이드에서는 Docker Compose를 사용하여 NGINX App Protect WAF v5를 배포하기 위한 기본 단계를 제공합니다. 특정 요구 사항에 맞게 배포를 조정해야 할 수도 있습니다.

NGINX App Protect를 직접 사용해 보시려면 30일 무료 평가판을 신청하거나 NGINX STORE에 연락하여 논의하십시오.

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

* indicates required