ゲートウェイネットワークトポロジの設定
外部クライアント属性(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ゲートウェイの前にリバースプロキシがある場合は、numTrustedProxies
を2
に設定します。
httpbinを使用したX-Forwarded-For機能の例
次のコマンドを実行して、
numTrustedProxies
が2
に設定された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
httpbin
という名前空間を作成します。$ kubectl create namespace httpbin namespace/httpbin created
サイドカーインジェクション用に
istio-injection
ラベルをenabled
に設定します。$ kubectl label --overwrite namespace httpbin istio-injection=enabled namespace/httpbin labeled
httpbin
名前空間にhttpbin
をデプロイします。$ kubectl apply -n httpbin -f @samples/httpbin/httpbin.yaml@
httpbin
に関連付けられたゲートウェイをデプロイします。
$ kubectl apply -n httpbin -f @samples/httpbin/httpbin-gateway.yaml@
$ kubectl apply -n httpbin -f @samples/httpbin/gateway-api/httpbin-gateway.yaml@
$ kubectl wait --for=condition=programmed gtw -n httpbin httpbin-gateway
- Istio IngressゲートウェイのIPアドレスに基づいて、ローカルの
GATEWAY_URL
環境変数を設定します。
$ export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ export GATEWAY_URL=$(kubectl get gateways.gateway.networking.k8s.io httpbin-gateway -n httpbin -ojsonpath='{.status.addresses[0].value}')
次の
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ヘッダーの処理方法を構成するには、IstioOperator
でforwardClientCertDetails
を設定します。
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プロトコルを有効にするには、IstioOperator
でproxyProtocol
を設定します。例:
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-For
やX-Envoy-External-Address
などのL7ヘッダーと相互に排他的であることに注意してください。PROXYプロトコルがgatewayTopology
構成と組み合わせて使用されている場合、信頼できるクライアントアドレスの決定では、numTrustedProxies
と受信したX-Forwarded-For
ヘッダーが優先され、PROXYプロトコルのクライアント情報は無視されます。
上記の例は、ゲートウェイが着信PROXYプロトコルTCPトラフィックを受け入れるように構成するだけであることに注意してください。PROXYプロトコルを使用してアップストリームサービスと通信するようにEnvoy自体を構成する方法の例については、Envoyのドキュメントを参照してください。