CS/network

Proxy Protocol: Client IP를 유지하는 방법

아야는 못말려 2024. 9. 26. 22:06

Proxy Protocol이란?

Proxy Protocol은 로드 밸런서나 프록시 서버를 거쳐 백엔드 서버로 트래픽이 전달될 때, 클라이언트의 원래 IP 주소와 포트 정보를 보존하기 위해 사용되는 프로토콜이다. 일반적으로 로드 밸런서나 프록시 서버는 클라이언트의 원래 IP를 숨기고 자체 IP로 요청을 전달하기 때문에, 백엔드 서버는 클라이언트의 실제 IP 정보를 알 수 없게 된다. Proxy Protocol은 이러한 문제를 해결하기 위해 요청의 첫 부분에 클라이언트 IP 주소와 포트 정보를 포함시켜 전달한다.

 

Proxy Protocol의 동작 방식

Proxy Protocol은 v1v2 두 가지 버전이 있으며, 현재 두 버전 모두 사용되고 있다.

  • v1: 텍스트 기반의 프로토콜로, 헤더 정보가 사람이 읽기 쉬운 ASCII 형식으로 전달된다. 예를 들어, PROXY TCP4 192.168.0.1 192.168.0.2 12345 80과 같은 형식으로 원래 클라이언트 IP, 대상 서버 IP, 원본 및 대상 포트 정보가 전달된다. v1은 사람이 쉽게 읽고 디버깅할 수 있다는 장점이 있지만, 헤더 크기가 크고 처리 효율이 떨어진다는 단점이 있다.
  • v2: 바이너리 기반의 프로토콜로, 더 효율적이고 다양한 프로토콜(TCP/UDP)을 지원한다. v1에 비해 데이터 크기가 작고 처리 속도가 빠르며, 추가적인 프로토콜 정보를 포함할 수 있다.

 

🔍 Proxy Protocol과 X-Forwarded-For의 차이점

Proxy Protocol과 X-Forwarded-For 헤더는 모두 클라이언트의 원래 IP 정보를 백엔드 서버에 전달하기 위한 목적으로 사용되지만, 그 동작 방식과 적용 범위에서 차이점이 있다.


전달 방식

🧬 Proxy Protocol: 클라이언트의 원래 IP 주소와 포트 정보를 실제 TCP 패킷 앞에 헤더 형태로 추가하여 전달한다. 이 헤더는 텍스트 기반(v1) 또는 바이너리 기반(v2)으로 구성되며, 로드 밸런서나 프록시 서버와 백엔드 서버 간의 연결이 TCP 레벨에서 이루어질 때 사용된다.

 

📨 X-Forwarded-For: HTTP 요청 헤더에 클라이언트의 원래 IP 주소를 포함시킨다. 프록시나 로드 밸런서가 클라이언트 요청을 백엔드 서버로 전달할 때 X-Forwarded-For: <client-ip> 형태로 IP를 추가한다.


지원 프로토콜

🧬 Proxy Protocol: L4 계층(TCP/UDP)에서 동작하기 때문에 HTTP뿐만 아니라 다양한 프로토콜을 지원한다.

 

📨 X-Forwarded-For: L7 계층에서 동작하는 HTTP 전용 헤더이므로, HTTP/HTTPS 트래픽에서만 사용 가능하다.


지원 환경

🧬 Proxy Protocol: 로드 밸런서와 백엔드 간 통신이 HTTP가 아닌 경우에도 클라이언트 IP를 전달할 수 있어, TCP 기반 애플리케이션이나 기타 프로토콜을 사용하는 환경에서 효과적으로 사용할 수 있다.

 

📨 X-Forwarded-For: 웹 애플리케이션이나 HTTP 프로토콜을 사용하는 서비스에 적합하며, 설정이 간단하고 다양한 웹 서버에서 기본적으로 지원한다.


설정 복잡도

🧬 Proxy Protocol: 백엔드 서버와 프록시/로드 밸런서 모두 Proxy Protocol을 지원하도록 설정해야 한다. 백엔드 서버가 Proxy Protocol을 지원하지 않는다면 올바르게 처리되지 않을 수 있다.

 

📨 X-Forwarded-For: 백엔드 서버에서 X-Forwarded-For 헤더를 읽기만 하면 되기 때문에 설정이 상대적으로 간단하다.


 

x-forwarded-for vs proxy protocol

 

Proxy Protocol 설정 해보기

