ゲートウェイネットワークトポロジの設定

外部クライアント属性(IPアドレス、証明書情報)を宛先ワークロードに転送

多くのアプリケーションは、正しく動作するために、発信元のリクエストのクライアントIPアドレスと証明書情報を知る必要があります。特に、クライアントIPを設定する必要があるロギングおよび監査ツールや、ルールセットを正しく適用するためにこの情報を必要とするWebアプリケーションファイアウォール(WAF)などのセキュリティツールが該当します。クライアント属性をサービスに提供する機能は、リバースプロキシの基本機能として長らく存在しています。これらのクライアント属性を宛先ワークロードに転送するために、プロキシはX-Forwarded-For(XFF)ヘッダーとX-Forwarded-Client-Cert(XFCC)ヘッダーを使用します。

今日のネットワークは性質が大きく異なりますが、ネットワークトポロジーがどうであれ、これらの属性のサポートは必須です。この情報は、ネットワークがクラウドベースのロードバランサー、オンプレミスロードバランサー、インターネットに直接公開されるゲートウェイ、多数の中間プロキシを提供するゲートウェイ、その他の指定されていないデプロイメントトポロジーを使用しているかどうかにかかわらず、保持および転送される必要があります。

IstioはIngressゲートウェイを提供しますが、上記の多様なアーキテクチャを考慮すると、宛先ワークロードへのクライアント属性の適切な転送をサポートする適切なデフォルトを同梱することはできません。Istioのマルチクラスターデプロイメントモデルがより一般的になるにつれて、これはますます重要になります。

X-Forwarded-Forの詳細については、IETFのRFCを参照してください。

ネットワークトポロジの設定

XFFおよびXFCCヘッダーの設定は、MeshConfigを介してすべてのゲートウェイワークロードに対してグローバルに設定するか、Podアノテーションを使用してゲートウェイごとに設定できます。たとえば、IstioOperatorカスタムリソースを使用する場合、インストールまたはアップグレード中にグローバルに設定するには、次のようにします。

spec:
  meshConfig:
    defaultConfig:
      gatewayTopology:
        numTrustedProxies: <VALUE>
        forwardClientCertDetails: <ENUM_VALUE>

Istio IngressゲートウェイのPodスペックにproxy.istio.io/configアノテーションを追加して、これらの両方の設定を構成することもできます。

...
  metadata:
    annotations:
      "proxy.istio.io/config": '{"gatewayTopology" : { "numTrustedProxies": <VALUE>, "forwardClientCertDetails": <ENUM_VALUE> } }'

X-Forwarded-Forヘッダーの設定

アプリケーションは、X-Forward-Forヘッダーなど、リクエスト内のクライアント属性を転送するためにリバースプロキシに依存しています。ただし、Istioをデプロイできるネットワークトポロジーが多様であるため、クライアントアドレスを正しく抽出できるように、numTrustedProxiesをIstioゲートウェイプロキシの前にデプロイされた信頼できるプロキシの数に設定する必要があります。これにより、X-Envoy-External-AddressヘッダーでIngressゲートウェイによって設定される値が制御され、アップストリームサービスはクライアントの元のIPアドレスに確実にアクセスできるようになります。

たとえば、クラウドベースのロードバランサーとIstioゲートウェイの前にリバースプロキシがある場合は、numTrustedProxies2に設定します。

httpbinを使用したX-Forwarded-For機能の例

  1. 次のコマンドを実行して、numTrustedProxies2に設定されたtopology.yamlという名前のファイルを作成し、Istioをインストールします。

    $ cat <<EOF > topology.yaml
    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    spec:
      meshConfig:
        defaultConfig:
          gatewayTopology:
            numTrustedProxies: 2
    EOF
    $ istioctl install -f topology.yaml
    
  2. httpbinという名前空間を作成します。

    $ kubectl create namespace httpbin
    namespace/httpbin created
    
  3. サイドカーインジェクション用にistio-injectionラベルをenabledに設定します。

    $ kubectl label --overwrite namespace httpbin istio-injection=enabled
    namespace/httpbin labeled
    
  4. httpbin名前空間にhttpbinをデプロイします。

    zip
    $ kubectl apply -n httpbin -f @samples/httpbin/httpbin.yaml@
    
  5. httpbinに関連付けられたゲートウェイをデプロイします。

zip
$ kubectl apply -n httpbin -f @samples/httpbin/httpbin-gateway.yaml@
  1. Istio IngressゲートウェイのIPアドレスに基づいて、ローカルのGATEWAY_URL環境変数を設定します。
