NGINX를 투명 프록시 (transparent proxy)로 사용하기

이 포스트에서는 NGINX Open Source와 NGINX Plus를 업스트림 서버로의 트래픽을 위한 투명 프록시(transparent proxy)로 구성하는 방법에 대해 설명합니다. 이는 IP Transparency을 구현하기 위해 패킷의 Source IP 주소를 위조하는 데 투명 프록시를 사용할 수 있다는 것과 UDP 트래픽에 대해 Direct Server Return이라고 불리는 로드 밸런싱 모드를 구현하는 방법에 대해 설명합니다.

이 포스트의 정보는 NGINX Open Source와 NGINX Plus 모두에 적용됩니다. 간결함을 위해 NGINX Plus만 언급하겠습니다.

목차

1. 소개: 표준 Layer 7 리버스 프록시의 패킷 흐름
1-1. Layer 7 리버스 프록시 모드의 이점 및 제한 사항
2. 방법 1: IP Transparency
2-1. NGINX Plus 로드 밸런서에서 HTTP 리버스 프록시 생성
2-2. IP Transparency를 위한 NGINX Plus 및 업스트림 구성
2-3. IP Transparency 구성 테스트
2-4. 요약: IP Transparency 구성이 어떻게 작동하는가?
3. 방법 2: Direct Server Return(DSR)
3-1. DSR 구성은 IP Transparency와 어떻게 다른가요?
3-2. 표준 UDP 리버스 프록시 서비스 생성
3-3. DSR을 위한 NGINX Plus 및 UDP 업스트림 구성
3-4. DSR용 NGINX Plus 프록시 구성
3-5. Router NAT – 중간 라우터에서 송신 패킷 재작성
3-6. Origin NAT – 각 업스트림 서버에서 송신 패킷 재작성
3-7. DSR 구성 테스트
3-8. 요약: DSR 구성은 어떻게 작동합니까?
4. 문제 해결
4-1. Root로 실행
4-2. 핑으로 테스트
4-3. 겹치는 IP 범위 없음
4-4. 어디에서나 tcpdump 사용
4-5. 라우팅 테이블 확인
4-6. 누락된 패킷
5. 업스트림 서버가 외부 서버에 도달하도록 설정
6. NGINX 프록시 지원 받기

NGINX 투명 프록시 (transparent proxy) 요약

NGINX Plus는 Layer 7 리버스 프록시로 작동합니다. 이를 통해 NGINX Plus는 관리하는 네트워크 요청에 대해 여러 최적화와 개선을 적용할 수 있습니다.

결과적으로, 상위 (로드 밸런싱된)서버는 모든 트래픽이 NGINX Plus 프록시의 IP 주소에서 시작된 것으로 간주합니다. 이는 상위 서버가 인증 또는 로깅을 위해 실제 Origin IP 주소(원격 클라이언트 IP)를 식별해야 하는 경우에 문제가 될 수 있습니다.

HTTP 및 HTTPS 트래픽에 대해서는 X-Forwarded-For HTTP 헤더나 PROXY 프로토콜을 사용하여 효과적인 해결책이 있습니다. 그러나 이 포스트에서는 TCP 및 UDP 트래픽에 적용되는 두 가지 추가적인 방법에 대해 설명합니다.

  • IP Transparency는 상위 서버가 각 연결이 원격 클라이언트에서 시작되었다고 인식하도록 합니다. 이는 TCP 및 UDP 기반 프로토콜에 적용됩니다.
  • Direct Server Return(DSR)은 업스트림 서버의 응답이 원격 클라이언트로 직접 이동하고 중간 로드 밸런서를 우회하도록 추가로 조정합니다. 이는 UDP 기반 프로토콜에 적용 가능하며, Origin 서버나 중간 라우터에서 NAT(network address translation)을 수행하여 구현할 수 있습니다.
 방법 1 – IP Transparency방법 2a – DSR
