🔥

なぜ外部公開されていない FQDN の Web Apps に Application Gateway でのヘッダ書換えが必要なのか

2023/10/09に公開

TL;DR

  • Web Apps を外部公開されていない FQDN でアクセスさせるためには Application Gateway でのヘッダ書換えが必要
  • Host header とは何か、なぜ必要なのか
  • Web Apps の Custom domain の意味

はじめに

先日、Web Apps に internal domain でアクセスさせられないか、という質問を受けて、その中で Application Gateway を利用した構成の話をしました。
Application Gateway をはさんでいる理由はヘッダの書換えなわけですが、口頭ではちょっと説明がしづらいというか、意外と複雑だなと思ったので、ここに書いておきます。

それぞれのレイヤにおけるヘッダ

たとえば、自分の PC からブラウザで https://app.internal.example.jp として Web Apps にアクセスしたいと思った時に、何が起こるかということを考えてみます。

PC and Application

最終的にはパケット、として PC の NIC から電気信号 (Wi-Fi であれば電波) が出ていくわけですが、それまでにもいろいろなことが考えられています。
まず、パケットにはヘッダと、実際の中身の情報に当たるペイロード、プロトコルによってはフッタがつきます。
カプセル化、encapsulation と呼ばれるものです。

今回の例では、以下のような感じになります。(全然厳密ではないですがなんとなくということで)

レイヤ・プロトコル 内容
HTTP app.internal.example.jp に接続したい (Host header)、GET というメソッドを使う、/ にアクセスする、など
TLS 通信先との接続にあたり TLS を利用したい、自分の PC で利用可能な暗号化方式はこれ、サーバ側はなに?じゃあこの方式で通信しましょうか、など
L4 (HTTPS なので) 443 番ポートに接続する、(TCP に使う) シーケンス番号はこれ、など
L3 通信先は app.internal.example.jp です、TCP を上位プロトコルとして使いたいので 6 番を指定、など

なんとなくカプセル化して包まれた感じを図示するとこんな感じでしょうか。

packet before DNS resolution

で、問題は L3 で、約束事であるプロトコル上、通信先を FQDN (app.internal.example.jp) という形では指定してはならないんですね。
そこで出てくるのが DNS で、名前解決という仕組みを使って、IP アドレスに変換します。
その結果、以下のような感じになります。

レイヤ・プロトコル 内容
HTTP app.internal.example.jp に接続したい (Host header)、GET というメソッドを使う、/ にアクセスする、など
TLS 通信先との接続にあたり TLS を利用したい、自分の PC で利用可能な暗号化方式はこれ、サーバ側はなに?じゃあこの方式で通信しましょうか、など
L4 (HTTPS なので) 443 番ポートに接続する、(TCP に使う) シーケンス番号はこれ、など
L3 通信先は 203.0.113.80 です、TCP を上位プロトコルとして使いたいので 6 番を指定、など

先ほどの図を変更するとこんな感じです。

packet after DNS resolution

で、この名前解決において、Web Apps では CNAME を利用しています。
どなたがお持ちのリソースかもわからないので例としては不適切ですが、例えば app.azurewebsites.net に対して app.internal.example.jp が設定できたとするとこうなります。

app.internal.example.jp.	1800	IN	CNAME	app.azurewebsites.net.
app.azurewebsites.net.	1800	IN	CNAME	waws-prod-cq1-005.vip.azurewebsites.windows.net.
waws-prod-cq1-005.vip.azurewebsites.windows.net. 300 IN	CNAME waws-prod-cq1-005.brazilsouth.cloudapp.azure.com.
waws-prod-cq1-005.brazilsouth.cloudapp.azure.com. 10 IN	A x.x.x.x

app.internal.azurewebsites.net みたいな FQDN で Web Apps にアクセスしたいと思った時に、単純に考えればこのように CNAME を書いたり、PC の hosts を書くことで解決できます。
ただし、先ほど図示したように、CNAME や hosts で変わるのは L3 ヘッダの内容のみで、HTTP の Host header は app.internal.example.jp から変わっていません。

HTTP の Host header の意味

次に、HTTP の Host header について少し説明していきます。

RFC 7230: Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing の sesion 5.4 から引用しますが、Host header は以下のように書かれます。

GET /pub/WWW/ HTTP/1.1
Host: www.example.org

接続先に対して、私は www.example.org と通信したいよ、と伝えているようなものですが、そもそもなぜ必要かということを考えます。
Web Apps の安価なプランなどが該当しますが、世の中の多くの Web サービスはひとつの IP アドレスでひとつの Web サービスを提供しているわけではありません。
IP アドレスが有限であることもそうですが、例えば app01.example.jp も app02.example.jp も app03.example.jp も同じ IP アドレスの可能性があります。
つまり 203.0.113.80 という IP アドレスの 443/tcp にパケットが来た、だけでは app01.example.jp なのか app02.example.jp なのか app03.example.jp なのかわからないわけです。
そこで出てくるのが Host header で、app01.example.jp と書いてあればサーバの中でパケットを処理する対象が分かるという仕組みです。

HTTP host header illustration

Web Apps の Custom domain

つぎに Web Apps 側に移りますが、Web Apps では Custom domain という機能があります。
これがないとどういうことが起こるかというと、例えば app.azurewebsites.net という名前でリソースを作成すると app.azurewebsites.net という名前でしかアクセスできるようになりません。
たまに、名前解決した結果の IP アドレスを直接してアクセスしてつながらない、という質問がありますが、これがその理由です。
自分で apache や nginx を立てた場合には、IP アドレスで Hello 的なページが表示されますが、Web Apps の場合にはそのようになりません。

Custom domain は、Web Apps に対して Host header で対応する FQDN を増やす機能です。
例えば app.azurewebsites.net に対して、app.internal.example.jp を Custom domain として追加すれば、そのリソースは app.azurewebsites.net と app.internal.example.jp の両方でアクセスできるようになります。

なぜヘッダの書換えが必要なのか

で、先ほどのを振り返ると、Host header は app.internal.example.jp と設定されてパケットが Web Apps に飛んできます。
一方で、Web Apps としてはそのような FQDN でアクセスされることを想定していません。

Host header before rewrite

様々な理由で、Custom domain として app.internal.example.jp を追加することができない場合には、Application Gateway による Host header の書き換えが必要ということになります。

Host header after rewrite

で、じゃあこれで完全解決ですね、かというとそうでもないので、internal domain での Web Apps 利用はハードルが高いですよ、という話です。
そもそもヘッダの書換えが必要、ってだけでも若干ややこしくなるのに加えて、Set-Cookie への対応などを考えると対応できないパターンが一部あります。
詳細については Application Gateway で HTTP ヘッダーと URL を書き換える を読んでいただければと思います。

参考

  • Application Gateway で HTTP ヘッダーと URL を書き換える

https://learn.microsoft.com/azure/application-gateway/rewrite-http-headers-url?wt.mc_id=MVP_391314

  • App Service でも internal な domain が使いたい

https://zenn.dev/skmkzyk/articles/app-service-internal-domain

Discussion