NGINX Instance Manager 보안 구성 가이드

이 가이드는 NGINX Instance Manager로 연결하는 클라이언트의 연결과 NGINX Instance Manager, NGINX 인스턴스간의 트래픽 보안 을 설정하는 방법에 관해서 설명합니다.

NGINX Plus R33버전은 원격 측정 데이터를 NGINX Instance Manager과 같은 사용 리포트 엔드포인트로 전송해야합니다. 이 데이터는 구독 자격을 검증하고 사용 메트릭을 추적합니다. 이 가이드에는 ssl_verify 지시문을 통한 인증서 검증을 통해 원격 측정 데이터 전송을 보호하는 방법도 포함하고 있습니다.

중요:

관리 서버를 공개 인터넷에 노출하지 마십시오. 이 가이드의 설정은 위협을 줄이지만, 인증되지 않은 사용자가 서버에 접근하지 못하도록 막는 것을 대체할 수는 없습니다.

목차

1. NGINX Proxy SSL Termination
2. Mutual Client Certificate Authentication 설정 (mTLS)
3. 자체 서명 인증서로 사용 리포트를 위한 SSL 검증 구성
4. 문제 해결

1. NGINX Proxy SSL Termination

SSL termination은 SSL 암호화된 트래픽이 프록시(이 경우 NGINX Instance Manager)에서 복호화되는 과정입니다. 복호화 후, 설정에 따라 트래픽은 암호화되지 않거나 다시 암호화된 상태로 목적지로 전송될 수 있습니다.

NGINX Plus와 NGINX Instance Manager 사이의 트래픽 보안 을 설정하기 위해, NGINX 설정에 SSL 인증서와 키를 설정해야 합니다. 이 구성은 NGINX OSS와 NGINX Plus 모두 해당합니다. 자세한 내용은 NGINX HTTPS 서버 구성을 참고하세요.

NGINX Plus R33 버전부터, NGINX Instance Manager가 원격 측정 데이터를 전송할 때 SSL 인증서를 확인하기 위해 ssl_verify 지시문을 활성화해야 합니다.

아래 예시는 NGINX Instance Manager에 대한 SSL termination을 설정하는 방법을 보여줍니다.