(Router NAT)
방법 2b – DSR
(Origin NAT)
지원되는
프로토콜
TCP 기반, UDP 기반UDP 기반UDP 기반
업스트림 서버에 의한 트래픽 라우팅NGINX Plus Proxy로 라우팅 되고 종료되는 모든 egress 트래픽중간 NGINX Plus 서버를 통해 라우팅 되는 모든 egress 트래픽모든 트래픽이 정상적으로 라우팅됨
성능표준: egress 트래픽은 NGINX Plus에서 종료우수: egress 트래픽은 중간 NGINX Plus 서버에 의해 전달최상: egress 트래픽이 NGINX Plus를 우회하여 원격 클라이언트로 직접 라우팅
Health checks기본적으로 수동적
활성 지원
활성 필요
수동 불가능
활성 필요
수동 불가능
필수 구성
NGINX Plus proxy의 TCP/UDPTCP: 기본적으로 작동
UDP: proxy_responses 1
TCP: 지원하지 않음
UDP: proxy_responses 0
TCP: 지원하지 않음
UDP: proxy_responses 0
패킷 처리는 어디서 어떻게 되나요?iptables NGINX Plus proxy에서 종료됩니다.중간 NGINX Plus 서버에서 tc nat rewrites업스트림 서버에서 tc nat rewrites
NGINX Plus proxy의
네트워킹 구성
송신 패킷을 캡처하는 iptablesIP forwarding과 stateless NAT
없음
업스트림 서버의
네트워킹 구성
NGINX Plus를 기본 경로로 지정NGINX Plus를 기본 경로로 지정Stateless NAT

IP Transparency와 DSR을 배포하고 문제를 해결하는 것은 복잡합니다. 이러한 구성을 구현해야 하는 경우는 표준 리버스 프록시 모드가 애플리케이션이나 서비스에 충분하지 않은 경우에만 해당됩니다.

1. 소개: 표준 Layer 7 리버스 프록시 의 패킷 흐름

NGINX Plus는 패킷을 단순히 전달하는 스위치나 라우터와 달리 Layer 7 리버스 프록시로 작동합니다. 이 작동 모드에서 NGINX Plus는 원격 클라이언트와 선택된 상위 서버 간의 통신을 제어하기 위해 HTTP 및 TCP 트래픽의 경우에는 별도의 클라이언트 측 및 업스트림 측 TCP 연결, UDP 세션을 관리합니다.

다이어그램은 NGINX Plus가 리버스 프록시 서버 역할을 할 때 TCP 패킷 및 UDP 데이터그램이 처리되는 방식을 보여줍니다.

표준 리버스 프록시 역할을 하는 NGINX Plus로 트래픽 처리

  1. 원격 클라이언트는 NGINX Plus 리버스 프록시의 공개된 IP 주소와 포트로 직접 TCP 연결을 생성하거나 UDP 데이터그램을 전송합니다. NGINX Plus는 TCP 연결이나 세션을 종료하고 요청 데이터를 읽습니다.
  2. 그런 다음 NGINX Plus는 선택한(로드 밸런싱된) 업스트림 서버에 새 연결을 만듭니다(또는 기존의 Idle connection).
  3. NGINX Plus가 업스트림 서버로 요청을 작성할 때, 연결을 NGINX Plus의 내부 IP 주소에서 시작됩니다.
  4. 업스트림 서버가 요청에 대한 응답을 보낼 때, 데이터는 NGINX Plus의 내부 IP주소로 전송됩니다.
  5. NGINX Plus는 업스트림 측 연결에서 응답 데이터를 수신합니다. 응답을 처리하거나 수정할 수 있습니다(예: HTTP 응답에 압축 적용).
  6. 그런 다음 NGINX Plus는 클라이언트 측 연결에 응답 데이터를 기록합니다.

이 표준 리버스 프록시 작동 모드의 결과로 업스트림 서버는 TCP 및 UDP 트래픽이 로컬 NGINX Plus에서 시작되었다고 인식합니다.

1-1. Layer 7 리버스 프록시 모드의 이점 및 제한 사항

Layer 7 리버스 프록시 작동 모드는 HTTP 및 TCP 트래픽에 대해 상당한 성능 향상과 효율성을 제공합니다(TCP 최적화, 버퍼링, HTTP keepalive 재사용 등). 그러나 업스트림 서버가 연결 또는 세션의 실제 Origin IP 주소를 확인해야 하는 경우(인증 및 접근 제어, 속도 제한, 로깅 등의 목적) 문제가 될 수 있습니다.

일부 프로토콜의 경우 NGINX Plus는 X-Forwarded-For HTTP 헤더 또는 PROXY 프로토콜을 사용하여 업스트림 서버에 Origin IP 주소를 제공할 수 있습니다. 이 포스트는 NGINX Plus R10에서 도입된 proxy_bind 지시문의 transparent 매개변수로 가능해진 두 가지 추가적인 방법을 설명합니다.

2. 방법 1: IP Transparency

