すべてのプロダクト
Search
ドキュメントセンター

Alibaba Cloud Service Mesh:ASM で Envoy フィルターを使用して HTTP レスポンスヘッダーを追加する

最終更新日:Jan 13, 2025

Web アプリケーションの HTTP レスポンスヘッダーを追加して、アプリケーションのセキュリティを向上させることができます。このトピックでは、Envoy フィルターを使用して Service Mesh(ASM)で HTTP レスポンスヘッダーを追加する方法について説明します。

前提条件

背景情報

Open Web Application Security Project(OWASP)は、HTTP レスポンスヘッダーを使用してアプリケーションのセキュリティを向上させる方法について説明するためのベストプラクティスとコーディングフレームワークを提供しています。次の表は、基本的な HTTP レスポンスヘッダーについて説明しています。

HTTP レスポンスヘッダー

デフォルト値

説明

Content-Security-Policy

frame-ancestors none;

他の Web サイトからのクリックジャッキング攻撃を防ぎます。

X-XSS-Protection

1;mode=block

ブラウザのクロスサイトスクリプティング(XSS)フィルター(使用可能な場合)をアクティブ化して、XSS 攻撃が検出されたときにブラウザがレンダリングを停止できるようにします。

X-Content-Type-Options

Nosniff

ブラウザのコンテンツスニッフィングを無効にします。

Referrer-Policy

no-referrer

リクエストと共にリファラー情報を送信しないように指定します。

X-Download-Options

noopen

古いバージョンの Internet Explorer でダウンロードが自動的に実行されるのを防ぎます。

X-DNS-Prefetch-Control

off

Web ページ上の外部ハイパーリンクの DNS プリフェッチを無効にします。

Server

envoy

レスポンスを生成するサーバー。この HTTP レスポンスヘッダーは、Istio ingress gateway によって自動的に設定されます。

X-Powered-by

N/A

ホスティング環境または他のフレームワークに関する情報が含まれています。脆弱なアプリケーションサーバーの名前とバージョン情報を非表示にする場合は、この HTTP レスポンスヘッダーを設定しないでください。

Feature-Policy

camera 'none';

microphone 'none';

geolocation 'none';

encrypted-media 'none';

payment 'none';

speaker 'none';

usb 'none';

ブラウザで使用可能な機能と API 操作を指定します。

この例では、Bookinfo アプリケーションが使用されています。詳細については、「ASM インスタンスへのアプリケーションのデプロイ」をご参照ください。次の curl コマンドを実行して、アプリケーションの HTTP レスポンスヘッダーをクエリできます。

curl -I http://{IP address of the ingress gateway}/productpage
# Output example
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 5183
server: istio-envoy
date: Tue, 28 Jan 2020 08:15:21 GMT
x-envoy-upstream-service-time: 28

コマンド出力は、アプリケーションに上記の表で説明されている HTTP レスポンスヘッダーのいずれも含まれていないことを示しています。アプリケーションのセキュリティを向上させるために、Envoy フィルターを作成してアプリケーションの HTTP レスポンスヘッダーを追加できます。