☁️ AWS ELB에서 설정하기

AWS에는 Classic Load Balancer (CLB), Network Load Balancer (NLB), Application Load Balancer (ALB) 세 가지 종류의 로드 밸런서가 있다. Proxy Protocol은 CLB와 NLB에서 지원하지만, ALB는 L7 계층 로드 밸런서로서 Proxy Protocol을 지원하지 않으며, 대신 X-Forwarded-For 헤더를 사용한다.

 

CLB는 Proxy Protocol의 v1만을 지원하며, NLB는 v2를 기본적으로 지원한다.

 

CLB에 적용하기

CLB에서 Proxy Protocol을 활성화하려면 AWS 콘솔이나 CLI를 통해 설정할 수 있다. 콘솔에서는 CLB의 'Listeners' 탭에서 Proxy Protocol을 활성화할 수 있다.

aws elb create-load-balancer-policy --load-balancer-name <your-load-balancer> \
    --policy-name ProxyProtocolPolicy \
    --policy-type-name ProxyProtocolPolicyType
aws elb set-load-balancer-policies-for-backend-server --load-balancer-name <your-load-balancer> \
    --instance-port 80 --policy-names ProxyProtocolPolicy

 

NLB에 적용하기

NLB에서 Proxy Protocol v2를 활성화하려면 대상 그룹(Target Group)에서 설정해야 한다. AWS CLI를 사용하여 다음과 같이 설정할 수 있다:

aws elbv2 modify-target-group-attributes \
    --target-group-arn <your-target-group-arn> \
    --attributes Key=proxy_protocol_v2.enabled,Value=true
  • <your-target-group-arn>: 대상 그룹(Target Group)의 ARN으로 변경해야 한다.

이렇게 설정하면 NLB가 Proxy Protocol v2를 사용하여 클라이언트 IP와 포트 정보를 백엔드로 전달하게 된다.

 

🧩 Nginx에 적용하기

NGINX를 프록시 또는 로드 밸런서로 사용할 경우, Proxy Protocol을 지원하도록 설정할 수 있다. NGINX의 설정 파일에서 proxy_protocol을 활성화하고, 백엔드로 전달되는 클라이언트 IP를 읽도록 설정한다.

http {
    set_real_ip_from 0.0.0.0/0;
    real_ip_header proxy_protocol;

    server {
        listen 80 proxy_protocol;
        location / {
            proxy_pass http://backend_service;
        }
    }
}

 

🚀 istio에 적용하기

Istio의 Ingress Gateway에서 Proxy Protocol을 지원하도록 하려면 EnvoyFilter를 사용하여 설정을 추가할 수 있다. 다음은 Istio의 Ingress Gateway에 Proxy Protocol을 적용하는 예시이다. 먼저, EnvoyFilter를 통해 Proxy Protocol listener filter를 활성화하고 Istio Ingress Gateway가 Proxy Protocol을 처리하도록 설정한다.

 

참고문서

https://istio.io/latest/docs/ops/configuration/traffic-management/network-topologies/#proxy-protocol

 

Configuring Gateway Network Topology

How to configure gateway network topology.

istio.io

 

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: proxy-protocol
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      istio: ingressgateway
  configPatches:
  - applyTo: LISTENER
    patch:
      operation: MERGE
      value:
        listener_filters:
        - name: envoy.filters.listener.proxy_protocol
        - name: envoy.filters.listener.tls_inspector

 

Proxy Protocol 사용 시 고려 사항

백엔드 서버의 Proxy Protocol 지원 여부

백엔드 서버가 Proxy Protocol을 지원하지 않는 경우, Proxy Protocol 헤더를 인식하지 못해 잘못된 데이터로 처리될 수 있다. 따라서 백엔드 서버가 Proxy Protocol을 지원하는지 확인해야 한다.

 

로드 밸런서와 백엔드 서버 간 설정 일치

Proxy Protocol을 활성화할 때는 로드 밸런서와 백엔드 서버 모두 동일한 설정을 적용해야 한다. 특히 프록시 서버가 올바르게 설정되어 있지 않으면 요청이 실패할 수 있다.

 

프로토콜 및 계층에 따른 사용 방법

Proxy Protocol은 TCP/UDP 프로토콜을 지원하므로 다양한 네트워크 환경에서 활용할 수 있다. 하지만 L7 로드 밸런싱을 사용하는 환경에서는 X-Forwarded-For를 사용하는 것이 더 적합할 수 있다.