IP Transparency는 리버스 프록시의 존재를 숨기고, Origin 서버에서 IP 패킷이 클라이언트의 IP 주소에서 시작되었다고 인식하도록 하는 것을 목표로 합니다. IP Transparency는 TCP 기반 및 UDP 기반 프로토콜과 함께 사용할 수 있습니다.

2-1. NGINX Plus 로드 밸런서에서 HTTP 리버스 프록시 생성

IP Transparency를 시연하기 위해 먼저 몇 가지 간단한 연결 정보로 응답하는 4개의 웹 서버로 구성된 로드 밸런싱된 클러스터를 만듭니다.

1. 업스트림 서버 그룹 간에 트래픽 부하를 분산하는 간단한 HTTP 가상 서버를 구성합니다.

# in the 'http' context
server {
    listen 80;

    location / {
        proxy_pass http://http_upstreams;
    }
}

upstream http_upstreams {
    server 172.16.0.11;
    server 172.16.0.12;
    server 172.16.0.13;
    server 172.16.0.14;
}

2. 업스트림 서버가 연결이 NGINX Plus 로드 밸런서에서 시작되었음을 확인하려면 NGINX Plus 로드 밸런서에 대한 정보를 return하는 간단한 가상 서버를 사용하여 4개(172.16.0.11 ~ 172.16.0.14) 각각에 NGINX Plus 웹 서버를 구성합니다.

# in the 'http' context
server {
    listen 80;

    location / {
        return 200 "Hello from $hostname. You connected from $remote_addr:$remote_port to $server_addr:$server_port\n";
    }
}

이 구성을 테스트할 때 업스트림은 연결이 로컬 NGINX Plus IP 주소 (172.16.0.1)에서 시작되었다고 보고합니다.

$ for i in {1..4}; do curl http://192.168.99.10 ; done
Hello from dev1. You connected from 172.16.0.1:42723 to 172.16.0.11:80
Hello from dev2. You connected from 172.16.0.1:39117 to 172.16.0.12:80
Hello from dev3. You connected from 172.16.0.1:54545 to 172.16.0.13:80
Hello from dev4. You connected from 172.16.0.1:57020 to 172.16.0.14:80

2-2. IP Transparency를 위한 NGINX Plus 및 업스트림 구성

NGINX Plus R10 이상(및 NGINX Open Source 1.11.0 이상)은 업스트림 트래픽의 소스 주소를 스푸핑할 수 있습니다. proxy_bind 지시문에 투명 매개변수를 포함합니다. 가장 일반적으로 소스 주소를 원격 클라이언트의 주소로 설정합니다.

proxy_bind $remote_addr transparent;

그러나 이 간단한 단계는 원격 클라이언트에 대한 응답(Egress) 트래픽이 올바르게 처리되도록 해야 하기 때문에 중요한 문제를 만듭니다. 응답 트래픽은 NGINX Plus로 라우팅되어야 하며 NGINX Plus는 업스트림 TCP 연결을 종료해야 합니다. 그런 다음 NGINX Plus는 클라이언트 TCP 연결을 통해 응답 트래픽을 원격 클라이언트로 보냅니다.

NGINX Plus 로드 밸런서와 각 업스트림 서버 모두에 몇 가지 구성을 변경해야 합니다.

1. NGINX Plus 로드 밸런서에서 root로 실행되도록 worker process를 구성하여 업스트림 소켓을 임의의 주소에 바인딩할 수 있습니다.

/etc/nginx/nginx.conf의 기본(최상위) 컨텍스트에서 NGINX Plus worker process의 ID를 root로 설정하는 user 지시문을 포함합니다.

# in the 'main' context
# 'user daemon' is the default; change to 'user root' with transparent proxy_bind
user root;

2. NGINX Plus 로드 밸런서에서 각 연결이 원격 클라이언트 주소에서 시작되는지 확인합니다.

transparent 매개변수가 있는 proxy_bind 지시문을 가상 서버 구성에 추가합니다.

# in the 'http' context
server {
    listen 80;

    location / {
        proxy_bind $remote_addr transparent;
        proxy_pass http://http_upstreams;
    }
}

3. NGINX Plus 로드 밸런서에서 업스트림 서버에서 return 패킷을 캡처하여 NGINX Plus로 전달하도록 iptables를 구성합니다.

이 예에서는 iptablesip rule 명령을 실행하여 IP 범위 172.16.0.0/28로 표시되는 서버에서 포트 80의 모든 TCP 트래픽을 캡처합니다.

