NGINX Plus

Proxy 프로토콜 수락

이 문서에서는 Proxy 프로토콜을 수락하고, Load Balancer 또는 Proxy의 IP 주소를 Proxy 프로토콜 헤더에 수신된 주소로 다시 쓰고, 클라이언트 IP 주소의 간단한 로깅을 구성하고, NGINX와 TCP Upstream 서버 간에 Proxy 프로토콜을 사용하도록 NGINX 및 NGINX Plus 를 구성하는 방법에 대해 설명합니다.

목차

1. 소개
2. 전제 조건
3. Proxy 프로토콜을 수락하도록 NGINX 구성하기
4. Load Balancer의 IP 주소를 클라이언트 IP 주소로 변경하기
5. 원본 IP 주소 로깅
6. Upstream에 대한 TCP 연결을 위한 Proxy 프로토콜
7. 예제

1. 소개

Proxy 프로토콜을 사용하면 NGINX와 NGINX Plus 가 Proxy 서버를 통해 전달된 클라이언트 연결 정보를 수신하고 HAproxy 및 Amazon Elastic Load Balancer(ELB)와 같은 Load Balancer를 사용할 수 있습니다.

Proxy 프로토콜을 사용하면 NGINX는 HTTP, SSL, HTTP/2, SPDY, WebSocket, TCP에서 원본 IP 주소를 학습할 수 있습니다. 클라이언트의 발신 IP 주소를 아는 것은 웹사이트에 특정 언어를 설정하거나, IP 주소 거부 목록을 유지하거나, 단순히 로깅 및 통계 목적으로 유용할 수 있습니다.

Proxy 프로토콜을 통해 전달되는 정보는 클라이언트 IP 주소, Proxy 서버 IP 주소 및 두 포트 번호입니다.

이 데이터를 사용하여 NGINX는 여러 가지 방법으로 클라이언트의 원본 IP 주소를 얻을 수 있습니다.

2. 전제 조건

  • Proxy 프로토콜 v2, NGINX Plus R16 이상 또는 NGINX Open Source 1.13.11 이상을 수락하려면 다음과 같이 하세요.
  • HTTP용 Proxy 프로토콜을 수락하려면 NGINX Plus R3 이상 또는 NGINX Open Source 1.5.12 이상이 필요합니다.
  • TCP 클라이언트 측 Proxy 프로토콜 지원의 경우, NGINX Plus R7 이상 또는 NGINX Open Source 1.9.3 이상이 필요합니다.
  • TCP용 Proxy 프로토콜을 수락하려면 NGINX Plus R11 이상 또는 NGINX Open Source 1.11.4 이상이 필요합니다.
  • HTTPStream TCP용 Real-IP 모듈은 기본적으로 NGINX Open Source에 포함되어 있지 않으므로 자세한 내용은 NGINX Open Source 설치하기를 참조하세요. NGINX Plus에는 추가 단계가 필요하지 않습니다.

3. Proxy 프로토콜을 수락하도록 NGINX 구성하기

Proxy 프로토콜 헤더를 허용하도록 NGINX를 구성하려면 http { } 또는 stream { } 블록의 server 블록에 있는 listen 지시문에 proxy_protocol 파라미터를 추가합니다.

http {
    #...
    server {
        listen 80   proxy_protocol;
        listen 443  ssl proxy_protocol;
        #...
    }
}
   
stream {
    #...
    server {
        listen 12345 proxy_protocol;
        #...
    }
}

이제 클라이언트 IP 주소와 포트에 $proxy_protocol_addr$proxy_protocol_port 변수를 사용하고, $remote_addr$remote_port 변수에 있는 Load Balancer의 IP 주소를 클라이언트의 IP 주소 및 포트로 대체하도록 HTTPstream RealIP 모듈을 추가적으로 구성할 수 있습니다.

4. Load Balancer의 IP 주소를 클라이언트 IP 주소로 변경하기

Load Balancer 또는 TCP Proxy 주소를 Proxy 프로토콜에서 수신한 클라이언트 IP 주소로 대체할 수 있습니다. 이 작업은 HTTPstream RealIP 모듈을 사용하여 수행할 수 있습니다. 이러한 모듈을 사용하면 $remote_addr$remote_port 변수는 클라이언트의 실제 IP 주소와 포트를 유지하고, $realip_remote_addr$realip_remote_port 변수는 Load Balancer의 IP 주소와 포트를 유지합니다.

Load Balancer의 IP 주소에서 클라이언트의 IP 주소로 IP 주소를 변경하려면 다음과 같이 하세요.

1. Proxy 프로토콜 헤더를 수락하도록 NGINX를 구성했는지 확인하세요. Proxy 프로토콜을 수락하도록 NGINX 구성을 참조하세요.

2. NGINX 설치에 HTTPStream Real-IP 모듈이 포함되어 있는지 확인하세요.

nginx -V 2>&1 | grep -- 'http_realip_module'
nginx -V 2>&1 | grep -- 'stream_realip_module'

