透過プロキシとしてのNGINXおよびNGINX PlusによるIP透過性とDirect Server Return

NGINX | 2016年9月14日

このブログ記事では、アップストリームサーバーへのトラフィックに対する透過プロキシとしてNGINX Open SourceとNGINX Plusを構成する方法について説明します。また、透過プロキシを使用してパケットの送信元IPアドレスを偽装し、IP Transparencyを実現する方法と、UDPトラフィックにDirect Server Returnと呼ばれる負荷分散モードを実装する方法についても解説します。

本記事の情報は、NGINX Open SourceとNGINX Plusの両方に適用されます。簡潔にするため、以降はNGINX Plusのみを記載します。

編集者注:NGINX Plus R10の新機能を詳しく解説するブログシリーズの第5回です。

オンデマンドウェビナー「NGINX Plus R10の新機能」もぜひご覧ください。

まとめ

NGINX Plusはレイヤー7リバースプロキシとして動作します。これにより、NGINX Plusは処理するネットワークリクエストにさまざまな最適化や機能強化を適用できます。

その結果、アップストリーム(負荷分散先)サーバーからは、すべてのトラフィックがNGINX Plusプロキシ上のIPアドレスから送信されているように見えます。たとえば認証やログ記録のために、アップストリームサーバーが実際の送信元IPアドレス(リモートクライアントのIPアドレス)を特定する必要がある場合、これが課題となります。

HTTPおよびHTTPSトラフィックには、X-Forwarded-For HTTPヘッダーまたはPROXY protocolを使用する有効な回避策があります。この記事では、TCPおよびUDPトラフィックに適用できる、さらに2つの方法について説明します。

  • IP Transparencyにより、アップストリームサーバーでは、各接続がその接続を開始したリモートクライアントから発信されたものとして認識されます。TCPおよびUDPベースのプロトコルに適用できます。
  • Direct Server Return(DSR)ではさらに、アップストリームサーバーからの応答が中間のロードバランサーを経由せず、リモートクライアントに直接送信されるようにします。UDPベースのプロトコルに適用でき、オリジンサーバーまたは中間ルーターでNAT(ネットワークアドレス変換)を実行することで実装できます。

方式1 – IP透過方式 方式2a – DSR(ルーター NAT) 方式2b – DSR(オリジン NAT)対応プロトコル TCPベースおよびUDPベース UDPベースのみ UDPベースのみアップストリームサーバーによるトラフィックルーティング すべての送信トラフィックをNGINX Plusプロキシにルーティングして終端 すべての送信トラフィックを中間のNGINX Plusサーバー経由でルーティング すべてのトラフィックを通常どおりルーティングパフォーマンス 標準:送信トラフィックをNGINX Plusプロキシで終端 より良好:送信トラフィックを中間のNGINX Plusサーバーが転送 最良:送信トラフィックをNGINX Plusを経由せず、リモートクライアントに直接ルーティングヘルスチェック デフォルトはパッシブ、アクティブもサポート アクティブが必須、パッシブは不可 アクティブが必須、パッシブは不可必要な設定NGINX Plusプロキシ上のTCPおよびUDP TCP:デフォルトで動作
UDP:proxy_responses 1 TCP:非対応
UDP:proxy_responses 0 TCP:非対応
UDP:proxy_responses 0パケットの処理方法と処理場所 iptablesによりNGINX Plusプロキシで終端 tc natにより中間のNGINX Plusサーバーで書き換え tc natによりアップストリームサーバーで書き換えNGINX Plusプロキシのネットワーク設定 iptablesで送信パケットを捕捉 IPフォワーディングおよびステートレスNAT なしアップストリームサーバーのネットワーク設定 NGINX Plusをデフォルトルートに指定 NGINX Plusをデフォルトルートに指定 ステートレスNAT

IP TransparencyとDSRの導入およびトラブルシューティングは複雑です。標準のリバースプロキシ動作モードではアプリケーションやサービスの要件を満たせない場合にのみ、これらの構成を実装してください。

はじめに:標準的なレイヤー7リバースプロキシにおけるパケットフロー