# ip rule add fwmark 1 lookup 100
# ip route add local 0.0.0.0/0 dev lo table 100
# iptables -t mangle -A PREROUTING -p tcp -s 172.16.0.0/28 --sport 80 -j MARK --set-xmark 0x1/0xffffffff

다음 명령을 실행하여 iptables mangle 테이블에서 현재 구성을 나열(-L)합니다.

# iptables -t mangle -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
MARK       tcp  --  172.16.0.0/28        anywhere             tcp spt:http MARK set 0x1

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination

업스트림 서버에서 모든 return 트래픽이 NGINX Plus로 전달되도록 라우팅을 구성합니다.

각 업스트림 서버에서 기존 기본 경로를 제거하고 기본 경로가 NGINX Plus 로드 밸런서/리버스 프록시의 IP 주소가 되도록 구성합니다. 이 IP 주소는 업스트림 서버의 인터페이스 중 하나와 동일한 서브넷에 있어야 합니다.

# route del default gw 10.0.2.2
# route add default gw 172.16.0.1

라우팅 테이블이 적절하게 보이는지 확인합니다.

# route -n
Kernel IP routing table
Destination   Gateway     Genmask        Flags Metric Ref Use Iface
0.0.0.0       172.16.0.1  0.0.0.0        UG    0      0     0 eth2
10.0.2.0      0.0.0.0     255.255.255.0  U     0      0     0 eth0
172.16.0.0    0.0.0.0     255.255.255.0  U     0      0     0 eth2
192.168.56.0  0.0.0.0     255.255.255.0  U     0      0     0 eth1

업스트림 서버가 외부 서버에 연결할 수 있어야 하는 경우 트래픽을 전달하고 위장하도록 새로운 NGINX Plus Gateway도 구성해야 합니다. 아래의 업스트림이 외부 서버에 도달하도록 설정을 참조하십시오.

2-3. IP Transparency 구성 테스트

이제 NGINX Plus에 요청을 전송하여 구성을 테스트할 수 있습니다. 업스트림 서버에서 직접 라우팅할 수 없는 원격 IP 주소에서 요청을 보내고 있는지 확인하십시오.

$ for i in {1..4}; do curl http://192.168.99.10 ; done
Hello from dev1. You connected from 192.168.99.1:60729 to 172.16.0.11:80
Hello from dev2. You connected from 192.168.99.1:43070 to 172.16.0.12:80
Hello from dev3. You connected from 192.168.99.1:45749 to 172.16.0.13:80
Hello from dev4. You connected from 192.168.99.1:46609 to 172.16.0.14:80

이제 연결이 NGINX Plus 로드 밸런서의 로컬 주소가 아닌 원격 클라이언트의 IP 주소(192.168.99.1)에서 시작되는 것으로 나타납니다.

구성이 작동하지 않으면 아래 문제 해결을 참조하십시오.

2-4. 요약: IP Transparency 구성이 어떻게 작동하는가?

  • NGINX Plus는 원격 클라이언트(192.168.99.1)로부터 HTTP 요청을 받습니다.
  • NGINX Plus는 연결할 업스트림 서버(예: 172.16.0.11)를 선택하여 부하 분산 결정을 내립니다. NGINX Plus는 연결하기 전에 업스트림 소켓을 원격 클라이언트의 주소에 바인딩합니다.
  • 업스트림 서버는 원격 클라이언트에서 직접 시작된 것처럼 보이는 연결을 수신합니다.
  • 업스트림 서버가 응답하여 패킷을 원격 클라이언트 주소로 지정하고 NGINX Plus(기본 라우터)를 통해 라우팅합니다.
  • NGINX Plus 로드 밸런서의 iptables 규칙은 이러한 패킷을 표시하고 라우팅은 이를 로컬로 전달합니다.
  • NGINX Plus는 응답을 읽습니다.
  • 그런 다음 NGINX Plus는 원격 클라이언트에 응답을 보냅니다.

최종 결과는 업스트림 서버의 관점에서 연결이 원격 클라이언트에서 직접 시작되는 것처럼 보입니다.

3. 방법 2: Direct Server Return(DSR)

Direct Server Return (DSR)는 IP Transparency 개념의 확장입니다. IP Transparency에서는 상위 서버가 원격 클라이언트에서 시작된 것처럼 보이는 패킷을 받습니다. DSR에서는 추가로 상위 서버가 직접 원격 클라이언트에 응답하며, 응답 패킷은 로드 밸런서를 완전히 우회합니다.

