AWS WAFを使ってEC2上のWordPress管理画面にIP制限をかける方法

こんにちは、D's Baseです。

AWSでIP制限をかける方法は多数ありますが、
「EC2上のWP管理画面（≒特定URL）にIP制限をかける場合、どの方法が適しているのか」
を調査しました。

本記事では
・どの方法を使って制限をかけるのが良いのか
・制限をかける方法
を記載します。

:::note warn
例としてWordPressを使っていますが、
・WP特有のカスタマイズなどは行っていない
・WP ＝ EC2上で動いているサイト、という前提で記載しています。
:::

## 構成図
今回、IP制限をかけるインフラの構成の概要は以下とします。

- 要点
    - WPはEC2上で動いている
    - EC2の前にELBが配置されている
    - ELBの前にCloudFrontが配置されている
    - **この構成だとEC2に届くアクセス元IPはCloudFrontのものになる**

![スクリーンショット 2022-11-06 17.38.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813353/870bf6eb-4438-b583-9801-2a46821f17ce.png)

## 要件
- 管理画面のログインURLには、特定のIPのみアクセスできるようにする
- ホワイトリストに登録したいIPが複数ある
    - 複数のIPを簡単に管理したい
- CloudFrontへのアクセスに対してIP制限をかけたい
    - CloudFront以降だとIPが変わってしまうため

## 結論
今回の要件お場合、**AWS WAF** でIP制限をかけるのが、最も適していました。
理由は下記になります。

### WAFを選んだ理由
- URL単位でIP制限がかけられる
- 制限の拡張が容易
    - ホワイトリストに登録するIP、および制限をかけたいURIがリスト形式で管理できる
- 任意のAWSリソース（CloudFront,ELB...)を選んで制限がかけられる
    - つまりCloudFrontをWAFの対象とすることで、アクセス元IPがCloudFrontのものに変わる前に制限がかけられる
### WAFのデメリット
サービスの利用料金がかかることが挙げられます。

料金は
・サイトへのアクセス量
・制限の複雑さ
で変化します。

:::note info
■参考
月毎で200万リクエスト程度のサイトにIP制限をかけた場合は月額1,000円程度
:::

料金の詳細は公式を参照

https://aws.amazon.com/jp/waf/pricing/

## AWSでIP制限をかける手段
AWSでIP制限をかける手段と、今回の要件ではなぜそれが適さない方法だったのかの理由です。

### ELB（リスナールール）
- できること
    - 接続元IP、HTTP、HTTPS、ドメイン、URLを条件に制限できる。
- 今回の要件に合わなかった理由
    - **ELBでもURL毎のIP制限が可能**だが、以下の理由で保守が大変と思ったため
        - ELBが複数ある場合、１台づつ設定を反映させる必要がある（設定が一元管理できない）
        - 許可したいIPのリスト管理ができない
### セキュリティグループ
- できること
    - プロトコル（HTTP,TCP,UDP...）単位で制限できる
    - AWSリソース（EC2,ELB...）単位で制限がかけられる
    - ホワイトリスト形式の制限のみ対応
- 今回の要件に合わなかった理由
    - URL単位で制限できない
### ACL
- できること
    - プロトコル（HTTP,TCP,UDP...）単位で制限できる
    - サブネット単位で制限がかけられる
    - セキュリティグループと違い、ブラックリスト形式の制限にも対応
- 今回の要件に合わなかった理由
    - URL単位でIP制限できない
### nginx (webサーバ)
- できること
    - 接続元IP、ドメイン、URLを条件に制限できる。
    - アプリケーション単位で制限ができる
- 今回の要件に合わなかった理由
    - nginxにアクセスが届く時点だと、接続元IPがCloudFrontのIPに変わっているため
### WPの.htaccess
nginxと同様。

## WAFで特定URLにIP制限をかける方法
### 作成したい制限の概要
![スクリーンショット 2022-11-06 21.47.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813353/a29259cc-a8f8-0667-9ef3-c60cb76a67d6.png)

### ホワイトリストに登録するIPセットを登録する
- AWS WAFコンソールの左メニューからIP setsを選択
- リージョンはGlobalを選択
    - ここはIP制限をかけたいリソースによって変わる。今回はCloudFrontに対して制限をかけるのでGlobalにする
- Create IP set選択してIPセットを作成
![スクリーンショット 2022-11-06 19.17.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813353/e97a5948-9a8c-b344-64a9-aed6f00b005c.png)

### IP制限をかけたいURIセットを登録する
- AWS WAFコンソールの左メニューからRegex pattern setsを選択
- リージョンはGlobalを選択
- Create Regex pattern setsを選択して制限をかけたいURIセットを作成
![スクリーンショット 2022-11-06 19.31.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813353/7fc5ed42-306d-e133-9874-c010573aa929.png)

### Web ACLを作成する
Web ACL（Web Access Control List）は、
IPやURIなどによる制限をまとめおく箱のようなイメージです。


