Application Gateway で HTTP ヘッダーと URL を書き換える
Application Gateway を使用すると、選択した要求と応答のコンテンツを書き換えることができます。 この機能により、URL の変換、文字列パラメーターのクエリ実行、要求ヘッダーと応答ヘッダーの変更を行えます。 また、条件を追加することで、特定の条件が満たされた場合にのみ、URL または指定したヘッダーが確実に書き換えられるようにできます。 これらの条件は、要求と応答の情報に基づいています。
HTTP ヘッダーおよび URL の書き換え機能は、Application Gateway v2 SKU でのみ使用できます。
要求ヘッダーと応答ヘッダー
Application Gateway を使用すると、要求/応答パケットがクライアントとバックエンド プールの間を移動する間に、HTTP 要求および応答ヘッダーを追加、削除、または更新できます。 クライアントとサーバーは、HTTP ヘッダーを使用して、要求または応答に追加の情報を渡すことができます。 これらのヘッダーの書き換えによって、HSTS/X-XSS-Protection などのセキュリティ関連ヘッダー フィールドの追加、機密情報が漏れる可能性のある応答ヘッダー フィールドの削除、X-Forwarded-For ヘッダーからのポート情報の削除など、重要なタスクを実現できます。
Connection
と Upgrade
のヘッダーを除く、要求と応答のすべてのヘッダーを書き換えることができます。 また、アプリケーション ゲートウェイを使用してカスタム ヘッダーを作成し、ゲートウェイを経由してルーティングされる要求と応答にヘッダーを追加することもできます。 Azure portal を使用して Application Gateway で要求ヘッダーと応答ヘッダーを書き換える方法については、こちらを参照してください。
URL パスとクエリ文字列
Application Gateway の URL 書き換え機能を使用すると、次のことができます。
要求 URL のホスト名、パス、およびクエリ文字列の書き換え
リスナーに対する全要求の URL の書き換え、または設定した 1 つ以上の条件に一致する要求の URL のみの書き換え。 これらの条件は、要求プロパティ (要求ヘッダーとサーバー変数) に基づいています。
元の URL または書き換えられた URL に基づく要求のルーティング (バックエンド プールの選択)
Azure portal を使用して Application Gateway で URL を書き換える方法については、こちらを参照してください。
Application Gateway での書き換えの概要
書き換えセットは、ルーティング規則、条件、アクションのコレクションです。
要求ルーティング規則の関連付け: 書き換え構成が、ルーティング規則によってソース リスナーに関連付けられます。 種類 Basic のルーティング規則を使用する場合、書き換え構成はそのリスナーに関連付けられ、グローバル書き換えとして機能します。 パスベースのルーティング規則を使用する場合、書き換え構成は URL パス マップに従って定義されます。 後者の場合、サイトの特定のパス領域にのみ適用されます。 1 つの書き換えセットを複数のルーティング規則に適用できますが、それに関連付けることができる書き換えは 1 つのみです。
書き換え条件: これは省略可能な構成です。 定義した条件に基づいて、Application Gateway によって HTTP(S) 要求と応答の内容が評価されます。 HTTP(S) の要求または応答がこの条件に一致する場合、後続の "書き換えアクション" が発生します。 複数の条件を 1 つのアクションと関連付けた場合は、すべての条件が満たされた場合にのみアクションが発生します。 つまり、論理 AND 演算です。 書き換え条件を使い、HTTP(S) の要求と応答の内容を評価できます。 このオプションの構成では、1 つ以上の条件が満たされた際にのみ書き換えを行えます。 アプリケーション ゲートウェイは、次の 3 種類の変数を使用して、要求と応答のコンテンツを評価します。
次の種類を選択して条件を検索できます。
- HTTP ヘッダー (要求と応答)
- サポートされているサーバー変数
条件を使用すると、テキストまたは正規表現パターンを使用して値を照合することで、指定したヘッダーまたは変数が存在するかどうかを評価できます。 高度な書き換え構成の場合、ヘッダーまたはサーバー変数の値を取り込んで、後で書き換えアクションで使用することもできます。 詳細については、パターンと取り込みに関する記事を参照してください。
書き換えアクション: 書き換えアクション セットを使用すると、ヘッダー (要求または応答) または URL コンポーネントを書き換えることができます。
アクションには、次の値の型またはそれらの組み合わせを含めることができます。
- Text。
- 要求ヘッダーの値 - 取り込まれた要求ヘッダー値を使用するには、構文を
{http_req_headerName}
として指定します。 - 応答ヘッダーの値 - 上記の条件から取り込んだ応答ヘッダー値を使用するには、構文を
{http_resp_headerName}
として指定します。 アクション セットの "Set-Cookie" 応答ヘッダーから値が取り込まれる場合は、{capt_header_value_matcher}
を使用できます。 詳細については、アクション セットの取り込みに関する記事を参照してください。 - サーバー変数 - サーバー変数を使用するには、構文を
{var_serverVariable}
として指定します。 サポートされているサーバー変数の一覧。
アクションを使用して URL を書き換える場合、次の操作がサポートされています。
- URL パス: パスとして設定する新しい値。
- URL クエリ文字列: クエリ文字列の書き換え先になる新しい値。
- パス マップを再評価する: 書き換え後に URL パス マップを再評価する必要があるかどうかを指定します。 オフのままにすると、元の URL パスが使用され、URL パス マップのパス パターンと照合されます。 True に設定すると、URL パス マップが再評価され、書き換えられたパスと一致するかどうかがチェックされます。 このスイッチを有効にすると、書き換え後に要求を別のバックエンド プールにルーティングする際に役立ちます。
パターン マッチングと取り込み
パターン マッチングと取り込みは、条件とアクションでサポートされています (アクションでは、特定のヘッダーでのみサポートされています)。
パターン マッチング
Application Gateway では、パターン マッチングに正規表現が使用されます。 パターン マッチング構文を記述するときは、正規表現 2 (RE2) と互換性のある式を使用する必要があります。
条件とアクションの両方でパターン マッチングを使用できます。
- 条件: これは、ヘッダーまたはサーバー変数の値を照合するために使用されます。 "条件" でパターンを照合するには、"pattern" プロパティを使用します。
- アクション: アクション セットのパターン マッチングは、応答ヘッダー "Set-Cookie" でのみ使用できます。 アクションで Set-Cookie のパターンを照合するには、"HeaderValueMatcher" プロパティを使用します。 取り込まれた場合、その値は {capt_header_value_matcher} として使用できます。 複数の Set-Cookie が存在する可能性があるため、ここでのパターン マッチングにより、特定の Cookie を探すことができます。 例: あなたは、特定のバージョンの user-agent の場合、"cookie2" の set-cookie 応答ヘッダーを max-age=3600 (1 時間) で書き換えたいと考えています。 この場合、以下を使用できます
- 条件 - 種類: 要求ヘッダー、ヘッダー名: user-agent、一致させるパターン: *2.0
- アクション - 書き換えの種類: 応答ヘッダー、アクションの種類: Set、ヘッダー名: Set-Cookie、ヘッダー値マッチャー: cookie2=(.*)、ヘッダー値: cookie2={capt_header_value_matcher_1}、Max-Age=3600
Note
コア ルール セット 3.1 以前で Application Gateway Web Application Firewall (WAF) を実行している場合、先読みおよび後読み (否定または肯定) アサーションの実行中に、Perl 互換正規表現 (PCRE) を使用すると問題が発生する可能性があります。
取り込みの構文
パターンを使用して、後で使用するために部分文字列を取り込むこともできます。 正規表現定義内のサブパターンをかっこで囲みます。 かっこの最初のペアによってその部分文字列が 1 に、2 番目のペアによって 2 に格納されます (以下同様)。 かっこはいくつでも使用できます。Perl は、キャプチャされた文字列を表すために、より多くの番号付き変数を定義し続けます。 この Perl プログラミング ガイダンスでいくつかの例を見つけることができます。
- (\d)(\d) # 2 桁を照合し、それらをグループ 1 と 2 にキャプチャします
- (\d+) # 1 桁以上の数字を照合し、すべてをグループ 1 にキャプチャします
- (\d)+ # 1 桁を 1 回以上照合し、最後の数字をグループ 1 にキャプチャします
取り込みが完了したら、次の形式を使用してアクション セット値で使用できます。
- 要求ヘッダーのキャプチャの場合は、{http_req_headerName_groupNumber} を使用する必要があります。 たとえば、{http_req_User-Agent_1} または {http_req_User-Agent_2} です
- 応答ヘッダーのキャプチャの場合は、{http_resp_headerName_groupNumber} を使用する必要があります。 たとえば、{http_resp_Location_1} または {http_resp_Location_2} です。 一方、"HeaderValueMatcher" プロパティを使用して取り込まれた応答ヘッダー Set-Cookie の場合は、{capt_header_value_matcher_groupNumber} を使用する必要があります。 たとえば、{capt_header_value_matcher_1} または {capt_header_value_matcher_2} です。
- サーバー変数の場合は、{var_serverVariableName_groupNumber} を使用する必要があります。 たとえば、{var_uri_path_1} または {var_uri_path_2} です
Note
- / をプレフィックスとサフィックスに使用すると、パターンで値を一致させるパターンを指定することはできません。 たとえば、(\d)(\d) は 2 桁に一致します。 /(\d)(\d)/ は 2 桁に一致しません。
- 条件変数の大文字と小文字の区別は、キャプチャ変数の大文字と小文字の区別と一致する必要があります。 たとえば、条件変数が User-Agent である場合、キャプチャ変数は User-Agent 対応 (つまり、{http_req_User-Agent_2}) である必要があります。 条件変数が user-agent として定義されている場合、キャプチャ変数は user-agent 対応 (つまり、{http_req_user-agent_2}) である必要があります。
- 値全体を使用する場合は、数値を指定しないでください。 GroupNumber を指定せずに、{http_req_headerName} などの形式を使用します。
サーバー変数
Application Gateway では、サーバー変数を使用して、サーバー、クライアントとの接続、およびその接続での現在の要求に関する情報が格納されます。 格納される情報には、クライアントの IP アドレスや Web ブラウザーの種類などがあります。 サーバー変数は、たとえば新しいページが読み込まるときや、フォームが投稿されるときに動的に変化します。 これらの変数を使用して、書き換え条件を評価し、ヘッダーを書き換えることができます。 サーバー変数の値を使ってヘッダーを書き換えるには、構文 {var_serverVariableName} でこれらの変数を指定する必要があります。
アプリケーション ゲートウェイでは、次のサーバー変数がサポートされています。
変数名 | 説明 |
---|---|
add_x_forwarded_for_proxy | X-Forwarded-For クライアント要求ヘッダー フィールドと、IP1、IP2、IP3 などの形式でそれに追加される client_ip 変数 (この表で後ほど説明します) が含まれています。 X-Forwarded-For フィールドがクライアント要求ヘッダーにない場合、add_x_forwarded_for_proxy 変数は $client_ip 変数と等しくなります。 この変数は、アプリケーション ゲートウェイによって設定された X-Forwarded-For ヘッダーを書き換えるときに役立ちます。この方法により、ヘッダーにはポート情報は含まれず、IP アドレスのみが含まれるようになります。 |
ciphers_supported | クライアントでサポートされている暗号の一覧。 |
ciphers_used | 確立された TLS 接続で使用される暗号の文字列。 |
client_ip | アプリケーション ゲートウェイが要求を受信したクライアントの IP アドレス。 アプリケーション ゲートウェイと発信元のクライアントの前にリバース プロキシがある場合、client_ip はリバース プロキシの IP アドレスを返します。 |
client_port | クライアント ポート。 |
client_tcp_rtt | クライアント TCP 接続の情報。 TCP_INFO ソケット オプションをサポートするシステムで使用できます。 |
client_user | HTTP 認証の使用時に、認証のために提供されるユーザー名。 |
host | 優先順位は次のとおりです: 要求行のホスト名、Host 要求ヘッダー フィールドのホスト名、要求に一致するサーバー名。 たとえば、要求 http://contoso.com:8080/article.aspx?id=123&title=fabrikam の場合、ホストの値は contoso.com です。 |
cookie_name | name クッキー。 |
http_method | URL 要求を行うために使用されたメソッド。 たとえば、GET、POST などです。 |
http_status | セッションの状態。 たとえば、200、400、403 です。 |
http_version | 要求プロトコル。 通常、HTTP/1.0、HTTP/1.1、または HTTP/2.0 です。 |
query_string | 要求された URL 内で "?" の後にある、変数と値のペアから成る一覧。 たとえば、要求 http://contoso.com:8080/article.aspx?id=123&title=fabrikam の場合、query_string の値は id=123&title=fabrikam です。 |
received_bytes | 要求の長さ (要求行、ヘッダー、および要求本文を含む)。 |
request_query | 要求行内の引数。 |
request_scheme | 要求スキーム。http または https です。 |
request_uri | 完全な元の要求 URI (引数を含む)。 たとえば、要求 http://contoso.com:8080/article.aspx?id=123&title=fabrikam* の場合、request_uri の値は /article.aspx?id=123&title=fabrikam です。 |
sent_bytes | クライアントに送信されたバイト数。 |
server_port | 要求を受け付けたサーバーのポート。 |
ssl_connection_protocol | 確立された TLS 接続のプロトコル。 |
ssl_enabled | 接続が TLS モードで動作する場合は "オン"。 それ以外の場合は、空の文字列です。 |
uri_path | Web クライアントがアクセスする必要があるホスト内の特定のリソースを識別します。 この変数は、編集前の元の URL パスを参照します。 これは、引数を含まない要求 URI の部分です。 たとえば、要求 http://contoso.com:8080/article.aspx?id=123&title=fabrikam の場合、uri_path の値は /article.aspx です。 |
相互認証サーバー変数
Application Gateway は、相互認証のシナリオに対して次のサーバー変数をサポートしています。 これらのサーバー変数は、上記の他のサーバー変数と同じように使用します。
変数名 | 説明 |
---|---|
client_certificate | 確立された SSL 接続用のクライアント証明書 (PEM 形式)。 |
client_certificate_end_date | クライアント証明書の終了日。 |
client_certificate_fingerprint | 確立された SSL 接続用のクライアント証明書の SHA1 フィンガープリント。 |
client_certificate_issuer | 確立された SSL 接続用のクライアント証明書の "発行者の DN" 文字列。 |
client_certificate_serial | 確立された SSL 接続用のクライアント証明書のシリアル番号。 |
client_certificate_start_date | クライアント証明書の開始日。 |
client_certificate_subject | 確立された SSL 接続のクライアント証明書の "サブジェクトの DN" 文字列。 |
client_certificate_verification | クライアント証明書検証の結果: SUCCESS、FAILED:<reason>、証明書が存在しない場合は NONE。 |
ヘッダーの書き換えの一般的なシナリオ
X-Forwarded-For ヘッダーからポート情報を削除する
Application Gateway では、要求をバックエンドに転送する前に、すべての要求に X-Forwarded-For ヘッダーが挿入されます。 このヘッダーは、IP ポート のコンマ区切りリストです。 バックエンド サーバーでヘッダーに IP アドレスが含まれることだけが必要なシナリオがあるとします。 ヘッダーの書き換えを使用して X-Forwarded-For ヘッダーからポート情報を削除できます。 これを行う 1 つの方法は、ヘッダーを add_x_forwarded_for_proxy サーバー変数に設定することです。 または、client_ip 変数を使用することもできます。
リダイレクト URL を変更する
リダイレクト URL の変更は、特定の状況で役に立つ場合があります。 たとえば、クライアントが元々 "/blog" のようなパスにリダイレクトされていて、コンテンツ構造が変わったために "/updates" に送信されるようになった場合などです。
警告
Application Gateway がバックエンドに対してホスト名をオーバーライドするように構成されている場合、構成のコンテキストでリダイレクト URL を変更する必要性が生じることがあります。 その場合、バックエンドから見えるホスト名は、ブラウザーから見えるホスト名とは異なります。 この状況では、リダイレクトに正しいホスト名が使われません。 この構成は推奨されていません。
このような構成の制限と意味については、「リバース プロキシとそのバックエンド Web アプリケーションの間で、元の HTTP ホスト名を維持する」を参照してください。 App Service の推奨される設定については、「Application Gateway を使用して App Service を構成する」の「カスタム ドメイン (推奨)」に記載されている手順に従ってください。 次の例で説明するように、応答の location ヘッダーを書き換えることは回避策と考えるべきであり、根本原因には対処できません。
アプリ サービスでは、リダイレクト応答を送信するとき、その応答の場所ヘッダーで、アプリケーション ゲートウェイから受信した要求のものと同じホスト名が使用されます。 そのためクライアントでは、アプリケーション ゲートウェイ (contoso.com/path2
) 経由ではなく、contoso.azurewebsites.net/path2
に直接要求を行います。 アプリケーション ゲートウェイをバイパスすることは望ましくありません。
この問題は、場所ヘッダーのホスト名をアプリケーション ゲートウェイのドメイン名に設定することで解決できます。
ホスト名を置換する手順を次に示します。
応答の場所ヘッダーに azurewebsites.net が含まれているかどうかを評価する条件で書き換え規則を作成します。 パターン「
(https?):\/\/.*azurewebsites\.net(.*)$
」を入力します。アプリケーション ゲートウェイのホスト名を含むように、場所ヘッダーを書き換えるにアクションを実行します。 これを行うには、ヘッダー値として「
{http_resp_Location_1}://contoso.com{http_resp_Location_2}
」を入力します。 または、サーバー変数host
を使用して、元の要求と一致するようにホスト名を設定することもできます。
脆弱性を防ぐための HTTP セキュリティ ヘッダーを実装する
アプリケーションの応答で必要なヘッダーを実装することにより、いくつかのセキュリティの脆弱性を修正できます。 たとえば、X-XSS-Protection、Strict-Transport-Security、Content-Security-Policy などのセキュリティ ヘッダーです。 Application Gateway を使用して、すべての応答にこれらのヘッダーを設定できます。
不要なヘッダーを削除する
HTTP 応答から、機密情報を明らかにするヘッダーを削除することができます。 たとえば、バックエンド サーバー名、オペレーティング システム、ライブラリの詳細などの情報を削除できます。 アプリケーション ゲートウェイを使用して、これらのヘッダーを削除できます。
ホスト ヘッダーを削除する書き換え規則は作成できません。 アクションの種類が削除に、ヘッダーがホストにそれぞれ設定されている書き換え規則を作成しようとすると、エラーが発生します。
ヘッダーの有無を確認する
HTTP 要求または応答ヘッダーを評価し、ヘッダーまたはサーバー変数の有無を確認できます。 この評価は、特定のヘッダーが存在する場合にのみヘッダーの書き換えを実行する場合に役立ちます。
URL の書き換えの一般的なシナリオ
パラメーター ベースのパスの選択
ヘッダーの値、URL の一部、または要求内のクエリ文字列に基づいてバックエンド プールを選択するシナリオを実現するには、URL 書き換え機能とパスベースのルーティングを組み合わせて使用できます。
これを行うには、特定のパラメーター (クエリ文字列、ヘッダーなど) を確認する条件を含む書き換えセットを作成し、URL パスを変更するアクションを実行します ([パス マップの再評価] が有効なことを確認します)。 次に、書き換えセットをパス ベースの規則に関連付ける必要があります。 パス ベースの規則には、書き換えセットで指定されているのと同じ URL パスと対応するバックエンド プールが含まれている必要があります。
そのため、書き換えセットを使用すると、ユーザーは特定のパラメーターを確認して新しいパスを割り当てることができ、パス ベースの規則を使用すると、ユーザーはそれらのパスにバックエンド プールを割り当てることができます。 "パス マップの再評価" が有効な限り、トラフィックは書き換えセットで指定されたパスに基づいてルーティングされます。
クエリ文字列を使用したユース ケースの例については、「ポータルでのパラメーター ベースのパス選択を使用してトラフィックをルーティングする」を参照してください。
URL に基づいてクエリ文字列パラメーターを書き換える
ユーザーに表示されるリンクを単純で読みやすくする必要があるショッピング Web サイトのシナリオについて考えてみましょう。ただし、バックエンド サーバーでは、適切なコンテンツを表示するためにクエリ文字列パラメーターが必要となります。
この場合、Application Gateway は URL からパラメーターを取得し、URL のクエリ文字列のキーと値のペアを追加できます。 たとえば、ユーザーが https://www.contoso.com/fashion/shirts
を https://www.contoso.com/buy.aspx?category=fashion&product=shirts
に書き換える必要がある場合は、次の URL 書き換え構成を使用して実現できます。
条件 - サーバー変数 uri_path
がパターン /(.+)/(.+)
に等しい場合
アクション - URL パスを buy.aspx
に設定し、クエリ文字列を category={var_uri_path_1}&product={var_uri_path_2}
に設定します
前述のシナリオを実現するための詳細な手順については、Azure portal を使用した Application Gateway での URL の書き換えに関する記事を参照してください
書き込み構成に関する一般的な落とし穴
基本要求ルーティング規則では、[パス マップの再評価] は有効にできません。 これは、基本的なルーティング規則の無限評価ループを防ぐためです。
パスベースのルーティング規則の無限評価ループを防ぐため、パスベースのルーティング規則に対して [パス マップの再評価] が有効になっていない条件の付き書き換え規則または書き換え規則が 1 つ以上必要です。
ループがクライアントの入力に基づいて動的に作成された場合、受信要求は 500 エラー コードで終了します。 このようなシナリオでは、アプリケーション ゲートウェイはいかなるパフォーマンス低下も起こさず、引き続き他の要求を処理します。
Web アプリケーション ファイアウォール (WAF_v2 SKU) で URL 書き換えまたはホスト ヘッダー書き換えを使用する
URL 書き換えまたはホスト ヘッダー書き換えを構成すると、要求ヘッダーまたは URL パラメーターへの変更後 (書き換え後) に、WAF 評価が行われます。 また、アプリケーション ゲートウェイで URL 書き換えまたはホスト ヘッダー書き換え構成を削除すると、ヘッダー書き換え (事前書き換え) 前に WAF 評価が行われます。 この順序により、バックエンド プールによって受信される最終的な要求に WAF ルールが適用されます。
たとえば、"Accept" : "text/html"
ヘッダーに対して、次のヘッダー書き換えルールがあるとします。ヘッダーの値 "Accept"
が "text/html"
と等しい場合は、値を "image/png"
に書き換えます。
ここではヘッダー書き換えが構成されているだけで、WAF 評価が "Accept" : "text/html"
に行われます。 ただし URL 書き換えやホスト ヘッダー書き換えを構成する場合、WAF 評価は "Accept" : "image/png"
に行われます。
URL の書き換えと URL のリダイレクト
URL の書き換えの場合は、要求がバックエンドに送信される前に、Application Gateway によって URL が書き換えられます。 変更はユーザーには表示されないため、これによって、ブラウザーでユーザーに表示される内容は変更されません。
URL のリダイレクトの場合、Application Gateway は新しい URL を使用してリダイレクトの応答をクライアントに送信します。 そのため、クライアントは、リダイレクトで提供された新しい URL に要求を再送信する必要があります。 ブラウザーでユーザーに表示される URL は、新しい URL に更新されます。
制限事項
- アプリケーション ゲートウェイが要求をリダイレクトするように構成されているとき、またはカスタム エラー ページを表示するように構成されているときは、書き換えはサポートされません。
- 要求ヘッダー名には、英数字とハイフンを含めることができます。 他の文字を含むヘッダー名は、要求がバックエンド ターゲットに送信されるときに破棄されます。
- 応答ヘッダー名には、任意の英数字と、RFC 7230 で定義されている特定の記号を含めることができます。
- 接続ヘッダーとアップグレード ヘッダーを書き換えることはできません
- 書き換えは、Application Gateway から直接生成される 4xx と 5xx の応答ではサポートされていません