DSR은 로드 밸런서의 로드를 줄이기 때문에 약간의 성능 이점을 제공할 수 있지만 여러 가지 제한 사항이 있습니다.

  • 로드 밸런서는 return 패킷을 볼 수 없으므로 업스트림 서버가 응답하는지 또는 실패했는지 감지할 수 없습니다.
  • 로드 밸런서는 업스트림을 선택하기 전에 첫 번째 패킷 이후의 요청을 검사할 수 없으므로 로드 밸런싱 결정(콘텐츠 기반 라우팅)을 내리는 기능이 매우 제한됩니다.
  • 로드 밸런서는 SSL/TLS와 같은 어떠한 형태의 협상 또는 상태 저장 처리에도 참여할 수 없습니다.
  • 캐싱, HTTP 다중화 및 로깅과 같은 대부분의 다른 ADC(Application Delivery Controller) 기능은 DSR에서 사용할 수 없습니다.

DSR은 TCP 프로토콜에 제한적으로 사용되며 어떤 경우에도 NGINX Plus의 리버스 프록시 아키텍처는 DSR/TCP에 적용할 수 없습니다.

UDP 프로토콜은 TCP의 연결 의미 체계가 전혀 없기 때문에 훨씬 더 간단합니다. DNS와 같은 UDP 프로토콜에 대해 DSR을 지원하도록 NGINX Plus를 구성할 수 있으며 이는 성능상의 이점을 제공할 수 있습니다. 구체적으로, DSR은 NGINX Plus가 응답 패킷을 예상하여 UDP 소켓을 열어 둘 필요가 없고(확장성이 향상됨) 응답 패킷이 NGINX Plus의 레이어 7 처리를 완전히 우회할 수 있음을 의미합니다(대기 시간 감소).

3-1. DSR 구성은 IP Transparent와 어떻게 다른가요?

UDP 트래픽에 대한 IP Transparency 구성과 DSR 구성 사이에는 세 가지 차이점이 있습니다.

  • NGINX Plus는 업스트림 서버에 데이터그램을 보낼 때 Remote 클라이언트 IP 주소와 포트를 모두 스푸핑해야 합니다(proxy_bind 포트 구성).
  • NGINX Plus는 업스트림 서버(proxy_responses 0 지시문)에서 응답 데이터그램을 예상하도록 구성하면 안 됩니다.
  • 로드 밸런서의 public 주소와 일치하도록 return 데이터그램의 소스 주소를 다시 작성하려면 추가 단계가 필요합니다.

또한 업스트림 서버에 대해 활성 상태 검사를 수행하도록 NGINX Plus를 구성해야 합니다. NGINX Plus는 서버가 보낸 응답 패킷을 관찰하지 않기 때문에 서버가 정상인지 확인하기 위해 일반적인 수동 검사에 의존할 수 없습니다.

3-2. 표준 UDP 리버스 프록시 서비스 생성

DSR을 시연하려면 먼저 http://www.example.com이라는 이름 조회를 위해 서로 다른 IP 주소로 응답하는 4개의 DNS 서버로 구성된 로드 밸런싱된 클러스터를 만듭니다.

DNS 서버 간에 로드 밸런싱을 수행하는 간단한 리버스 프록시 구성을 구성합니다.

# in the 'stream' context
server {
    listen 53 udp;

    proxy_responses 1;
    proxy_timeout 1s;
    proxy_pass dns_upstreams;
}

upstream dns_upstreams {
    server 172.16.0.11:53;
    server 172.16.0.12:53;
    server 172.16.0.13:53;
    server 172.16.0.14:53;
}

proxy_responsesproxy_timeout 지시문은 기본 health check 구현합니다. 업스트림 서버가 1초 이내에 1개의 응답을 보내지 않으면 NGINX Plus는 서버가 실패한 것으로 간주하고 DNS 요청을 다시 시도합니다.

http://www.example.com 조회에 자체 IP 주소로 응답하도록 각 DNS 서버를 구성합니다.

$TTL   	604800
@           IN          SOA         ns1.example.com. admin.example.com. (
                              2           ; Serial
                         604800           ; Refresh
                          86400           ; Retry
                        2419200           ; Expire
                         604800 )         ; Negative Cache TTL

example.com.    IN      NS      ns1.example.com.

ns1             IN      A       172.16.0.11
www             IN      A       172.16.0.11

테스트를 통해 NGINX Plus가 DNS 서버 간에 요청을 로드 밸런싱하고 있음이 분명해졌습니다.

$ for i in {1..4} ; do dig +short @192.168.99.10 www.example.com ; done
172.16.0.11
172.16.0.12
172.16.0.13
172.16.0.14

3-3. DSR을 위한 NGINX Plus 및 UDP 업스트림 구성

NGINX Plus R10 이상(및 NGINX Open Source 1.11.2 이상)은 업스트림 트래픽의 Source Address와 포트를 모두 스푸핑할 수 있습니다. proxy_bind 지시문에 투명 매개변수를 포함합니다.

proxy_bind $remote_addr:$remote_port transparent;

이를 통해 업스트림 서버는 전체 Source IP 주소를 관찰할 수 있으므로 원격 클라이언트로 직접 전송되는 응답 데이터그램을 구성할 수 있습니다.

업스트림 서버는 올바른 IP 대상으로 응답(“egress”) 패킷을 생성하지만 로컬 IP 주소를 Source Address로 사용합니다. Source Address는 클라이언트가 원래 연결된 NGINX Plus 로드 밸런서의 IP 주소와 포트로 다시 작성해야 합니다.

두 가지 방법이 가능합니다.

  • Router NAT – 중간 라우터(예: NGINX Plus 프록시)에서 이그레스 패킷 재작성
  • Origin NAT – 각 업스트림 DNS 서버를 떠날 때 송신 패킷을 다시 작성합니다.

두 방법 모두 tc 명령으로 구성하는 상태 비저장 NAT 기능을 사용합니다. 업스트림 서버가 인터넷에 직접 연결된 경우(토폴로지는 리턴 패킷이 사용자가 제어할 수 있는 중간 라우터를 통해 전송되지 않음을 의미함) Origin NAT 방법을 선택해야 합니다.

3-4. DSR용 NGINX Plus 프록시 구성

응답 패킷이 NGINX Plus로 전달되지 않으므로 표준 UDP 리버스 프록시 서비스 생성에서 구성한 상태 확인을 비활성화해야 합니다. proxy_responses 지시문을 수정하고 proxy_timeout 지시문을 비활성화합니다. 이제 NGINX Plus는 응답을 기다리지 않으며 응답을 받지 못했다고 업스트림 서버가 실패했다고 결론을 내리지 않습니다. 이 검사를 비활성화하면 NGINX Plus가 소켓 리소스를 즉시 재사용할 수도 있습니다.

또한 $remote_addr 및 $remote_port 변수를 proxy_bind 지시문의 첫 번째 매개변수에 포함하여 NGINX Plus가 업스트림 서버로 전송되는 데이터그램에서 원래 Source Address와 Source Port를 모두 보존하도록 합니다.

# in the 'stream' context
server {
    listen 53 udp;

    proxy_bind $remote_addr:$remote_port transparent;
    proxy_responses 0;
    #proxy_timeout 1s;
}

3-5. Router NAT – 중간 라우터에서 송신 패킷 재작성

단일 중간 라우터에서 송신 패킷을 다시 작성할 수 있습니다. 예를 들어 업스트림 서버가 NGINX Plus 로드 밸런서 뒤에 있는 사설 네트워크에 있는 경우 로드 밸런서를 기본 경로로 사용하고 전달되는 패킷을 다시 작성할 수 있습니다.

1. NGINX Plus 서버를 통해 나가는 모든 트래픽을 라우팅하도록 각 업스트림 서버를 구성합니다.

# route add default gw nginx-ip-address

2. IP 트래픽을 전달하도록 NGINX Plus 서버를 구성합니다.

# sysctl -w net.ipv4.ip_forward=1

3. 상태 비저장 NAT 재작성을 수행하도록 NGINX Plus 서버를 구성합니다.

# tc qdisc add dev eth0 root handle 10: htb
# tc filter add dev eth0 parent 10: protocol ip prio 10 u32 match ip src 172.16.0.11 match ip sport 53 action nat egress 172.16.0.11 192.168.99.10
# tc filter add dev eth0 parent 10: protocol ip prio 10 u32 match ip src 172.16.0.12 match ip sport 53 action nat egress 172.16.0.12 192.168.99.10
# tc filter add dev eth0 parent 10: protocol ip prio 10 u32 match ip src 172.16.0.13 match ip sport 53 action nat egress 172.16.0.13 192.168.99.10
# tc filter add dev eth0 parent 10: protocol ip prio 10 u32 match ip src 172.16.0.14 match ip sport 53 action nat egress 172.16.0.14 192.168.99.10