パケットを単に転送するスイッチやルーターとは異なり、NGINX PlusはLayer 7の「リバースプロキシ」として動作します。この動作モードでは、リモートクライアントと選択されたアップストリームサーバー間の通信を制御するため、NGINX Plusがクライアント側とアップストリーム側で個別のTCP接続(HTTPおよびTCPトラフィックの場合)またはUDPセッションを管理します。

NGINX Plusがリバースプロキシサーバーとして機能する際に、TCPパケットとUDPデータグラムを処理する仕組みを示す図
標準的なリバースプロキシとして動作するNGINX Plusによるトラフィック処理

  1. リモートクライアントは、公開されているIPアドレスとポートを使用して、NGINX Plusリバースプロキシに直接TCP接続を確立するか、UDPデータグラムを送信します。NGINX PlusはTCP接続またはUDPセッションを終端し、その中のリクエストデータを読み取ります。
  2. 次に、NGINX Plusは、選択された(負荷分散先の)アップストリームサーバーへの新しい接続を確立します(または、既存のアイドル状態の接続を再利用します)。
  3. NGINX Plusがアップストリームサーバーにリクエストを書き込む際、接続元はNGINX Plusの内部IPアドレスになります。
  4. アップストリームサーバーがリクエストに応答すると、NGINX Plusの内部IPアドレスにデータを書き込みます。
  5. NGINX Plusは、アップストリーム側の接続でレスポンスデータを受信します。レスポンスを処理または変更する場合があります(たとえば、HTTPレスポンスを圧縮します)。
  6. その後、NGINX Plusはクライアント側の接続に応答データを書き込みます。

この標準的なリバースプロキシの動作モードでは、アップストリームサーバーから見ると、TCPおよびUDPトラフィックはローカルのNGINX Plusプロキシから送信されているように見えます。

レイヤー7リバースプロキシモードの利点と制限

レイヤー7リバースプロキシモードでは、HTTPおよびTCPトラフィックのパフォーマンスと効率が大幅に向上します(TCPの最適化、バッファリング、HTTPキープアライブの再利用など)。一方、認証やアクセス制御、レート制限、ロギングなどの目的で、アップストリームサーバーが接続またはセッションの実際の送信元IPアドレスを特定する必要がある場合には、課題が生じます。

For some protocols, NGINX Plus can use the X-Forwarded-For HTTP header or the PROXY protocol to provide the origin IP address to upstream servers. This post describes two additional methods, made possible by the transparent parameter to the proxy_bind directive, which was introduced in NGINX Plus Release 10 (R10)<.htmla>.

方法1:IP透過性

IP Transparencyの目的は、リバースプロキシの存在を隠し、送信元サーバーからIPパケットがクライアントのIPアドレスを送信元としているように見せることです。IP Transparencyは、TCPベースおよびUDPベースのプロトコルで使用できます。

NGINX PlusロードバランサーでのHTTPリバースプロキシサービスの作成

IP Transparencyの動作を示すため、まず、簡単な接続情報を返す4台のWebサーバーで構成される負荷分散クラスターを作成します。

  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;
}
  1. アップストリームサーバー側で、接続元がNGINX Plusロードバランサーとして認識されていることを確認するには、4台の各サーバー(172.16.0.11~172.16.01.14)にNGINX Plus Webサーバーを構成し、次のように接続情報を返すシンプルな仮想サーバーを設定します。