- AWS WAFコンソールの左メニューからWeb ACLsを選択
- 以下を入力
    - Nameを入力
    - Resource typeは制限をかけるAWSリソースを選択する、今回はCloudFrontを選択
    - Add AWS resourcesを選んで、制限をかけたいCloudFrontを選択する
![スクリーンショット 2022-11-06 19.47.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813353/07a7ca41-7e3f-db39-c5fd-1618fa1b0bf4.png)
- 次画面のAdd rules and rule groupsでは、このWeb ACLに追加するRuleを作成できる
    - Ruleとは、IP制限やURI制限などのアクセスに対する制限を指している
- Ruleの追加は後から追加するのでこの時点では何もしない
- Default ActionにはAllowを選択する
    - Default ActionはこのWebACLに当たったアクセスをデフォルトで許可するかブロックするかの設定
    - BlockにするとRuleで明示的に許可したアクセス以外はブロックされる
 ![スクリーンショット 2022-11-06 19.53.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813353/7e40f281-260e-6917-dc6e-8fbcb3559ca7.png)
- 次ページのSet rule priorityは、追加したRuleの優先順位を設定できる
- Ruleを設定していないので何もせずに次へ
- 次ページのConfigure metricsは、ログの設定ができる
    - 具体的には以下の設定
        - 「作成したRuleのデータをCloudWatchに貯めるか」
        - 「このWebACLに当たったリクエストを解析してグラフ表示などできるようにしておくか」
- 好みで設定して、次ページでこれまでの設定を確認し、WebACLを作成
### Web ACLにIP制限のRuleを追加する
- AWS WAFコンソールの左メニューからWeb ACLsを選択
- 先ほど作ったWeb ACLを選択
- Ruleタブにて、add my own rules and rule groupsを選択
![スクリーンショット 2022-11-06 20.15.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813353/c93c277d-3162-10f7-4529-a153ab8da93b.png)
- 以下設定を入力
    - Rule typeにはIP setを選択
    - Nameには任意のルール名を入力
    - IP setには最初に登録したIPセットを選択
        - ここで作ったはずのIPセットが出てこない場合は、リージョンを間違えている可能性がある
    - ActionはAllowを選択
- Add Ruleを選択し次ページへ

![スクリーンショット 2022-11-06 20.16.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813353/66c0bac9-0816-18c9-35bd-cf7de137b609.png)
- 次ページのSet rule priorityは、追加したRuleの優先順位を設定できる
- この時点ではRuleは1つしか無いので何もせずSaveする。

### Web ACLにURI制限のRuleを追加する

- Ruleタブにて、add my own rules and rule groupsを選択
- 以下設定を入力
    - Rule typeにはRule builderを選択
    - Nameには任意のルール名を入力
    - if arequestにmaches the statementを選択
    - inspetにURI Pathを選択
    - Mache typeにはMaches pattern form regex pattern setを選択
    - Regex pattern setに最初に登録したURIセットを選択
    - ActionはBlockを選択
- Add Ruleを選択し次ページへ
![スクリーンショット 2022-11-06 20.45.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813353/8780e0d3-bd23-5c42-0638-5876fdb76c8a.png)
![スクリーンショット 2022-11-06 20.20.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813353/f1e9308b-bf05-49fd-8bae-074a0de74054.png)


- 次ページのSet rule priorityでは、何もせずSaveする。
- この時、IP制限のRuleの方が、URI制限のRuleより優先度が上になっていることを確認しておく
![スクリーンショット 2022-11-06 21.17.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813353/26ae7665-e3ed-9fac-654e-f0cf7f683040.png)



:::note info
Capacityについて

画像ではURI制限のCapacityが25になっているが、これは優先度とは関係ありません。

Capacityは、そのWebACLが持てるRuleの処理量のようなもので、
数値が大きいほど処理量が多くなります。

Capacityが1500を超えるRuleの追加はできません。
※AWSに申請すれば拡張は可能らしい。

詳しくは公式ドキュメントを参照
https://docs.aws.amazon.com/waf/latest/developerguide/how-aws-waf-works.html#aws-waf-capacity-units
:::

### 設定を確認する
- 最後にRuleタブにて想定通りの設定になっているか確認する
- 以下事項を確認
    - IP制限Ruleの優先順位がURI制限より高いこと
    - IP制限RuleのActionがAllowになっていること
    - URI制限RuleのActionがBlockになっているこ
    - デフォルトのActionがAllowになっていること
![スクリーンショット 2022-11-06 20.35.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813353/389aa714-9dc7-bc9d-e861-0fe9f9131edb.png)

上記でAWSのIP制限の対応は完了です。

:::note info
D’s Baseでは、“アプリケーション開発” に携わるディレクターのノウハウ共有や、ディレクターとエンジニアが少しでも仕事が進めやすくなるような情報を発信していきます。
:::