手順

  1. ASM インスタンスのバージョンに基づいて Envoy フィルターをデプロイします。

    バージョン 1.12.4.0 以降の ASM インスタンスの場合

    ASM コンソールのマーケットプレイスページで Envoy フィルターをデプロイできます。

    1. ASM コンソール にログインします。左側のナビゲーションペインで、[service Mesh] > [メッシュ管理] を選択します。

    2. [メッシュ管理] ページで、ASM インスタンスの名前をクリックします。左側のナビゲーションペインで、[プラグイン拡張センター] > [マーケットプレイス] を選択します。

    3. [マーケットプレイス] ページで、[HTTP レスポンスヘッダーの追加] をクリックします。[プラグインの詳細] ページで、[プラグインインスタンスの作成] をクリックします。

    4. [プラグインの有効範囲] セクションで、[ゲートウェイスコープ] を選択し、[ASM ゲートウェイを有効範囲に追加] をクリックします。

    5. [ASM ゲートウェイを有効範囲に追加] ダイアログボックスで、[ASM ゲートウェイの選択] セクションの [ingressgateway] を選択し、添加 アイコンをクリックして [ingressgateway][選択済み] セクションに追加し、[OK] をクリックします。

      説明

      [ingressgateway] は、デフォルトの ingress gateway の名前です。追加された HTTP レスポンスヘッダーを有効にする他のゲートウェイを選択することもできます。

    6. [プラグイン設定] セクションで、YAML コードエディターからすべてのコンテンツを削除し、[プラグインスイッチ] をオンにして、プラグインが有効になるまで待ちます。

      プラグインが有効になると、ASM は Envoy フィルターを自動的に作成します。

    バージョン 1.12.4.0 より前の ASM インスタンスの場合

    次のコマンドを実行して、Envoy フィルターをデプロイできます。

    コマンドを表示するには展開します

    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1alpha3
    kind: EnvoyFilter
    metadata:
      name: addheader-into-ingressgateway
      namespace: istio-system
      labels:
        asm-system: 'true'
        provider: asm
    spec:
      workloadSelector:
        # workloadSelector フィールドを使用して、Envoy フィルターの特定の名前空間内のワークロードを選択できます。
        labels:
          istio: ingressgateway
      configPatches:
        # 変更する必要がある Envoy 設定。
      - applyTo: HTTP_FILTER
        match:
          context: GATEWAY
          proxy:
            proxyVersion: '^1\.9.*'
          listener:
            filterChain:
              filter:
                name: "envoy.filters.network.http_connection_manager"
                subFilter:
                  name: "envoy.filters.http.router"
        patch:
          operation: INSERT_BEFORE
          value: # Lua スクリプト設定
            name: envoy.lua
            typed_config:
              "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
              inlineCode: |-
                function envoy_on_response(response_handle)
                    function hasFrameAncestors(rh)
                    s = rh:headers():get("Content-Security-Policy");
                    delimiter = ";";
                    defined = false;
                    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
                        match = match:gsub("%s+", "");
                        if match:sub(1, 15)=="frame-ancestors" then
                        return true;
                        end
                    end
                    return false;
                    end
                    if not response_handle:headers():get("Content-Security-Policy") then
                    csp = "frame-ancestors none;";
                    response_handle:headers():add("Content-Security-Policy", csp);
                    elseif response_handle:headers():get("Content-Security-Policy") then
                    if not hasFrameAncestors(response_handle) then
                        csp = response_handle:headers():get("Content-Security-Policy");
                        csp = csp .. ";frame-ancestors none;";
                        response_handle:headers():replace("Content-Security-Policy", csp);
                    end
                    end
                    if not response_handle:headers():get("X-Frame-Options") then
                    response_handle:headers():add("X-Frame-Options", "deny");
                    end
                    if not response_handle:headers():get("X-XSS-Protection") then
                    response_handle:headers():add("X-XSS-Protection", "1; mode=block");
                    end
                    if not response_handle:headers():get("X-Content-Type-Options") then
                    response_handle:headers():add("X-Content-Type-Options", "nosniff");
                    end
                    if not response_handle:headers():get("Referrer-Policy") then
                    response_handle:headers():add("Referrer-Policy", "no-referrer");
                    end
                    if not response_handle:headers():get("X-Download-Options") then
                    response_handle:headers():add("X-Download-Options", "noopen");
                    end
                    if not response_handle:headers():get("X-DNS-Prefetch-Control") then
                    response_handle:headers():add("X-DNS-Prefetch-Control", "off");
                    end
                    if not response_handle:headers():get("Feature-Policy") then
                    response_handle:headers():add("Feature-Policy",
                                                    "camera 'none';"..
                                                    "microphone 'none';"..
                                                    "geolocation 'none';"..
                                                    "encrypted-media 'none';"..
                                                    "payment 'none';"..
                                                    "speaker 'none';"..
                                                    "usb 'none';");
                    end
                    if response_handle:headers():get("X-Powered-By") then
                    response_handle:headers():remove("X-Powered-By");
                    end
                end
    EOF

    proxyVersion: Envoy フィルターが適用される Istio のバージョンを指定します。値を Istio のバージョンに設定します。Envoy フィルターの一部のフィールドは、Istio のバージョンと互換性がない場合があります。Istio のバージョンに基づいて、Envoy フィルターのフィールドを変更する必要がある場合があります。

    • Istio のバージョンが 1.8 以前の場合は、proxyVersion パラメーターを Istio のバージョンに設定し、envoy.filters.network.http_connection_managerenvoy.http_connection_manager に、envoy.filters.http.routerenvoy.router に、type.googleapis.com/envoy.extensions.filters.http.lua.v3.Luatype.googleapis.com/envoy.config.filter.http.lua.v2.Lua に置き換えます。

    • Istio のバージョンが 1.9 以降の場合は、proxyVersion パラメーターを Istio のバージョンに設定します。

  2. 次のコマンドを実行して、HTTP レスポンスヘッダーが正常に追加されたかどうかを確認します。

    {IP address of the ingress gateway} を ingress gateway の実際の IP アドレスに置き換えます。ingress gateway の IP アドレスを取得する方法の詳細については、「Istio リソースを使用してトラフィックをサービスの異なるバージョンにルーティングする」トピックの「ingress gateway の IP アドレスを取得する」セクションをご参照ください。

    curl -I http://{IP address of the ingress gateway}/productpage

    予期される出力:

    HTTP/1.1 200 OK
    content-type: text/html; charset=utf-8
    content-length: 4183
    server: istio-envoy
    date: Tue, 28 Jan 2020 09:07:01 GMT
    x-envoy-upstream-service-time: 17
    content-security-policy: frame-ancestors none;
    x-frame-options: deny
    x-xss-protection: 1; mode=block
    x-content-type-options: nosniff
    referrer-policy: no-referrer
    x-download-options: noopen
    x-dns-prefetch-control: off
    feature-policy: camera 'none';microphone 'none';geolocation 'none';encrypted-media 'none';payment 'none';speaker 'none';usb 'none';

    コマンド出力は、アプリケーションに上記の表で説明されている基本的な HTTP レスポンスヘッダーが含まれていることを示しています。

FAQ

特殊文字を含む URL を使用してアプリケーションにアクセスできないのはなぜですか?

特殊文字のエンコード形式が URL エンコード規則に準拠していない可能性があります。たとえば、特殊文字 Á に ASCII エンコードではなく Unicode エンコードが使用されています。詳細については、「Envoy cannot parse non-alphanumeric characters if not urlencoded」をご参照ください。