# in the 'http' context
server {
    listen 80;

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

この構成をテストすると、アップストリームでは、接続元がローカルの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

IPトランスペアレンシーに対応するためのNGINX Plusとアップストリームの設定

NGINX Plus R10以降(およびNGINX Open Source 1.11.0以降)では、アップストリームトラフィックの送信元アドレスを偽装できます。proxy_bindディレクティブにtransparentパラメーターを指定します。通常は、送信元アドレスをリモートクライアントのアドレスに設定します。

proxy_bind $remote_addr transparent;

ただし、この単純な手順には大きな課題があります。リモートクライアントへの応答(送信)トラフィックが正しく処理されるようにする必要があるためです。応答トラフィックはNGINX Plusにルーティングし、NGINX PlusでアップストリームTCP接続を終端する必要があります。その後、NGINX PlusはクライアントTCP接続を介してリモートクライアントに応答トラフィックを送信します。

NGINX Plusロードバランサーと各アップストリームサーバーの両方で、いくつかの設定を変更する必要があります。

  1. NGINX Plusロードバランサーで、ワーカープロセスが任意のアドレスにアップストリームソケットをバインドできるよう、実行ユーザーを「root」に設定します。/etc/nginx/nginx.confのメイン(最上位)コンテキストに「user」ディレクティブを追加し、NGINX PlusワーカープロセスのIDを「root」に設定します。
# in the 'main' context
# 'user daemon' is the default; change to 'user root' with transparent proxy_bind
user root;
  1. NGINX Plusロードバランサーで、各接続の送信元がリモートクライアントのアドレスになるようにします。仮想サーバーの設定に、proxy_bindディレクティブをtransparentパラメーターとともに追加します:
# in the 'http' context
server {
    listen 80;

    location / {
        proxy_bind $remote_addr transparent;
        proxy_pass http://http_upstreams;
    }
}
  1. NGINX Plusロードバランサーで、iptablesを設定し、アップストリームサーバーからの戻りパケットをキャプチャしてNGINX Plusに転送します。この例では、iptablesコマンドとip 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
  1. 次のコマンドを実行して、-Lによりiptables mangleテーブルの現在の設定を一覧表示します:
# 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
  1. アップストリームサーバーで、すべての戻りトラフィックがNGINX Plusに転送されるようにルーティングを設定します。各アップストリームサーバーで、既存のデフォルトルートをすべて削除し、NGINX Plusロードバランサー/リバースプロキシのIPアドレスをデフォルトルートとして設定します。このIPアドレスは、アップストリームサーバーのいずれかのインターフェースと同じサブネット上にある必要があります。
# route del default gw 10.0.2.2
# route add default gw 172.16.0.1
  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
  1. アップストリームサーバーから外部サーバーへの接続が必要な場合は、新しいNGINX Plusゲートウェイでトラフィックの転送とマスカレードも設定する必要があります。以下の「アップストリームから外部サーバーへの接続を有効にする」を参照してください。

IP透過性設定のテスト

これで、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)として表示されるようになったことを確認します。

設定が機能しない場合は、以下の「トラブルシューティング」を参照してください。

概要:IP Transparencyの設定の仕組み

  • NGINX Plusは、リモートクライアント(192.168.99.1)からHTTPリクエストを受信します。
  • NGINX Plusは負荷分散を判断し、接続先のアップストリームサーバー(例:172.16.0.11)を選択します。接続する前に、アップストリームソケットをリモートクライアントのアドレスにバインドします。
  • アップストリームサーバーは、リモートクライアントから直接開始されたように見える接続を受信します。
  • アップストリームサーバーは、リモートクライアントのアドレスを宛先としてパケットを送信し、デフォルトルーターであるNGINX Plus経由でルーティングすることで応答します。
  • NGINX Plusロードバランサー上の「iptables」ルールがこれらのパケットをマークし、ルーティングによってローカルに配信します。
  • NGINX Plusがレスポンスを読み取ります。
  • その後、NGINX Plusはリモートクライアントにレスポンスを送信します。

その結果、アップストリームサーバーからは、接続がリモートクライアントから直接開始されたように見えます。

方法2:Direct Server Return

Direct Server Return(DSR)は、IP Transparencyの概念を拡張したものです。IP Transparencyでは、アップストリームサーバーはリモートクライアントから送信されたように見えるパケットを受信します。DSRではさらに、アップストリームサーバーがリモートクライアントに直接応答するため、戻りのパケットはロードバランサーを完全に迂回します。