$ export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  1. 次のcurlコマンドを実行して、X-Forwarded-Forヘッダーにプロキシアドレスを含めたリクエストをシミュレートします。

    $ curl -s -H 'X-Forwarded-For: 56.5.6.7, 72.9.5.6, 98.1.2.3' "$GATEWAY_URL/get?show_env=true" | jq '.headers["X-Forwarded-For"][0]'
      "56.5.6.7, 72.9.5.6, 98.1.2.3,10.244.0.1"
    

上記の出力は、httpbinワークロードが受信したリクエストヘッダーを示しています。Istioゲートウェイがこのリクエストを受信したとき、X-Envoy-External-AddressヘッダーをcurlコマンドのX-Forwarded-Forヘッダーの最後から2番目(numTrustedProxies: 2)のアドレスに設定しました。さらに、ゲートウェイはhttpbinワークロードに転送する前に、独自のIPをX-Forwarded-Forヘッダーに追加します。

X-Forwarded-Client-Certヘッダーの設定

XFCCに関するEnvoyのドキュメントから:

XFCCヘッダーの処理方法を構成するには、IstioOperatorforwardClientCertDetailsを設定します。

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  meshConfig:
    defaultConfig:
      gatewayTopology:
        forwardClientCertDetails: <ENUM_VALUE>

ここで、ENUM_VALUEは次のタイプのいずれかになります。

ENUM_VALUE
UNDEFINEDフィールドが設定されていません。
SANITIZE次のホップにXFCCヘッダーを送信しないでください。
FORWARD_ONLYクライアント接続がmTLS(相互TLS)の場合、リクエストでXFCCヘッダーを転送します。
APPEND_FORWARDクライアント接続がmTLSの場合、クライアント証明書情報をリクエストのXFCCヘッダーに追加して転送します。
SANITIZE_SETクライアント接続がmTLSの場合、クライアント証明書情報でXFCCヘッダーをリセットし、次のホップに送信します。これはゲートウェイのデフォルト値です。
ALWAYS_FORWARD_ONLYクライアント接続がmTLSかどうかに関係なく、常にリクエストでXFCCヘッダーを転送します。

この機能の使用例については、Envoyのドキュメントを参照してください。

PROXYプロトコル

PROXYプロトコルを使用すると、HTTPなどのL7プロトコルやX-Forwarded-ForおよびX-Envoy-External-Addressヘッダーに依存せずに、TCPプロキシ間でクライアント属性を交換および保持できます。これは、外部TCPロードバランサーがTCPトラフィックをIstioゲートウェイ経由でバックエンドTCPサービスにプロキシし、ソースIPなどのクライアント属性をアップストリームTCPサービスエンドポイントに公開する必要があるシナリオを対象としています。PROXYプロトコルはEnvoyFilterを介して有効にできます。

外部TCPロードバランサーがTCPトラフィックを転送し、PROXYプロトコルを使用するように構成されている場合、IstioゲートウェイTCPリスナーもPROXYプロトコルを受け入れるように構成する必要があります。ゲートウェイ上のすべてのTCPリスナーでPROXYプロトコルを有効にするには、IstioOperatorproxyProtocolを設定します。例:

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  meshConfig:
    defaultConfig:
      gatewayTopology:
        proxyProtocol: {}

または、次のPodアノテーションを使用してゲートウェイをデプロイします。

metadata:
  annotations:
    "proxy.istio.io/config": '{"gatewayTopology" : { "proxyProtocol": {} }}'

クライアントIPは、ゲートウェイによってPROXYプロトコルから取得され、X-Forwarded-ForおよびX-Envoy-External-Addressヘッダーに設定(または追加)されます。PROXYプロトコルは、X-Forwarded-ForX-Envoy-External-AddressなどのL7ヘッダーと相互に排他的であることに注意してください。PROXYプロトコルがgatewayTopology構成と組み合わせて使用されている場合、信頼できるクライアントアドレスの決定では、numTrustedProxiesと受信したX-Forwarded-Forヘッダーが優先され、PROXYプロトコルのクライアント情報は無視されます。

上記の例は、ゲートウェイが着信PROXYプロトコルTCPトラフィックを受け入れるように構成するだけであることに注意してください。PROXYプロトコルを使用してアップストリームサービスと通信するようにEnvoy自体を構成する方法の例については、Envoyのドキュメントを参照してください。

この情報は役に立ちましたか?
改善のための提案はありますか?

フィードバックありがとうございます!