Azure Firewallを配置したときにアプリケーションでクライアントIPアドレスを取得する

2022.04.09

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

いわさです。

先日、WebサーバーのフロントにAzure Firewallを配置してみたところ、アクセス元が取得出来ずに回避策を調べていました。
結論としてはApplication GatewayをFirewallの前に配置し、X_FORWARDED_FORを使用したのですが、情報をまとめてみました。

裸の仮想マシン

VNETに仮想マシンを配置し、Ubutu + Apacheな構成でPHPアプリケーションをデプロイしました。
アプリケーションではアクセス元のパブリックIPアドレスを元に一部コンテンツをパーソナライズしようとしていました。

Azure Firewallを配置する

次にセキュリティレイヤーを追加するために、Azure Firewallを使ってみました。

様々な保護機能を使用することが出来るようになったのですが、インバウンド通信でDNATを構成したところ、アクセス元がAzure FirewallインスタンスのプライベートIPアドレスになりました。そりゃそうだ、という感じだと思いますが。

$ curl http://20.222.7.11/
array(26) {
:
  ["SERVER_ADDR"]=>
  string(8) "10.0.0.5"
:
  ["REMOTE_ADDR"]=>
  string(8) "10.0.1.4"
:
}

Application Gatewayを配置する

どうしたものかなと調べていたのですが、Azure Architecture Center でこの場合の推奨アーキテクチャーが紹介されていました。
Azure Architecture Centerはクラウドデザインパターンやベストプラクティスがまとめられている設計ガイダンスです。

This design is appropriate for applications that need to know incoming client source IP addresses, for example to serve geolocation-specific content or for logging.

上記のように記載がありました。まさに今回の構成を解決したい場合に使えそうです。
ほかにも上記ドキュメントでは、Application GatewayにおけるWAFと、Azure Firewallの役割などについても細かく触れられています。

以下のようにAzure Firewallの前にApplication Gatewayを構成してみました。

$ curl http://20.210.242.63/
array(33) {
:
  ["HTTP_X_FORWARDED_FOR"]=>
  string(21) "203.0.113.100:64870"
:
  ["SERVER_ADDR"]=>
  string(8) "10.0.0.5"
:
  ["REMOTE_ADDR"]=>
  string(8) "10.0.1.4"
:
}

X_FORWARDED_FORで接続元が取得出来ていますね。
アプリケーションで接続元の取得部分は修正する必要はありますが、取得できずにどうしたものかという状態から脱することが出来ました。

さいごに

本日はAzure Firewallを配置した際に接続元が取得できなくなる場合の対応を行ってみました。
今回はAzureの例でしたが、NATで変換される部分はHTTPレイヤーでX_FORWARDED_FORを前段で設定してやること回避出来るパターンは他のクラウドサービスでも使えそうです。

L7ロードバランサーのバッグエンドがX-Fowarded-forからクライアントIPアドレスを取得するパターンはよくやると思いますが、今回のようにクライアント情報取得のためにわざわざ外側に1レイヤー追加するというのは、おもしろいなと思いました。