/etc/nginx/conf.d/nms-http.conf
# Main external HTTPS server, needs port 443
server {
    listen 443 ssl;
    http2  on;
    root   /var/www/nms;

    server_name _;

    ssl_protocols       TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;

    ssl_certificate         /etc/nms/certs/manager-server.pem;
    ssl_certificate_key     /etc/nms/certs/manager-server.key;
    ssl_client_certificate  /etc/nms/certs/ca.pem;

2. Mutual Client Certificate Authentication 설정 (mTLS)

Mutual TLS (mTLS)는 클라이언트 인증서를 사용하여 통신 중 서버와 클라이언트를 모두 인증하는 보안 방법입니다. 이를 통해 NGINX Instance Manager와 NGINX Plus 인스턴스가 모두 안전하게 인증되어 네트워크가 인증되지 않은 접근으로부터 보호됩니다.

mTLS를 사용하면 각 NGINX 인스턴스는 고유의 클라이언트 인증서를 보유하며, NGINX Instance Manager가 통신을 허용하기 전에 해당 인증서를 검증합니다. NGINX를 프록시로 구성하여 이 안전한 교환을 위해 클라이언트 인증서를 처리하도록 할 수 있습니다.

아래 과정을 따라 공개키 인프라(Public Key Infrastructure/PKI) 시스템을 사용하여 mTLS를 설정하세요.

인증 기관(CA) 설정
  1. 개인 인증 기관 생성(CA):
    • 테스트 중이라면, NGINX Instance Manager와 동일한 머신에서 CA를 생성해도 됩니다.
    • 프로덕션 환경이라면, 조직의 보안 표준을 따릅니다. (주로 안전한 오프라인 머신에서 CA 생성을 요구합니다.)
  2. 루트, 중간 CA 설정:
    • 루트 CA는 인증서를 중간 CA에 발급합니다. 중간 CA는 클라이언트와 서버에 대한 인증서를 발급합니다. 이러한 계층 구조는 루트 CA는 최상위 작업에만 사용되도록 하여 보안을 강화합니다.
  3. 클라이언트, 서버 인증서 발급:
    • 중간 CA는 인증서 서명 요청(CSRs)에 서명하고 인증서를 NGINX 클라이언트와 NGINX Instance Manager에 발급합니다.
인증서 생성

필수 인증서를 생성하려면 다음 단계를 따르세요. 환경에 맞게 지침을 수정할 수 있습니다.

1. OpienSSL을 설치합니다(아직 설치되지 않았다면).

2. 인증서 생성 스크립트를 만듭니다:

  • 다음 예제 스크립트를 사용하여 CA, 서버, 클라이언트를 위한 인증서를 생성합니다. 스크립트를 make_certs.sh와 같은 이름으로 저장합니다.
make_certs.sh
#!/bin/bash
set -e

make_ca() {
    echo "Creating Self-Signed Root CA certificate and key"
    openssl req \
        -new \
        -nodes \
        -x509 \
        -keyout ca.key \
        -out ca.crt \
        -config ca.cnf \
        -extensions v3_req \
        -days 1826  # 5 years
}

make_int() {
    echo "Creating Intermediate CA certificate and key"
    openssl req \
        -new \
        -nodes \
        -keyout ca_int.key \
        -out ca_int.csr \
        -config ca-intermediate.cnf \
        -extensions v3_req
    openssl req -in ca_int.csr -noout -verify
    openssl x509 \
        -req \
        -CA ca.crt \
        -CAkey ca.key \
        -CAcreateserial \
        -in ca_int.csr \
        -out ca_int.crt \
        -extfile ca-intermediate.cnf \
        -extensions v3_req \
        -days 365 # 1 year
    openssl verify -CAfile ca.crt ca_int.crt
    echo "Creating CA chain"
    cat ca_int.crt ca.crt > ca.pem
}

make_server() {
    echo "Creating nginx-manger certificate and key"
    openssl req \
        -new \
        -nodes \
        -keyout server.key \
        -out server.csr \
        -config server.cnf
    openssl req -in server.csr -noout -verify
    openssl x509 \
        -req \
        -CA ca_int.crt \
        -CAkey ca_int.key \
        -CAcreateserial \
        -in server.csr \
        -out server.crt \
        -extfile server.cnf \
        -extensions v3_req \
        -days 365 # 1 year
    openssl verify -CAfile ca.pem server.crt
}

make_agent() {
    echo "Creating Agent certificate and key"
    openssl req \
        -new \
        -nodes \
        -keyout agent.key \
        -out agent.csr \
        -config agent.cnf
    openssl req -in agent.csr -noout -verify
    openssl x509 \
        -req \
        -CA ca.crt \
        -CAkey ca.key \
        -CAcreateserial \
        -in agent.csr \
        -out agent.crt \
        -extfile agent.cnf \
        -extensions v3_req \
        -days 365 # 1 year
    openssl verify -CAfile ca.pem agent.crt
}

# MAIN
make_ca
make_int
make_server
make_agent

3. 설정 파일을 위치시킵니다.

  • 아래 .cnf OpenSSL 파일을 make_certs.sh 스크립트와 같은 디렉터리에 넣습니다. 이 파일들은 인증 기관을 구성하고 적절한 인증서를 생성하는 데 필요합니다.
ca.cnf
[req]
default_bits        = 4096
distinguished_name  = req_distinguished_name
prompt              = no
default_md          = sha256
req_extensions      = v3_req

# recommend changing these to your needs
[req_distinguished_name]
countryName                 = US
stateOrProvinceName         = California
localityName                = San Francisco
organizationName            = NGINX, Inc.
commonName                  = nms-ca

[v3_req]
basicConstraints = critical, CA:true
keyUsage = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
ca-intermediate.cnf
[req]
default_bits        = 4096
distinguished_name  = req_distinguished_name
prompt              = no
default_md          = sha256
req_extensions      = v3_req

# recommend changing these to your needs
[req_distinguished_name]
countryName                 = US
stateOrProvinceName         = California
localityName                = San Francisco
organizationName            = NGINX, Inc.
commonName                  = nms-int-ca

[v3_req]
basicConstraints = critical, CA:true
keyUsage = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
server.cnf
[req]
prompt             = no
default_bits       = 4096
x509_extensions    = v3_req
req_extensions     = v3_req
default_md         = sha256
distinguished_name = req_distinguished_name

# recommend changing these to your needs
[req_distinguished_name]
countryName                 = US
stateOrProvinceName         = California
localityName                = San Francisco
organizationName            = NGINX, Inc.
commonName                  = nginx-manager.example.com

[v3_req]
basicConstraints = CA:FALSE
keyUsage         = nonRepudiation, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage = critical, serverAuth
subjectAltName = @alt_names

# apply any DNS or IP SANs as needed
[alt_names]
DNS.1 = <NGINX-INSTANCE-MANAGER-FQDN>
IP.1 = <NGINX-INSTANCE-MANAGER-IP>
agent.cnf
[req]
prompt             = no
default_bits       = 2048
x509_extensions    = v3_req
req_extensions     = v3_req
default_md         = sha256
distinguished_name = req_distinguished_name

# recommend changing these to your needs
[req_distinguished_name]
countryName                 = US
stateOrProvinceName         = California
localityName                = San Francisco
organizationName            = NGINX, Inc.
commonName                  = agent.example.com

[v3_req]
basicConstraints = CA:FALSE
keyUsage         = nonRepudiation, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage = critical, clientAuth

4. 스크립트를 실행합니다:

  • 스크립트를 저장하고, 실행하여 인증서를 생성할 수 있도록 만듭니다.
$ sudo chmod +x ./make_certs.sh
$ sudo ./make_certs.sh

5. NGINX 인스턴스에 인증서 복사:

  • 생성이 끝나면 ca.pem, agent.crt, agent.key 파일을 NGINX Agent 인증서가 설치될 NGINX 인스턴스에 복사합니다.
$ sudo mkdir -p /etc/nms/certs
$ sudo cp ca.pem /etc/nms/certs/
$ sudo cp agent.crt /etc/nms/certs/
$ sudo cp agent.key /etc/nms/certs/

6. NGINX Agent 설정 수정:

  • nginx-agent.conf 파일을 아래 예제에 맞게 수정합니다. TLS 옵션은 NGINX Agent가 NGINX Instance Manager의 NGINX 프록시와 클라이언트 인증서 인증을 사용하도록 구성합니다. ca.pem 파일은 agent가 NGINX Instance Manager의 서버 인증서를 확인하는 데 사용할 인증 기관으로 포함됩니다.
  • 운영 체제가 CA를 신뢰하는 경우 ca 옵션을 생략할 수 있습니다.
  • NGINX Instance Manager 주소와 일치하도록 서버 호스트를 업데이트합니다.
/etc/nginx-agent/nginx-agent.conf
#
# /etc/nginx-agent/nginx-agent.conf
#
# Configuration file for NGINX Agent.
#
# This file is to track agent configuration values that are meant to be statically set. There
# are additional agent configuration values that are set via the API and agent install script
# which can be found in /var/lib/nginx-agent/agent-dynamic.conf.

# specify the server grpc port to connect to
server:
    # host of the control plane
    host: <NGINX-INSTANCE-MANAGER-FQDN>
    grpcPort: 443
    # provide servername overrides if using SNI
    metrics: "nginx-manager.example.com"
    command: "nginx-manager.example.com"
# tls options
tls:
    enable: true
    skip_verify: false
    cert: /etc/nms/certs/agent.crt
    key: /etc/nms/certs/agent.key
    ca: /etc/nms/certs/ca.pem
log:
    # set log level (panic, fatal, error, info, debug, trace; default "info")
    level: info
    # set log path. if empty, don't log to file.
    path: /var/log/nginx-agent/
# data plane status message / 'heartbeat'
nginx:
    # path of NGINX logs to exclude
    exclude_logs: ""

dataplane:
    sync:
        enable: true
    # poll interval for data plane status
    status:
        poll_interval: 30s
metrics:
    # specify the size of a buffer to build before sending metrics
    bulk_size: 20
    # specify metrics poll interval
    report_interval: 1m
    collection_interval: 15s
    mode: aggregated

# OSS NGINX default config path
# path to aux file dirs can also be added
config_dirs: "/etc/nginx:/usr/local/etc/nginx"

7.  ca.pemserver.crtserver.key를 NGINX Instance Manager로 복사합니다.

$ sudo cp ca.pem /etc/nms/certs/
$ sudo cp server.crt /etc/nms/certs/
$ sudo cp server.key /etc/nms/certs/

8. 새로 생성된 인증서를 사용하여 NGINX Instance Manager 설정에서 gRPC용 NGINX 프록시에 새로운 서버를 추가하고 서비스를 reload 합니다.

  • server_namenginx-agent.confserver.metricsserver.command 값과 일치해야 합니다.
  • 기존 서버의 MetricsServiceCommander 로케이션을 제거할 수 있습니다.
  • 새로운 서버는 NGINX agent와 NGINX Instance Manager 간에 mTLS 통신을 시행하는 반면, 이전 서버는 mTLS 요구 사항 없이 웹 인터페이스 및 API에 대한 정적 콘텐츠를 계속 제공할 수 있습니다.

tls.skip_verify가  false로 설정된 경우, NGINX Agent는 서버의 인증서와 호스트 이름을 검증합니다. 설정의 server_name이 생성한 인증서의  Common Name (CN) 혹은 Subject Alternative Name (SAN)과 일치하는지 확인합니다.

# gRPC HTTPS server, needs port 443
server {
    listen 443 ssl;
    http2  on;
    root   /var/www/nms;

    server_name nginx-instance-manager.example.com;

    ssl_protocols       TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;

    ssl_certificate         /etc/nms/certs/server.crt;
    ssl_certificate_key     /etc/nms/certs/server.key;
    ssl_client_certificate  /etc/nms/certs/ca.pem;
    ssl_verify_client on;

    # gRPC service for metric ingestion
    location /f5.nginx.agent.sdk.MetricsService {
        include /etc/nms/nginx/errors-grpc.loc_conf;
        grpc_socket_keepalive on;
        grpc_read_timeout 5m;
        grpc_send_timeout 5m;
        client_body_timeout 10m;
        grpc_pass grpc://ingestion-grpc-service;
    }

    # gRPC service for DPM
    location /f5.nginx.agent.sdk.Commander {
        include /etc/nms/nginx/errors-grpc.loc_conf;
        grpc_socket_keepalive on;
        grpc_read_timeout 5m;
        grpc_send_timeout 5m;
        client_body_timeout 10m;
        grpc_pass grpc://dpm-grpc-service;
    }

9. NGINX 프록시 설정을 reload 합니다:

  • NGINX 프록시 설정을 reload 하여 새로운 설정을 적용합니다.
$ sudo nginx -s reload

10. NGINX Agent를 재시작합니다:

  • 변경 사항 적용을 위해 NGINX Agent를 재시작하거나 시작합니다.
$ sudo systemctl restart nginx-agent

3. 자체 서명 인증서로 사용 리포트를 위한 SSL 검증 구성

버전 요구사항

NGINX Pluss R33 혹은 이후 버전의 네트워크 제한 환경에서의 사용 리포트 전송은 NGINX Instance Manager 2.18 혹은 이후 버전을 필요로 합니다.

NGINX Plus R33부터, NGINX Plus는 사용 데이터를 NGINX Instance Manager과 같은 리포트 엔드포인트로 전송해야 합니다. 더 많은 정보는 구독 라이선스 – NGINX Plus R33+ 문서를 참고하세요.

mgmt 블록의 ssl_verify 지시문은 NGINX Plus가 서버의 SSL 인증서를 검증하여 신뢰할 수 있는 리포트 엔드포인트에만 연결되도록 보장합니다. ssl_verify 지시문은 기본적으로 on으로 설정됩니다.

ssl_verify가 중요한 이유

ssl_verify가 활성화된 경우

  • NGINX Plus는 NGINX Instance Manager가 제시한 SSL 인증서를 검증하여, 신뢰할 수 있는 출처에서 발급된 것인지 확인합니다.
  • 안전한 원격 측정 전송을 통해 중간자 공격(MITM)을 방지합니다.

인증서가 유효하지 않거나 신뢰할 수 없는 경우, 원격 측정 리포트는 실패합니다. 이러한 실패는 구독 검증과 NGINX Plus의 정상적인 동작에 영향을 끼칠 수 있습니다.

자체 서명 인증서 신뢰

만약 NGINX Instance Manager가 자체 서명 인증서를 사용한다면, NGINX Plus가 이를 명시적으로 신뢰하도록 설정해야 합니다. ssl_trusted_certificate 지시문을 사용하여 신뢰할 수 있는 CA 인증서가 포함된 PEM 형식의 파일을 지정합니다.

mgmt {
    usage_report endpoint=<NGINX-INSTANCE-MANAGER-FQDN>;
    ssl_verify on;
    ssl_trusted_certificate <CA-CERT-FILE-FROM-NGINX-INSTANCE-MANAGER>;
    ssl_name manager-server;
}

자체 서명 인증서를 사용하는 경우 연결 문제나 잠재적인 취약점을 피하기 위해 신중한 구성이 필요합니다.

ssl_verify 비활성화

ssl_verify를 비활성화하면 SSL 인증서 검증을 건너뜁니다. 이러한 구성은 보안이 약화되고 프로덕션 환경에선 권장되지 않습니다. 하지만 테스트 환경이나 연결 문제 해결과 같은 특별한 경우에는 비활성화할 수 있습니다.

mgmt {
    ssl_verify off;
}

4. 문제 해결

만약 NGINX Agent와 NGINX Instance Manager 사이에 통신 문제가 발생한 경우 아래 단계를 따라 문제를 해결하세요.

1. 엑세스 로그와 에러 로그 확인:

  • 엑세스 로그와 에러 로그를 활성화 하여 에러 및 요청 처리의 상세한 정보를 기록하도록 합니다.
  • 기본적으로, 두 로그 모두 NGINX 메인 설정 파일의 http 블록에 활성화되어 있습니다.
# nginx.conf
http {
    ...
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    ...
}

2. 인증서 문제에 대한 로그 확인:

  • 인증서 관련 에러가 발생했는지 로그를 검토합니다. 서버가 올바른 인증서와 인증 기관(CA)을 사용하는지 확인합니다.