【Azure WAF】 WAF を調べたので吐き出す 【Application Gateway】

# はじめに

どうも、ATLのヴィリアスです。

最近、**Azure の App Service に WAF V1 (Application Gateway) を導入しました。**
そこで色々と情報を収集したので、記事にしてまとめることにしました。

**※免責事項(必ず、ご一読ください)**
　　本記事の情報により生じた、いかなる損害や損失についても、当社は一切の責任を負いかねます。
　　また、誤情報が入り込んだり、情報が古くなったりすることもありますので、
　　必ずしも正確性を保証するものではありません。ご了承ください。

# Azure WAF とは？

「SQLインジェクション や クロスサイトスクリプティング (XSS) などの
**攻撃から Web アプリケーションを保護する Azure サービス**」です。

https://learn.microsoft.com/ja-jp/azure/web-application-firewall/overview

:::note info
WAF そのものが単体で存在しているわけではなく、
**Azure Application Gateway や Azure Front Door などに含まれる
一つの機能として存在しています。**
:::

# Application Gateway とは？

「 Web アプリケーションに対するトラフィックを管理できる
**Web トラフィックロードバランサー**」です。

以下の Learn を受けたり、記事を読んだりすればざっくりと理解できます。

https://learn.microsoft.com/ja-jp/training/modules/intro-to-azure-application-gateway/

https://techblog.ap-com.co.jp/entry/2022/02/28/132156

## 補足: SKU

Application Gateway には SKU が4つ存在します。
| SKU |
|:--|
| Standard  |
| Standard V2  |
| WAF  |
| WAF V2  |

以下のドキュメントに、 **V1 (無印) と V2 の機能比較**がされています。

https://learn.microsoft.com/ja-jp/azure/application-gateway/overview-v2#feature-comparison-between-v1-sku-and-v2-sku

WAF SKU と WAF V2 SKU については、
**Standard SKU に WAF の機能が追加されたもの**と考えて大丈夫だと思います。

# Application Gateway と Front Door の違いは？

先ほど、[Azure WAF とは？](#Azure-WAF-とは？)にて
「**Azure WAF は Application Gateway や Front Door の機能の一部として存在している。**」と書きました。

https://learn.microsoft.com/ja-jp/azure/application-gateway/overview

https://learn.microsoft.com/ja-jp/azure/frontdoor/front-door-overview

それでは、**2つのサービスの違い**は何でしょうか？
Microsoft の FAQ から引用します。

https://learn.microsoft.com/ja-jp/azure/frontdoor/front-door-faq#azure-front-door---azure-application-gateway----------

> 主な違いは、 **Front Door が非リージョンサービス**であるのに対し、
> **Application Gateway はリージョンサービス**であるということです。 

つまり、**異なるリージョン間のリソース**を
一元的に負荷分散したり、 WAF を導入したりしたい場合は **Front Door** を利用します。
そうでなければ、 Application Gateway でも問題ないということです。

また、**課金方式**もそれぞれ異なります。
ですが、互いに非常に似ているサービスのようです。

# Azure WAF と Azure Firewall の違いは？

Azure WAF に似ている Azure サービスとして、「**Azure Firewall**」があります。

https://learn.microsoft.com/ja-jp/azure/firewall/overview

この2つのサービスの違いは、OSI参照モデルにおける**保護する層が異なる**ことです。
| サービス | 保護する層 |
|:--|:--|
| Azure WAF | アプリケーション層  |
| Azure Firewall  | ネットワーク層、トランスポート層  |

Azure Firewall については、以下の記事が参考になります。

https://www.rworks.jp/cloud/azure/azure-column/azure-entry/27173/

# とりあえずチュートリアルがやりたい！

https://learn.microsoft.com/ja-JP/azure/web-application-firewall/ag/application-gateway-web-application-firewall-portal

「**仮想マシンに WAF 経由でアクセスできるようにする**」というシナリオで
チュートリアルを受けられます。

# 502 エラーが出るんだけど…

**App Service に対して WAF を実装しようとすると 502 エラーが出る**ことがあります。

https://docs.microsoft.com/ja-jp/azure/application-gateway/application-gateway-troubleshooting-502

その場合は「**正常性プローブ**」と「**バックエンド設定**」を正しく設定すると治るかもしれません。

「**とりあえず 502 エラーを解決したい！**」という場合のために、設定の一例を載せておきます。

## 正常性プローブ

プローブを画像のように作成します。
![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/4c247668-c951-7d02-d282-6c166194026c.png)

## バックエンド設定

バックエンド設定では、[**ホスト名**] の設定が 502 エラーに影響する可能性があります。
![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/c523959c-36be-0a71-911f-f9634e8ae659.png)

[**新しいホスト名でオーバーライドする**] は、 "**はい**" を選択します。

また、 [ホスト名] に正しいホスト名が入力されていることを確認します。
例えば、```hogefuga.com```とかですね。

[**カスタムプローブの使用**] も "**はい**" を選択し、
先ほど作成したプローブを選択します。

この設定をすれば、 502 エラーが解消されていると思います。

もし解消されていなければ、
**IP アドレスによる通信拒否**などがされていないかも確認してください。

# 証明書はどうやって設定するの？

Application Gateway には「**リスナー**」と「**バックエンド設定**」の2つに証明書を配置できます。
証明書の配置としてはこんなイメージ。
![画像6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/fb312b37-fc2d-7c77-32b6-3eaf62d7de07.png)

リスナーとバックエンド設定に、証明書を配置する・しないは自由です。

ただ、**リスナーで証明書を配置しなければ**、バックエンド設定で証明書が配置されていても
**クライアントからはHTTP通信をしているように見えます。**

逆に、リスナーで証明書を配置すれば、バックエンド設定で証明書が配置されていなくても
クライアントからはHTTPS通信をしているように見えます。

| リスナーの証明書 | バックエンド設定の証明書 | クライアントから見える通信方式 |
|:-:|:-:|:-:|
| ✕  | ✕  | HTTP  |
| ✕  | ◯  | HTTP  |
| ◯  | ✕  | **HTTPS**  |
| ◯  | ◯  | **HTTPS**  |

詳細については、以下のドキュメントに記載されています。

https://learn.microsoft.com/ja-jp/azure/application-gateway/ssl-overview

## リスナー

[**プロトコル**] として "**HTTPS**" を選択すると、証明書を設定できます。

![画像7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/6938dd3e-275c-ca34-f3d2-78147d22224f.png)

## バックエンド設定

[**バックエンド認証証明書**] にて、証明書を設定できます。

バックエンドターゲットが App Service の場合、
**App Service に配置されている証明書をそのまま使うこともできます。**

![画像4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/11a1ab19-4961-3063-7b47-91953d5e8107.png)

# App Service にアクセスする前に WAF を経由させたいんだけど…

**Application Gateway** と **App Service** の 2 つで設定をします。

## Application Gateway

Application Gateway の **DNS 名**と
Webサイト (App Serviceなど) の**カスタムドメイン名**を **CNAME** で紐づけてください。

Application Gateway の DNS 名は、
[**フロントエンドパブリック IP アドレス**] で確認できます。
![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/c78b9b58-3e3a-6d92-e9ec-0e73ec4df358.png)

## App Service

[**ネットワーク**] **のアクセス制限から、 Application Gateway のみを許可**するようにしてください。
![画像8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/12b58433-b1d5-fc84-6bf8-b4019ca8d79c.png)

こうすることで、 App Service への通信は **Application Gateway のみ許可**されます。

Application Gateway を経由せずに、
直接 App Service にアクセスしようとすると **403 エラー**が発生します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/557c310d-fceb-9204-1f59-cf0624f9df59.png)