그렇지 않은 경우 이러한 모듈을 사용하여 NGINX를 다시 컴파일하세요. 자세한 내용은 NGINX Open Source 설치하기를 참조하세요. NGINX Plus에는 추가 단계가 필요하지 않습니다.

3. HTTP, Stream 또는 둘 다에 대한 set_real_ip_from 지시문에서 TCP Proxy 또는 Load Balancer의 IP 주소 또는 주소의 CIDR 범위를 지정합니다.

server {
    #...
    set_real_ip_from 192.168.1.0/24;
   #...
}

4. http { } 컨텍스트에서 proxy_protocol 매개변수를 real_ip_header 지시문에 지정하여 Load Balancer의 IP 주소를 Proxy 프로토콜 헤더에서 수신한 클라이언트의 IP 주소로 변경합니다.

http {
    server {
        #...
        real_ip_header proxy_protocol;
      }
}

5. 원본 IP 주소 로깅

클라이언트의 원래 IP 주소를 알고 있으면 올바른 로깅을 구성할 수 있습니다.

1. HTTP의 경우, proxy_set_header 지시문과 함께 $proxy_protocol_addr 변수를 사용하여 클라이언트 IP 주소를 Upstream 서버에 전달하도록 NGINX를 구성합니다.

http {
    proxy_set_header X-Real-IP       $proxy_protocol_addr;
    proxy_set_header X-Forwarded-For $proxy_protocol_addr;
}

2. log_format 지시문(HTTP 또는 Stream)에 $proxy_protocol_addr 변수를 추가합니다.

http 블록에서.

http {
    #...
    log_format combined '$proxy_protocol_addr - $remote_user [$time_local] '
                        '"$request" $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent"';
}

stream 블록에서.

stream {
    #...
    log_format basic '$proxy_protocol_addr - $remote_user [$time_local] '
                      '$protocol $status $bytes_sent $bytes_received '
                      '$session_time';
}

6. Upstream에 대한 TCP 연결을 위한 Proxy 프로토콜

TCP Stream의 경우, NGINX와 Upstream 서버 간의 연결에 PROXY 프로토콜을 활성화할 수 있습니다. Proxy 프로토콜을 활성화하려면 stream { } Level의 server 블록에 proxy_protocol 지시문을 포함하세요.

stream {
    server {
        listen 12345;
        proxy_pass example.com:12345;
        proxy_protocol on;
    }
}

7. 예제

http {
    log_format combined '$proxy_protocol_addr - $remote_user [$time_local] '
                        '"$request" $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent"';
    #...

    server {
        server_name localhost;

        listen 80   proxy_protocol;
        listen 443  ssl proxy_protocol;

        ssl_certificate      /etc/nginx/ssl/public.example.com.pem;
        ssl_certificate_key  /etc/nginx/ssl/public.example.com.key;

        location /app/ {
            proxy_pass       http://backend1;
            proxy_set_header Host            $host;
            proxy_set_header X-Real-IP       $proxy_protocol_addr;
            proxy_set_header X-Forwarded-For $proxy_protocol_addr;
        }
    }
} 

stream {
    log_format basic '$proxy_protocol_addr - $remote_user [$time_local] '
                     '$protocol $status $bytes_sent $bytes_received '
                     '$session_time';
    #...
    server {
        listen              12345 ssl proxy_protocol;

        ssl_certificate     /etc/nginx/ssl/cert.pem;
        ssl_certificate_key /etc/nginx/ssl/cert.key;

        proxy_pass          backend.example.com:12345;
        proxy_protocol      on;
    }
}

이 예제에서는 들어오는 모든 HTTPS 트래픽을 처리하는 Load Balancer(예: Amazon ELB)가 NGINX 앞에 있다고 가정합니다. NGINX는 포트 443(listen 443 ssl;)에서 HTTPS 트래픽을 수신하고, 포트 12345에서 TCP 트래픽을 수신하며, Load Balancer에서 전달된 클라이언트의 IP 주소(http { }stream { } 블록 모두에서 listen 지시문에 대한 proxy_protocol 매개변수)도 Proxy 프로토콜을 통해 수신합니다.

NGINX Terminate는 HTTPS 트래픽(ssl_certificatessl_certificate_key 지시문)을 해독하고 해독된 데이터를 Backend 서버로 Proxy합니다.

  • HTTP의 경우: proxy_pass http://backend1;
  • TCP의 경우: proxy_pass backend.example.com:12345

여기에는 클라이언트 IP 주소와 포트가 proxy_set_header 지시문과 함께 포함됩니다.

log_format 지시문에 지정된 $proxy_protocol_addr 변수는 클라이언트의 IP 주소도 HTTP와 TCP 모두에 대해 로그에 전달합니다.

또한 TCP 서버( stream { } 블록)는 자체 Proxy 프로토콜 데이터를 Backend 서버(proxy_protocol on 지시문)로 전송합니다.