DSRはロードバランサーの負荷を軽減するため、パフォーマンスがわずかに向上する可能性がありますが、いくつかの制約もあります。

  • ロードバランサーは戻りパケットを受信しないため、アップストリームサーバーが応答しているか、障害が発生しているかを検出できません。
  • ロードバランサーはアップストリームを選択する前に、リクエストの最初のパケットより先を検査できないため、負荷分散の判断(コンテンツベースルーティング)を行う能力は大幅に制限されます。
  • ロードバランサーは、SSL/TLSなどのネゴシエーションやステートフル処理には一切関与できません。
  • キャッシュ、HTTP多重化、ロギングなど、その他のアプリケーションデリバリコントローラー(ADC)機能のほとんどは、DSRでは使用できません。

DSRはTCPプロトコルでは用途が限られており、いずれにしてもNGINX PlusのリバースプロキシアーキテクチャはDSR/TCPには適用できません。

UDPプロトコルはTCPのような接続セマンティクスを持たないため、はるかにシンプルです。NGINX Plusは、DNSなどのUDPプロトコルでDSRをサポートするように構成でき、パフォーマンスの向上が期待できます。具体的には、DSRを使用すると、NGINX Plusは応答パケットを待つためにUDPソケットを開いたままにする必要がなくなり、スケーラビリティが向上します。また、応答パケットはNGINX Plusのレイヤー7処理を完全にバイパスできるため、レイテンシーが短縮されます。

DSR構成とIP Transparencyの違い

UDPトラフィック向けのIP Transparency構成とDSR構成には、次の3つの違いがあります。

  • NGINX Plusは、アップストリームサーバーにデータグラムを送信する際、リモートクライアントのIPアドレスとポートの両方を偽装する必要があります(proxy_bindのポート設定)。
  • NGINX Plusは、アップストリームサーバーからの応答データグラムを待機するように設定してはなりません(proxy_responses 0ディレクティブ)。
  • 返送データグラムの送信元アドレスをロードバランサーのパブリックアドレスと一致するように書き換えるには、追加の手順が必要です。

さらに、アップストリームサーバーに対してアクティブヘルスチェックを実行するようにNGINX Plusを設定する必要があります。NGINX Plusはサーバーから送信される応答パケットを監視しないため、通常のパッシブチェックではサーバーが正常かどうかを確認できません。

標準UDPリバースプロキシサービスの作成

DSRの動作を示すため、まず、名前「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;
}

The proxy_responsesとproxy_timeoutの各ディレクティブは、基本的なヘルスチェックを実装します。アップストリームサーバーから1秒以内に1件の応答がない場合、NGINX Plusはそのサーバーに障害が発生したと判断し、DNSリクエストを再試行します。

各DNSサーバーで、www.example.comの名前解決要求に対して自身のIPアドレスを返すように設定します:

$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

DSR向けのNGINX PlusとUDPアップストリームの設定

NGINX Plus R10以降(およびNGINX Open Source 1.11.2以降)では、アップストリームトラフィックの送信元アドレスとポートの両方を偽装できます。transparentパラメーターをproxy_bindディレクティブに追加します。

proxy_bind $remote_addr:$remote_port transparent;

これにより、アップストリームサーバーは完全な送信元IPアドレスを確認し、リモートクライアントに直接送信する応答データグラムを作成できます。

アップストリームサーバーは、正しい宛先IPを指定した応答(「送信」)パケットを生成しますが、送信元アドレスには自身のローカルIPアドレスを使用します。この送信元アドレスは、クライアントが最初に接続したNGINX PlusロードバランサーのIPアドレスとポートに書き換える必要があります。

次の2つの方法があります。

  1. ルーターNAT – 中間ルーター(NGINX Plusプロキシなど)で送信パケットを書き換える
  2. オリジンNAT – 各アップストリームDNSサーバーから送出される際に、送信パケットを書き換えます

どちらの方法でも、tc コマンドで設定するステートレスNAT機能を使用します。アップストリームサーバーがインターネットに直接接続されている場合(制御可能な中間ルーターを経由してリターンパケットが送信されないトポロジの場合)は、Origin NAT方式を選択する必要があります。

DSR向けのNGINX Plusの設定