각 업스트림 서버의 적절한 송신 인터페이스와 적절한 IP 주소를 선택해야 합니다.

상태 비저장 NAT에 대한 자세한 내용은 tc nat 매뉴얼 페이지를 참조하십시오. 구성에 따라 src 및 egress old 매개변수에 CIDR 마스크를 사용하여 tc 필터 명령을 단일 명령으로 줄일 수 있습니다.

현재 tc 필터 구성을 표시하려면 다음 명령을 실행하십시오.

# tc filter show dev eth0

3-6. Origin NAT – 각 업스트림 서버에서 송신 패킷 재작성

업스트림 서버에서 네트워킹을 구성할 수 있는 경우, 특히 인터넷에 직접 연결된 경우 다음 구성을 사용할 수 있습니다. 각 업스트림 서버에 적용해야 합니다.

상태 비저장 NAT 재작성을 수행하도록 각 업스트림 서버를 구성합니다.

# tc qdisc add dev eth0 root handle 10: htb
# tc filter add dev eth0 parent 10: protocol ip prio 10 u32 match ip src 172.16.0.11 match ip sport 53 action nat egress 172.16.0.11 192.168.99.10

각 업스트림에서 적절한 인터페이스와 IP 주소를 선택했는지 확인하십시오.

3-7. DSR 구성 테스트

구성을 테스트하려면 NGINX Plus 로드 밸런서에 DNS 요청을 보내고 업스트림 서버 간에 로드 밸런싱되는지 확인합니다.

DSR에는 직접 눈에 보이는 효과가 없습니다. Proxy_responses 0 지시문을 사용하여 NGINX Plus가 응답 패킷을 기대하지 않도록 구성했지만 DNS 클라이언트가 부하 분산된 응답을 수신한다면 제대로 작동하는지 확신할 수 있습니다. 아래 문제 해결에 설명된 대로 tcpdump를 사용하여 패킷 흐름을 더 자세히 관찰할 수 있습니다.

3-8. 요약: DSR 구성은 어떻게 작동합니까?

  • NGINX Plus는 Remote 클라이언트(192.168.99.1:port)로부터 UDP 데이터그램을 수신합니다.
  • NGINX Plus는 데이터그램 콘텐츠를 쓸 업스트림 서버(예: 172.16.0.11)를 선택하여 부하 분산 결정을 내립니다. NGINX Plus는 연결하기 전에 업스트림 소켓의 로컬 측을 원격 클라이언트의 IP 주소 및 포트에 바인딩합니다.
  • 업스트림 서버는 NGINX Plus에서 보낸 데이터그램을 수신하는데, 이는 분명히 Remote 클라이언트 주소와 포트에서 직접 발생합니다.
  • 업스트림 서버가 응답하여 데이터그램을 Remote 클라이언트로 다시 보냅니다. 업스트림 서버는 응답 데이터그램의 Source IP Address와 포트를 자신의 로컬 IP 주소와 포트로 설정합니다.
  • Source IP 주소(및 필요한 경우 포트)는 업스트림 서버(origin NAT 구성) 또는 중간 라우터(router NAT 구성)에 의해 다시 작성됩니다.
  • 원격 클라이언트는 올바른 4-튜플(Source 및 대상 IP 주소와 포트)로 지정된 데이터그램을 수신합니다.
  • NGINX Plus는 응답 데이터그램을 관찰하지 않고 업스트림 소켓을 즉시 닫습니다.

최종 결과는 응답 패킷이 NGINX Plus의 레이어 7 처리를 우회하고 직접 Remote 클라이언트로 이동한다는 것입니다.

4. NGINX 프록시 문제 해결

IP Transparency 또는 DSR이 예상대로 작동하지 않는 경우 다음 제안을 사용하여 가능한 원인을 조사하십시오.

4-1. Root로 실행

NGINX Plus worker process가 root로 실행되도록 구성되었는지 확인합니다. 그렇지 않은 경우 NGINX Plus가 소켓을 nonlocal 주소에 바인딩하려고 시도할 때 error log에 다음과 유사한 오류 메시지가 표시됩니다.

setsockopt(IP_TRANSPARENT) failed (1: Operation not permitted) while connecting to upstream, client: 192.168.99.1, server: , request: "GET / HTTP/1.1", upstream: "http://172.16.0.11:80/", host: "192.168.99.10"