## 補足: 404 エラーが出るようになった…

以前、 CNAME で 紐づけをしたところ
WAF の先にある App Service にアクセスできなくなったことがありました。 (404 エラー)

この場合、Application Gateway の [**リスナー**] にて、**証明書を設定し直してみてください。**

# Azure WAF で IP アドレス制限はできる？

**WAF V2 の場合、WAF ポリシーを作成することで IP アドレス制限を付与できます。**

https://learn.microsoft.com/ja-jp/azure/web-application-firewall/ag/policy-overview

**WAF V1 の場合、 WAF ポリシーを作成できません。**
代替案として、 Application Gateway が存在する
**仮想ネットワークをネットワークセキュリティグループに所属させることで、IP アドレス制限を付与できます。**

https://learn.microsoft.com/ja-jp/azure/virtual-network/network-security-groups-overview

#  WAF を経由してもクライアント IP アドレスは取得できるの？

[**X-Forwarded-For**] ヘッダーで取得できます。

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Forwarded-For

```C#
// HTTPリクエストヘッダーの"X-Forwarded-For"を参照すると、カンマ区切りでIPアドレスが取得できる
// [構文] X-Forwarded-For: <クライアントIP>, <プロキシーサーバーIP1>, <プロキシーサーバーIP2>
var ipAddress = Request.Headers["X-Forwarded-For"].ToString().Split(",")[0];
```

# どうやって WAF の動作確認をするの？

Web アプリの URL に**XSSテスト用パラメーターを付与したもの**をブラウザへ入力し、アクセスします。

例えばこんな URL 
```https://hogefuga.com?<script>alert(1);</script>```

**URL にスクリプトが含まれている場合、 WAF によってアクセスが拒否されます。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/e6394387-e5df-1319-8c90-faf7cee11d27.png)
このように403 エラーが発生したら、WAFは正常に動作しています。

# おわりに

なぐり書きレベルで調べたことをつらつらと書き連ねましたが、
この情報がどなたかの参考になれば嬉しいです。

なにかあれば随時、情報を追記したり修正したりしようと思います。