応答パケットはNGINX Plusに配信されないため、標準UDPリバースプロキシサービスの作成で設定したヘルスチェックを無効にする必要があります。proxy_responsesディレクティブを変更し、proxy_timeoutディレクティブを無効にします。これにより、NGINX Plusは応答を待機せず、応答を受信しなくてもアップストリームサーバーに障害が発生したとは判断しません。このチェックを無効にすると、NGINX Plusはソケットリソースをすぐに再利用できるようになります。

また、アップストリームサーバーに送信されるデータグラムで元の送信元アドレスと送信元ポートの両方がNGINX Plusによって保持されるように、$remote_addr変数と$remote_port変数の両方をproxy_bindディレクティブの第1パラメーターに含めます。

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

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

ルーターNAT – 中間ルーターでの送信パケットの書き換え

単一の中間ルーターで送信パケットを書き換えることができます。たとえば、アップストリームサーバーがNGINX Plusロードバランサーの背後にあるプライベートネットワーク上に配置されている場合、ロードバランサーをデフォルトルートとして使用し、パケットの転送時に書き換えることができます。

  1. 各アップストリームサーバーで、すべての送信トラフィックがNGINX Plusサーバーを経由するようにルーティングを設定します:
# route add default gw nginx-ip-address
  1. NGINX PlusサーバーでIPトラフィックを転送するように設定します:
# sysctl -w net.ipv4.ip_forward=1
  1. ステートレス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
  1. 適切な出力インターフェースと、各アップストリームサーバーの適切なIPアドレスを選択してください。

ステートレスNATの詳細については、tc natのmanページを参照してください。構成によっては、tc filterコマンドでsrcパラメーターとegress oldパラメーターにCIDRマスクを使用することで、コマンドを1つにまとめられる場合があります。

現在のtc filter設定を表示するには、次のコマンドを実行します。

# tc filter show dev eth0

オリジン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アドレスを選択してください。

DSR構成のテスト

構成をテストするには、NGINX PlusロードバランサーにDNSリクエストを送信し、アップストリームサーバー間で負荷分散されていることを確認します。

DSRの効果を直接確認することはできません。proxy_responses 0ディレクティブを使用して、応答パケットを待機しないようにNGINX Plusを設定しているにもかかわらず、DNSクライアントが負荷分散された応答を受信している場合は、DSRが機能していると判断できます。さらに、以下の「tcpdump」で説明するように、トラブルシューティングを使用してパケットフローを確認できます。

まとめ:DSR構成の仕組み

  • NGINX Plusはリモートクライアント(192.168.99.1:ポート)からUDPデータグラムを受信します。
  • NGINX Plusは負荷分散を判断し、データグラムの内容を書き込むアップストリームサーバー(例:172.16.0.11)を選択します。NGINX Plusは接続前に、アップストリームソケットのローカル側をリモートクライアントのIPアドレスとポートにバインドします。
  • アップストリームサーバーは、NGINX Plusから送信されたデータグラムを受信します。このデータグラムは、リモートクライアントのアドレスとポートから直接送信されたように見えます。
  • アップストリームサーバーは応答として、リモートクライアントにデータグラムを送り返します。アップストリームサーバーは、応答データグラムの送信元IPアドレスとポートを、自身のローカルIPアドレスとポートに設定します。
  • 送信元IPアドレス(必要に応じてポートも)は、アップストリームサーバー(origin NAT構成)または中間ルーター(router NAT構成)のいずれかによって書き換えられます。
  • リモートクライアントは、正しい4タプル(送信元と宛先のIPアドレスおよびポート)が指定されたデータグラムを受信します。
  • NGINX Plusは応答データグラムの受信を想定していないため、アップストリームソケットを直ちに閉じます。

その結果、応答パケットはNGINX Plusのレイヤー7処理を経由せず、リモートクライアントに直接送信されます。

トラブルシューティング

IP TransparencyまたはDSRが想定どおりに動作しない場合は、考えられる原因を調査するために、以下の方法をお試しください。

次のユーザーとして実行:root