4-2. ping으로 테스트

NGINX Plus 프록시에서 클라이언트와 서버를 ping할 수 있는지 확인합니다. 업스트림 서버는 먼저 필요한 라우팅 구성을 생성하고 패킷을 전달하도록 NGINX Plus 중개자를 구성하지 않는 한 Remote 클라이언트 IP 주소를 ping할 수 없습니다.

4-3. 겹치는 IP 범위 없음

Remote 클라이언트가 사용하는 IP 서브넷이 업스트림 서버에 직접 연결되어 있지 않은지 확인하십시오. 그렇다면 두 가지 문제가 발생할 수 있습니다.

  • Source IP 주소가 다른 인터페이스의 서브넷과 연결되어 있기 때문에 Linux의 “reverse path filtering” 보호 기능은 NGINX Plus의 패킷을 자동으로 거부할 수 있습니다.
  • Return 패킷은 기본 경로를 사용하지 않고 대신 로컬로 연결된 Remote 클라이언트로 직접 전송됩니다.

4-4. 어디에서나 tcpdump 사용

구성을 구축하고 각 중간 단계를 테스트할 때 각 서버에서 tcpdump를 계속 실행하여 패킷이 각 단계에서 올바른 endpoiont로 전송되고 수신되는지 확인합니다.

$ sudo tcpdump -i any -n tcp port 80

아래 나열된 확인 사항을 사용하여 비정상적인 동작을 조사합니다.

4-5. 라우팅 테이블 확인

특히 업스트림 서버에 주의하면서 각 서버의 라우팅 테이블을 주의 깊게 확인하십시오.

# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.16.0.1      0.0.0.0         UG    0      0        0 eth2
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
172.16.0.0      0.0.0.0         255.255.255.0   U     0      0        0 eth2
192.168.56.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1

예기치 않은 경로가 있습니까? 흐름의 모든 패킷이 올바른 대상으로 라우팅되는지 확인할 수 있습니까? iptables 및 라우터 NAT 구성에서 모든 송신 패킷은 중간 NGINX Plus 프록시를 통해 라우팅되어야 합니다.

4-6. 누락된 패킷

패킷이 예기치 않게 삭제된 경우(tcpdump는 패킷이 한 시스템에서 전송되었지만 다른 시스템에서는 수신되지 않음을 보여줌) reverse path filtering이 잠재적인 범인입니다. reverse path filtering을 일시적으로 비활성화하려면 다음 명령을 실행합니다.

# for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $f ; done

5. 업스트림 서버가 외부 서버에 도달하도록 설정

업스트림 서버가 사설 네트워크에 상주하고 NGINX Plus(또는 다른 서버)를 기본 게이트웨이로 사용하는 경우 업스트림 서버가 외부(인터넷) 호스트에 도달할 수 있도록 게이트웨이를 구성할 수 있습니다.

게이트웨이가 업스트림 서버에서 패킷을 전달할 수 있도록 IP 전달을 활성화해야 합니다. IP 전달은 일반적으로 기본적으로 비활성화되어 있습니다. 서버에 라우팅 가능한 IP 주소가 없는 경우(172.16.0.0/24와 같은 private 주소 사용) 게이트웨이 서버의 외부 인터페이스에서 IP 위장을 구성해야 합니다.

# sysctl -w net.ipv4.ip_forward=1
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

내부 업스트림 서버에서 외부 서버를 ping할 수 있는지 확인합니다.

root@dev1:~# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=61 time=6.72 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=61 time=5.49 ms

현재 전달, 라우팅 및 iptables nat 구성을 표시하려면 다음 세 가지 명령을 실행하십시오.

# sysctl net.ipv4.ip_forward
# route -n
# iptables -t nat -L

6. NGINX 프록시 지원 받기

IP Transparency 또는 Direct Server Return에 대한 구성은 복잡하며 다른 중간 네트워크 디바이스는 패킷을 삭제하거나 다시 작성하여 배포에 영향을 줄 수 있습니다. 도움이 필요하시면 NGINX팀이 도와드리겠습니다.

NGINX Plus로 IP Transparency 및 DSR을 직접 살펴보십시오. 지금 무료 30일 평가판을 시작하거나 사용 사례에 대해 논의하려면 NGINX STORE에 문의하십시오.

사용 사례에 대해 최신 소식을 빠르게 전달받고 싶으시면 아래 뉴스레터를 구독하세요.