NGINX Plusのワーカープロセスがrootとして実行されるように設定されていることを確認します。設定されていない場合、NGINX Plusがソケットを非ローカルアドレスにバインドしようとすると、エラーログに次のようなエラーメッセージが表示されます。

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"

テスト:ping

NGINX Plusプロキシからクライアントとサーバーにpingできることを確認します。必要なルーティングを設定し、NGINX Plusを介してパケットが転送されるように構成しない限り、アップストリームサーバーからリモートクライアントのIPアドレスにpingすることはできません。

重複するIPアドレス範囲なし

リモートクライアントが使用するIPサブネットが、アップストリームサーバーに直接接続されていないことを確認してください。直接接続されている場合、次の2つの問題が発生する可能性があります。

  • 送信元IPアドレスが別のインターフェース上のサブネットに関連付けられているため、Linuxの「リバースパスフィルタリング」保護機能によって、NGINX Plusからのパケットが通知なしに拒否される可能性があります。
  • 戻りパケットはデフォルトルートを使用せず、ローカルに接続されたリモートクライアントに直接送信されます。

あらゆる場所で「tcpdump」を使用

構成を段階的に構築し、各中間ステップをテストする際は、すべてのサーバーで継続的にtcpdumpを実行し、各段階で正しいエンドポイントとの間でパケットが送受信されていることを確認します。

$ sudo tcpdump -i any -n tcp port 80

以下に示す確認項目を使用して、異常な動作を調査します。

ルーティングテーブルの確認

各サーバーのルーティングテーブルを慎重に確認してください。特にアップストリームサーバーを重点的に確認します。

# 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プロキシ経由でルーティングする必要があります。

欠落したパケット

パケットが予期せず破棄される場合(tcpdumpでは、あるマシンから送信されているものの、別のマシンでは受信されていないことが確認できる場合)、リバースパスフィルタリングが、表面化しにくい原因となっている可能性があります。リバースパスフィルタリングを一時的に無効にするには、次のコマンドを実行します。

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

アップストリームサーバーから外部サーバーへのアクセスを有効にする

アップストリームサーバーがプライベートネットワーク上にあり、NGINX Plus(または別のサーバー)をデフォルトゲートウェイとして使用している場合は、アップストリームサーバーが外部(インターネット)ホストにアクセスできるようにゲートウェイを構成できます。

ゲートウェイがアップストリームサーバーからのパケットを転送できるようにするには、IP フォワーディングを有効にする必要があります。通常、IPフォワーディングはデフォルトで無効になっています。サーバーにルーティング可能なIPアドレスがない場合(172.16.0.0/24などのプライベートアドレスを使用している場合)は、ゲートウェイサーバーの外部インターフェースで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
^C

現在のフォワーディング、ルーティング、およびiptables natの設定を表示するには、次の3つのコマンドを実行します。

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

NGINXからサポートを受ける

IP TransparencyまたはDirect Server Returnの構成は複雑であり、経路上の他のネットワークデバイスがパケットを破棄したり、別の方法で書き換えたりすることで、導入に影響を及ぼす可能性があります。サポートが必要な場合は、NGINXの「Professional Services」チームがお手伝いします。

NGINX PlusでIP TransparencyとDSRを実際にお試しください。今すぐ30日間の無料トライアルを開始するか、ユースケースについてご相談ください。


共有
タグ: F5 NGINX, Tech, 2016

著者について

Owen Garrett
Owen Garrettプロダクトマネジメント担当シニアディレクター

Owen Garrettのその他のブログ記事

関連するブログ記事

チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
NGINX | 2024/01/18

チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する

OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。

AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
NGINX | 2023/05/31

AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正

Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。

JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
NGINX | 2023/02/09

JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法

Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。

F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINX | 2022/05/24

F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング

NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
NGINX | 2018/08/17

SELinuxでNGINXおよびNGINX Plusを使用する

Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。

NGINX PlusによるAWS Auto Scalingグループの負荷分散
NGINX | 2017/03/06

NGINX PlusによるAWS Auto Scalingグループの負荷分散

新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります