AWS Network Firewall で特定のドメインのみ許可するホワイトリスト方式をやってみた

# はじめに

AWS Network Firewall では、ネットワークトラフィックをきめ細かく制御するファイアウォールルールを定義できます。AWS のウェブサイトでは以下のユースケースが紹介されています。

- VPC 間のトラフィックを検査
- アウトバウンドトラフィックをフィルタリング
- インバウンドのインターネットトラフィックの侵入を防ぐ
- AWS Direct Connect と VPN のトラフィックを保護する



アウトバウンドトラフィックの HTTP/HTTPS 通信を、特定のドメインのみ許可して、他のドメインを禁止ができます。事前に確認した安全なドメインのみ HTTP/HTTPS アクセスを許可することで、セキュリティレベルの向上が期待できます。

この記事では「特定のドメインを許可するホワイトリスト方式」の設定方法を紹介します。



# 構成図

Network Firewall の構成図を先に紹介します。Network Firewall を構成するときに、どの経路を検査するかをコントロールするために各 Subnet で Route Table の適切な設定が必要です。この記事で扱う構成図を、以下の Workshop から引用します。AWS からインターネットへのアウトバウンド通信や、逆方向のインバウンド通信が、すべて Network Firewall の Endpoint を経由するのが注目ポイントですね。

https://catalog.workshops.aws/networkfirewall/en-US/setup/distributedmodel

![image-20230111222315596.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/acbce143-3d81-724b-8ea2-95b703fb3902.png)



それでは設定を進めていきます。



# Firewall Policy の作成

まず、Network Firewall の Firewall Policy の作成をしていきます。Create Firewall Policy を押します。

![image-20230114163928703.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/a2caef75-724d-5493-8f18-7f67f136f348.png)

　

適当に名前を指定して Next を押します。

![image-20230114164000844.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/9d9cc819-9f72-8155-dca5-7f126e0718d5.png)

　

rule group は空っぽのままにしておきます。

![image-20230114164103048.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/f33da6de-78f1-4436-520f-c30dcc4fb538.png)

　

**ここは重要な設定です。** Firewall Policy の Rule order (ルールの評価順) をどうするか指定する項目です。**Rule order の `Default` or `Strict` は一度設定すると、後から変更ができません。** もし変更したいときには削除と再作成が必要となり、Route Table の設定変更も含めて、全体的な設定変更が必要となります。

個人的な感想ですが、ここの設定は `Strict` の方が柔軟に運用が出来ると思います。以下の 2 点が理由です。

- ファイアウォールのルールの評価順を厳密に指定可能
- ルールに何もマッチしなかったときのデフォルトアクションを、許可 or 拒否で設定可能

　

ということで、以下の設定を入れます

- Strict
- Drop established : デフォルト拒否の設定。HTTP(S) のドメインを検査するときには、Drop established が設定しやすい。Drop All では、HTTP(S) の通信手前の ハンドシェイク部分も Drop してしまうため、下位の TCP レベルで許可設定を入れないと動作しない。Drop established では、ハンドシェイク部分は許可してくれるので、直感的に設定が出来る
- Alert all : ログの指定
- Alert established : ログの指定

![image-20230114211704211.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/911a8bc6-f838-f6db-01c9-ea4840140378.png)

　

Next を押します。

![image-20230114164439907.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/af2bd725-d0f3-344a-d335-e0ed2ecdcfb1.png)

　

デフォルトのまま Next を押します。

![image-20230114164459551.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/22f2b5df-8050-1f0d-9a3b-4463550264e9.png)

　

Tag は無しで Next を押します。

![image-20230114164515978.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/a7b30157-7455-4996-282e-04f734772f7a.png)

　

Create firewall policy を押します。

![image-20230114164538981.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/b4c641b6-b667-075e-029c-8aed1e1af215.png)

　

Firewall Policy が 作成されました。

![image-20230114164601661.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/f8e141bd-6a78-7ded-1370-e881a8e8fc87.png)



# Network Firewall の作成

次に、Firewall を作成します。各 Subnet に Network Firewall の Endpoint が作成されます。

VPC のサービス画面に Network Firewall があり、Create Firewall を押します。

![image-20230113213246693.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/327af248-2a39-8fe9-4a38-7048f91a1cc9.png)

　

Firewall をデプロイする VPC と Subnet を指定します。Network Firewall 専用の Subnet を選択します。Routing Table でルートをコントロールするため、専用の Subnet を用意するとシンプルに構成できます。

また、指定した Subnet ごとに Network Firewall Endpoint が作成されるので、料金に影響が有る部分となっています。

![image-20230114164701967.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/a673f839-bbee-dc3c-bc82-04c6d64d2dee.png)

　

前の手順で作成した Firewall Policy を紐づけます。

![image-20230114164728043.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/7529ff35-cf68-955d-d127-bfc7ee121db1.png)

　

Create Firewall を押します。

![image-20230113214820841.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/71dedb6f-09fb-9be8-d21b-7f4769a0e8e4.png)

　

Firewall が作成され、Provisioning になっています。

![image-20230114164852811.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/1b754ee0-c1c6-b278-35fa-11c193d661b2.png)

　

一定時間後に Ready になりました。

![image-20230113220204139.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/60dd09ed-1f1a-1dbb-d572-803391fbb85d.png)

　

Firewall Endpoint が 2 個作成されています。

![image-20230113220318741.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/026e4172-adce-6ead-7305-501c66049356.png)



# Route Table の設定

構成図通りに設定をします。重要そうな設定のみ抜粋して紹介します。



## Firewall Route Table

Firewall Endpoint が動作する Subnet に紐づく Route Table です。

Internet Gateway を経由して、インターネットに出るための経路を設定します。

![image-20230113234557758.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/6bf0ae91-883b-6d1d-50e2-9238a45682e7.png)

　

こんな感じの設定です。

![image-20230113231655079.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/f79886ab-3462-e559-7751-6532d5944fd6.png)



## Public Route Table

NAT Gateway を配置する Public Subnet です。

これが重要なポイントですね。`0.0.0.0/0` の経路に対して、Internet Gateway の代わりに、**Network Firewall の Endpoint を指定** します。これを指定することで、インターネットへ出る経路に Network Firewall を中継させることができます。

![image-20230113234723801.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/68679201-7faa-aa27-50b7-dd3d41f5ea83.png)

　

Edit routes を押します。

![image-20230113232747416.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/e0f25d5b-f65d-95b6-147a-b65053d92557.png)

　

`0.0.0.0/0` の宛先に対して、**Gateway Load Balancer Endpoint** を指定します。Network Firewall と表示されないのが、ちょっとややこしいですね。

![image-20230113232827894.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/cccb9608-c097-84f2-1f6f-529b34068d28.png)

　

2 つの選択肢が表示されているのが、Network Firewall の Endpoint です。AZ が同じものを選択して、Save を押します。

![image-20230113233002817.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/302785f4-835f-76d8-c212-abd062b06049.png)

　

別の Route Table も同様に設定します。

![image-20230113233428299.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/e637f311-a13b-e18b-f0e6-a029d0dc3c7d.png)



## Ingress Route Table の作成

Internet Gateway に紐づける、Ingress Route Table です。

インターネット側から入ってくる通信に、Network Firewall を経由するルートを設定していきます。ポイントは、NAT Gateway が稼働している **Public Subnet 宛の通信を、Network Firewall の Endpoint に指定** している点です。ここは間違えやすいポイントなので注意しましょう。

![image-20230113234254285.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/e2d13e86-d65c-326a-9406-dfb806cda799.png)

　

また、Ingress Route Table そのものについて気になる方は、Classmethod さんのとてもわかりやすいブログを見てみてください。(ありがとうございます！)
https://dev.classmethod.jp/articles/what-is-vpc-ingress-routing/

それでは、Ingress Route Table を作成していきます。作成するモノ自体は、通常の Route Table と同じです。

![image-20230111233922889.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/59209b53-253d-2118-8778-7f5d2a4449bc.png)

　

適当に名前を付与して、Create を押します。

![image-20230111234011874.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/efb93dd4-c367-1e6f-9a8f-19004872a9ce.png)

　

作成された Route Table を選択して、**Edit edge associations** を選択します。Edit subnet associations ではなく、edge の方を選択することで、Ingress Route Table になります。

![image-20230113233626354.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/f2c960b4-d7b3-efb5-93d8-a439f9f55da6.png)

　

Internet Gateway を選択して、Save changes を押します。

![image-20230113233759663.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/328eda91-76bd-e613-3594-05ccc615e161.png)

　

紐づけが出来ました。

![image-20230113233826068.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/bec8c243-41ec-6921-08c2-2fe1fda4c116.png)

　

Route を編集します。

![image-20230113233851283.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/31bf60e1-8125-593a-cd98-4c3d28ea1a12.png)

　

ルートを追加します。インターネットから Public Subnetへの通信を、Network Firewall を経由するように設定します。これによって、インターネットから返ってくる通信を、Network Firewall で中継できるので、セキュリティ設定に応じた通信遮断などが出来るようになります。

![image-20230113234934507.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/44c0059d-3167-795c-06fa-9c07fa64be51.png)

　

設定されました。

![image-20230113235239391.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/fe3d040c-32be-72c7-fa75-4d2b7ebebbc7.png)



# Network Firewall の Log の有効化

Network Firewall のデフォルトでは、Log 出力が無効化になっています。遮断したときのログを確認したいので、有効化していきます。Firewall の詳細画面を開きます。

![image-20230114002638798.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/9d6651a7-fd0b-eb83-96f0-c181cdb3e99a.png)

　

Firewall details を選択します。

![image-20230114002744681.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/fda29079-953f-850d-9858-948e07d83583.png)

　

Log の設定で Edit を押します。

![image-20230114002818156.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/fec28efe-c1c1-873d-9093-72666441aecc.png)

　

出力対象のログを全て選択します。

![image-20230114162914749.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/3ba7e2e3-bf23-3b9f-c99b-e8f72e664342.png)

　

今回はログの出力先を S3 にします。Bucket 名などを指定します。

![image-20230114170617422.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/ac2dcb7f-1ff3-0533-0a9e-7169470b38aa.png)

　

設定されました。

![image-20230114170647712.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/44498c75-5771-d8c1-b0e1-ca63d57747bf.png)



# アウントバウンドトラフィックをドメインで制御

AWS から外のインターネットへ通信するアウトバウンドトラフィックで、特定のドメインだけの通信を許可するホワイトリスト形式を試してみましょう。



## Rule Group の作成

特定のドメインを許可するために、Role Group を作成します。

Network Firewall rule group で、独自のルールを作成していきます。

![image-20230114150205336.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/666f2ad5-bfec-f6ea-d76a-d55fe5058045.png)

　

Stateful Rule Group を選択し、Domain List を指定します。

Capacity は、いくらか小さめに 100 と指定します。ここで指定する Capacity は後で変更が出来ないので、今後のドメイン追加の余地を考慮して、ある程度余裕をもって設定すると良いです。

ちょっと辛いところが、Capacity 消費の計算式は公開されていないので、事前に検証しながら進めていく必要があります。それなら大き目の Capacity を指定すればいいんじゃないかと思いますが、それも難しいです。Rule Group に紐づけられる Rule の Capacity 上限は 30000 となっています。なので、Capacity を大きくしすぎるのもデメリットがあります。

![image-20230114153604049.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/62985187-a191-6b93-f767-5e093dd742c1.png)

　

Stateful Rule order を Strict にします。Firewall Policy を Strict で作成したので、こちらも Strict にする必要があります。(Default で作ると、紐づけるときにエラーになる)

![image-20230114170823745.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/d10183b0-27fa-4850-2f86-6a0089a3734c.png)

　

指定したドメインの通信を許可します。AWS のサービスが EC2 インスタンスと通信することもあるので、amazon 系のドメインを許可します。

```
.amazon.com
.amazonaws.com
```

![image-20230114154545992.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/798c1b32-6860-0dc4-3db5-fa3afc390d1f.png)

　

Create を押します。

![image-20230114154615017.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/96ded3fd-7383-587a-2849-f0555d5acf71.png)

　

作成されました。

![image-20230114154832855.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/686ebf9b-9393-22e4-cafb-5d5ff0473990.png)



## Firewall に Rule Group を紐づける

Firewall を選択します。

![image-20230114170955133.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/ee946dd2-471d-6d02-006c-d43800e4ee1a.png)

　

Add unmanaged stateful rule groups を押します。

![image-20230114155333120.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/cb63596d-f73d-21c1-f352-5e856555bfa3.png)

　

さきほど作成した Rule Group を選択して Add を押します。

![image-20230114155419289.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/55ffb825-cd79-6ca4-f1bf-d28648ea7f28.png)

　

Firewall に Rule Group が紐づけられました。Capacity 30000 の上限から、紐づけた 100 分が消費されていることがわかります。

![image-20230114155538065.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/6901009f-60c6-36f7-d4d3-1c0e4bae8353.png)



## 動作確認 : 通信遮断

Private Subnet に配置した EC2 インスタンスから、禁止されている (許可されていない) ドメインへ通信をしてみます。遮断されることが期待値です。

![image-20230115145009495.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/a74184b4-c106-eb05-6681-226b5bc361d3.png)

　

Google の検索エンジンにアクセスしますが、レスポンスが返ってきません。期待通りですね。

```
[ec2-user@ip-10-1-0-143 ~]$ curl -v https://www.google.com/
*   Trying 142.251.42.132:443...
* Connected to www.google.com (142.251.42.132) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt
*  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
^C

[ec2-user@ip-10-1-0-143 ~]$ date
Sat Jan 14 12:44:06 UTC 2023
```

　

このときの Alert ログは、こんな感じに出力されています。

- Block されている点がログでわかる
- 送信元と送信先 IP がわかる
- sni に、リクエストヘッダーに含まれるドメインが記録されている

```json
{
	"firewall_name": "network-firewall-test02",
	"availability_zone": "ap-northeast-1a",
	"event_timestamp": "1673700244",
	"event": {
		"timestamp": "2023-01-14T12:44:04.278827+0000",
		"flow_id": 419526559929285,
		"event_type": "alert",
		"src_ip": "10.1.1.102",
		"src_port": 8485,
		"dest_ip": "142.251.42.132",
		"dest_port": 443,
		"proto": "TCP",
		"alert": {
			"action": "blocked",
			"signature_id": 5,
			"rev": 0,
			"signature": "aws:alert_established action",
			"category": "",
			"severity": 3
		},
		"tls": {
			"sni": "www.google.com",
			"version": "UNDETERMINED",
			"ja3": {},
			"ja3s": {}
		},
		"app_proto": "tls"
	}
}
```

　

このときの Flow ログは、こんな感じに出力されています。

- Block されていでも、Flow ログには出力されている
- Flow ログだけでは、Block されているのか、通信が許可されているのかはわからない (と思う)

```json
{
	"firewall_name": "network-firewall-test02",
	"availability_zone": "ap-northeast-1a",
	"event_timestamp": "1673700521",
	"event": {
		"timestamp": "2023-01-14T12:48:41.460387+0000",
		"flow_id": 419526559929285,
		"event_type": "netflow",
		"src_ip": "10.1.1.102",
		"src_port": 8485,
		"dest_ip": "142.251.42.132",
		"dest_port": 443,
		"proto": "TCP",
		"app_proto": "tls",
		"netflow": {
			"pkts": 23,
			"bytes": 6482,
			"start": "2023-01-14T12:44:04.267205+0000",
			"end": "2023-01-14T12:45:07.655326+0000",
			"age": 63,
			"min_ttl": 253,
			"max_ttl": 253
		},
		"tcp": {
			"tcp_flags": "1b",
			"syn": true,
			"fin": true,
			"psh": true,
			"ack": true
		}
	}
}
```



## 許可ドメインを追加

`www.google.com` のドメインを Block 出来たことがわかったので、これを許可する設定もやってみます。

該当の Rule Group を開きます。

![image-20230114230343706.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/72ef042b-1368-336c-f616-f7b6748c708a.png)

　

Add domains を押します。

![image-20230114230439968.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/0a964912-078f-99d5-f1a4-73f07b95dd64.png)

　

以下のドメインを追加して、Save を押します。

```
.google.com
```

![image-20230114230505306.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/96556c54-5dd6-eaed-b437-b2a0974013ce.png)



## 動作確認 : 通信許可

curl で通信が出来ました。

```
[ec2-user@ip-10-1-0-143 ~]$ curl -v https://www.google.com/
*   Trying 142.250.196.132:443...
* Connected to www.google.com (142.250.196.132) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt
*  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=www.google.com
*  start date: Dec 12 08:19:43 2022 GMT
*  expire date: Mar  6 08:19:42 2023 GMT
*  subjectAltName: host "www.google.com" matched cert's "www.google.com"
*  issuer: C=US; O=Google Trust Services LLC; CN=GTS CA 1C3
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x1edb770)
> GET / HTTP/2
> Host: www.google.com
> user-agent: curl/7.79.1
> accept: */*
>
< HTTP/2 200
< date: Sat, 14 Jan 2023 14:05:51 GMT
< expires: -1
< cache-control: private, max-age=0
< content-type: text/html; charset=ISO-8859-1
< cross-origin-opener-policy-report-only: same-origin-allow-popups; report-to="gws"
< report-to: {"group":"gws","max_age":2592000,"endpoints":[{"url":"https://csp.withgoogle.com/csp/report-to/gws/other"}]}
< p3p: CP="This is not a P3P policy! See g.co/p3phelp for more info."
< server: gws
< x-xss-protection: 0
< x-frame-options: SAMEORIGIN
< set-cookie: 1P_JAR=2023-01-14-14; expires=Mon, 13-Feb-2023 14:05:51 GMT; path=/; domain=.google.com; Secure
< set-cookie: AEC=ARSKqsJnvdRVKWp9FLX-MNF4uHPDtkkQttjNyvTqgmosDvY2JKJe4Tsy1dk; expires=Thu, 13-Jul-2023 14:05:51 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=lax
< set-cookie: NID=511=UES9AYD9DVc9WFQlUfGuFh1K4VjvHE8HsjE6L7c2T9zIKxfbfcs6zam9CjIPKxQib7G5feVTwHMSM9tNy3CZ5AaNS8Z-YPUj34fG5u89pc978Kc8x1VarTSvLtNs5_OKkbnA89aqYTJewc8ZBYBu0Ezzk96PWhMQYMNrPh3gjCg; expires=Sun, 16-Jul-2023 14:05:51 GMT; path=/; domain=.google.com; HttpOnly
< alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
< accept-ranges: none
< vary: Accept-Encoding
<
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="ja"><head><meta content="&#19990;&#30028;&#20013;&#12398;&#12354;&#12425;&#12422;&#12427;&#24773;&#22577;&#12434;&#26908;&#32034;&#12377;&#12427;&#12383;&#12417;&#12398;&#12484;&#12540;&#12523;&#12434;&#25552;&#20379;&#12375;&#12390;&#12356;&#12414;&#12377;&#12290;&#12373;&#12414;&#12374;&#12414;&#12394;&#26908;&#32034;&#27231;&#33021;&#12434;&#27963;&#29992;&#12375;&#12390;&#12289;&#12362;&#25506;&#12375;&#12398;&#24773;&#22577;&#12434;&#35211;&#12388;&#12369;&#12390;&#12367;&#12384;&#12373;&#12356;&#12290;" name="description"><meta content="noodp" name="robots"><meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
省略

[ec2-user@ip-10-1-0-143 ~]$ date
Sat Jan 14 14:05:55 UTC 2023
```



このときの Alert ログは、こんな感じに出力されています。

- action が allowed となっている
- 送信先のドメインは記録されていない

```json
{
	"firewall_name": "network-firewall-test02",
	"availability_zone": "ap-northeast-1a",
	"event_timestamp": "1673705151",
	"event": {
		"timestamp": "2023-01-14T14:05:51.670926+0000",
		"flow_id": 1641110069783548,
		"event_type": "alert",
		"src_ip": "10.1.1.102",
		"src_port": 50749,
		"dest_ip": "142.250.196.132",
		"dest_port": 443,
		"proto": "TCP",
		"alert": {
			"action": "allowed",
			"signature_id": 2,
			"rev": 0,
			"signature": "aws:alert_strict action",
			"category": "",
			"severity": 3
		}
	}
}
```

　

このときの Flow ログは、こんな感じに出力されています。

```json
{
	"firewall_name": "network-firewall-test02",
	"availability_zone": "ap-northeast-1a",
	"event_timestamp": "1673705245",
	"event": {
		"timestamp": "2023-01-14T14:07:25.116483+0000",
		"flow_id": 1641110069783548,
		"event_type": "netflow",
		"src_ip": "10.1.1.102",
		"src_port": 50749,
		"dest_ip": "142.250.196.132",
		"dest_port": 443,
		"proto": "TCP",
		"app_proto": "tls",
		"netflow": {
			"pkts": 25,
			"bytes": 2240,
			"start": "2023-01-14T14:05:51.666620+0000",
			"end": "2023-01-14T14:05:51.810241+0000",
			"age": 0,
			"min_ttl": 253,
			"max_ttl": 253
		},
		"tcp": {
			"tcp_flags": "1b",
			"syn": true,
			"fin": true,
			"psh": true,
			"ack": true
		}
	}
}
```

　

想定通りに、特定のドメインの許可設定を入れることで、それ以外のドメインの HTTT/HTTPS 通信が禁止されることがわかりました。



# 検証を通じてわかったこと

- 特定のドメインに限定したホワイトリスト形式が構成できる。

  - 通信プロトコルは HTTP/HTTPS が対応している。
  - HTTP/HTTPS プロトコル以外の TCP/UDP では、ドメイン許可はサポートされていない。ただ、ルールに合致しないものはデフォルトで禁止しているので、悪意のある通信が許可されるわけではない。そのため、TCP/UDP などは、ドメインの代わりに、IP アドレスの許可設定を入れることで柔軟にコントロールが出来る。

- ドメイン制限は、Stateful Rule Group で設定が可能。Stateless Rule Group には無い。

- 独自に設定するルールに加えて、AWS 側で管理されているマネージドグループがある。以下の Document に一覧と説明が書かれている。
  
  - いろいろ便利なルールがあるので、これも使っていくのが良さそう。
  - https://docs.aws.amazon.com/network-firewall/latest/developerguide/aws-managed-rule-groups-list.html
  
- Firewall に Rule Groups を紐づけるときに消費する Capacity という概念がある。1 Firewall あたり、30,000 Capacity を超えて紐づけが出来ない。
  - https://docs.aws.amazon.com/network-firewall/latest/developerguide/quotas.html
![image-20230113221159640.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/19a79776-3f1c-10cc-e764-8ecbf472f88e.png)
  
- Network Firewall のネットワークトラフィックをログに出力可能。出力先は、S3, CloudWatch Logs, Kinesis Data Firehose の 3 つから選択可能。

- ログに出力するときに、Log type を Alert と Flow の 2 つから選択可能
  - Alert : ルールの中で Action を `Alert ` か `Drop` を選択したものがログに出される。この記事の構成では、通信をブロックしたものと許可したものの両方が Alert に表示される。
  - Flow (netflow) : 通信が許可されたものがログに表示される (はず)。`drop established` で設定している場合は、禁止しているドメインについても、TCP の 3 ウェイハンドシェイクの部分だけは通信が許可されるのでログに出力される。そのため混乱しないようにしたい。
![image-20230114003022527.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/e38322b5-be99-8238-1e63-662e9bb4a3b4.png)
  
- 出力されるログのフォーマットが、以下の Document で記載されている。ログに出力されるなかで、`event_type` がログの種別を表している
  - alert
  - netflow
  - https://docs.aws.amazon.com/network-firewall/latest/developerguide/firewall-logging.html

- ログは、リアルタイムに出力されるわけではなく、出力されるまで時間が必要。
  - CloudWatch Logs, Kinesis Data Firehose : 平均 3 ~ 6 分
  - S3 : 平均 8 ~ 12 分
  - https://docs.aws.amazon.com/network-firewall/latest/developerguide/firewall-logging.html
  
- netflow で通信が許可されたもの、1 回のリクエストにつき、行きの経路と帰りの経路の 2 個が記録される

- Firewall Policy の Rule Order に関する設定は、`Default` と `Strict` の 2 種類の中から 1 つを選ぶ。個人的には、`Strict` の方が設定が楽だと思う。`Strict`  では、ルールに該当しなかったときのデフォルトアクションを指定できるので、柔軟なコントロールが出来る。

  - 一度作った後に設定変更が出来ない。やろうとおもったら、削除と再作成が必要。

- Stateful Rule で `Strict` にしたときに、何もルールに合致しなかったときのデフォルトドロップアクションを指定できる。

  - `drop established` と `drop all` の2種類が選択が出来るが、デフォルト拒否のルールを設定するためには、``drop established`` の方がより直感的に設定が出来た。以下引用

  - > `drop established` を選択すると、Network Firewall は接続が確立されている状態のパケットのみをドロップします。これにより、上位層の接続に必要なレイヤー 3 と 4 の接続確立用のパケットは許可し、既に接続が確立されているパケットについてはドロップします。このため、下位層のプロトコルで実施するハンドシェーク部分を許可する追加のルールを記述する必要なく、デフォルト拒否の設定においてアプリケーション層の pass ルールを記述することができます。

  - https://aws.amazon.com/jp/blogs/news/hands-on-walkthrough-of-the-aws-network-firewall-flexible-rules-engine-part-2/

- ログに出力される送信元 IP は、**実際に通信する EC2 instance ではなく 、NAT Gateway** となった。
  - この記事の構成では、Firewall Gateway の手前に NAT Gateway が存在しているので、このような構成になる。
  - 記事を作った後に気が付いたのだが、Subnet の Routing 構成を工夫することで送信元 IP を実際のインスタンスにできる
  - https://d1.awsstatic.com/webinars/jp/pdf/services/202110_AWS_Black_Belt_Network_Firewall_advanced01.pdf
  - P.8 : Amazon VPCの新機能 More specific routing(MSR)



# 付録1 : S3にログ出力

こんな感じで、S3 にログが出力される。

![image-20230114004749344.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/9930a44b-045b-3618-cdc6-7e74699ead55.png)





# 付録2 : Flowlog 

Network Firewall で通信が許可されたときのログを次に記載します。EC2 インスタンスから、Google の検索エンジンに Curl したときのログです。

```
curl -v https://www.google.com/
```

　

Network Firewall が出力するログは 1 回のリクエストで 2 個分出力される。

行きのログ

```json
{
	"firewall_name": "network-firewal-test01",
	"availability_zone": "ap-northeast-1a",
	"event_timestamp": "1673625629",
	"event": {
		"timestamp": "2023-01-13T16:00:29.530458+0000",
		"flow_id": 237681334242370,
		"event_type": "netflow",
		"src_ip": "10.1.1.102",
		"src_port": 55057,
		"dest_ip": "142.251.42.196",
		"dest_port": 443,
		"proto": "TCP",
		"app_proto": "tls",
		"netflow": {
			"pkts": 24,
			"bytes": 2188,
			"start": "2023-01-13T15:57:51.478274+0000",
			"end": "2023-01-13T15:57:51.628997+0000",
			"age": 0,
			"min_ttl": 253,
			"max_ttl": 253
		},
		"tcp": {
			"tcp_flags": "1b",
			"syn": true,
			"fin": true,
			"psh": true,
			"ack": true
		}
	}
}
```

　

帰りのログ

```json
{
	"firewall_name": "network-firewal-test01",
	"availability_zone": "ap-northeast-1a",
	"event_timestamp": "1673625629",
	"event": {
		"timestamp": "2023-01-13T16:00:29.530489+0000",
		"flow_id": 237681334242370,
		"event_type": "netflow",
		"src_ip": "142.251.42.196",
		"src_port": 443,
		"dest_ip": "10.1.1.102",
		"dest_port": 55057,
		"proto": "TCP",
		"app_proto": "tls",
		"netflow": {
			"pkts": 28,
			"bytes": 22399,
			"start": "2023-01-13T15:57:51.478274+0000",
			"end": "2023-01-13T15:57:51.628997+0000",
			"age": 0,
			"min_ttl": 44,
			"max_ttl": 44
		},
		"tcp": {
			"tcp_flags": "1b",
			"syn": true,
			"fin": true,
			"psh": true,
			"ack": true
		}
	}
}
```



# 付録3 : Alertlog

ブロックされたときのログ

```json
{
	"firewall_name": "network-firewall-test02",
	"availability_zone": "ap-northeast-1a",
	"event_timestamp": "1673698029",
	"event": {
		"timestamp": "2023-01-14T12:07:09.638080+0000",
		"flow_id": 814109353713397,
		"event_type": "alert",
		"src_ip": "10.1.1.102",
		"src_port": 60573,
		"dest_ip": "142.250.196.132",
		"dest_port": 443,
		"proto": "TCP",
		"alert": {
			"action": "blocked",
			"signature_id": 4,
			"rev": 0,
			"signature": "aws:alert_established action",
			"category": "",
			"severity": 3
		},
		"tls": {
			"sni": "www.google.com",
			"version": "UNDETERMINED",
			"ja3": {},
			"ja3s": {}
		},
		"app_proto": "tls"
	}
}
```

　

通信許可されたときのログ

```json
{
	"firewall_name": "network-firewall-test02",
	"availability_zone": "ap-northeast-1a",
	"event_timestamp": "1673705151",
	"event": {
		"timestamp": "2023-01-14T14:05:51.670926+0000",
		"flow_id": 1641110069783548,
		"event_type": "alert",
		"src_ip": "10.1.1.102",
		"src_port": 50749,
		"dest_ip": "142.250.196.132",
		"dest_port": 443,
		"proto": "TCP",
		"alert": {
			"action": "allowed",
			"signature_id": 2,
			"rev": 0,
			"signature": "aws:alert_strict action",
			"category": "",
			"severity": 3
		}
	}
}
```



# 付録4 : 特定の IP アドレスへのアウトバウンドを許可する

ドメイン以外にも、特定の IP アドレスに限定した接続を許可させてみます。

rule group の作成

![image-20230115151100855.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/dcad4fa5-3cb8-0ae0-fc6f-1f459507bcd2.png)

　

名前を適当に指定します。

![image-20230115151403779.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/a18024e7-6695-aa49-f037-c6472779e801.png)

　　

通信許可をさせたい宛先の IP アドレスと Port と Protocol を指定します。

![image-20230115151446377.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/812cd58a-cc81-bcde-d175-19bc4b6a53fd.png)

　　

Create します。

![image-20230115151533907.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/4dba2a31-365e-533a-1f9a-3520938752e3.png)

　

作成されました。

![image-20230115151642663.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/c3c3374c-e535-ea0a-cd31-2a457840653d.png)

　

作成した Rule Group を、Firewall Policy に紐づけます。

![image-20230115151754221.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/302ea128-09ba-3418-8dbc-185520eb9496.png)

　

紐づけします。

![image-20230115151807806.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/261d7740-cea6-4074-4c5e-59dc2df484e0.png)

　

これで、特定の IP アドレスと Port に対して通信が出来たことを確認できました。

　

許可されていない (禁止されている) IPアドレスのときの通信ログは次にようになっています。 

SSH は、この記事では TCP Port 22 を使っているのでなので、TCP の 3 ウェイハンドシェイクの通信が走ります。この記事の構成では `drop established` を設定しているため、3 ウェイハンドシェイクの部分は、禁止されている IP アドレスでも許可されたログが出ます。混乱しないようにしましょう。

Alert ログの  3 ウェイハンドシェイク部分 : SYN

```json
{
	"firewall_name": "network-firewall-test02",
	"availability_zone": "ap-northeast-1a",
	"event_timestamp": "1673764392",
	"event": {
		"timestamp": "2023-01-15T06:33:12.737152+0000",
		"flow_id": 1655536452400602,
		"event_type": "alert",
		"src_ip": "10.1.1.102",
		"src_port": 4647,
		"dest_ip": "xx.xx.xx.xx",
		"dest_port": 22,
		"proto": "TCP",
		"alert": {
			"action": "blocked",
			"signature_id": 5,
			"rev": 0,
			"signature": "aws:alert_established action",
			"category": "",
			"severity": 3
		},
		"ssh": {
			"client": {
				"proto_version": "2.0",
				"software_version": "OpenSSH_7.4"
			},
			"server": {
				"proto_version": "2.0",
				"software_version": "OpenSSH_7.4"
			}
		},
		"app_proto": "ssh"
	}
}
```

　

Alert ログの  3 ウェイハンドシェイク部分 : SYN + ACK

```json
{
	"firewall_name": "network-firewall-test02",
	"availability_zone": "ap-northeast-1a",
	"event_timestamp": "1673764392",
	"event": {
		"timestamp": "2023-01-15T06:33:12.491950+0000",
		"flow_id": 1655536452400602,
		"event_type": "alert",
		"src_ip": "xx.xx.xx.xx",
		"src_port": 22,
		"dest_ip": "10.1.1.102",
		"dest_port": 4647,
		"proto": "TCP",
		"alert": {
			"action": "allowed",
			"signature_id": 2,
			"rev": 0,
			"signature": "aws:alert_strict action",
			"category": "",
			"severity": 3
		}
	}
}
```

　

Alert ログの  3 ウェイハンドシェイク部分 : ACK

```json
{
	"firewall_name": "network-firewall-test02",
	"availability_zone": "ap-northeast-1a",
	"event_timestamp": "1673764392",
	"event": {
		"timestamp": "2023-01-15T06:33:12.493100+0000",
		"flow_id": 1655536452400602,
		"event_type": "alert",
		"src_ip": "10.1.1.102",
		"src_port": 4647,
		"dest_ip": "xx.xx.xx.xx",
		"dest_port": 22,
		"proto": "TCP",
		"alert": {
			"action": "allowed",
			"signature_id": 2,
			"rev": 0,
			"signature": "aws:alert_strict action",
			"category": "",
			"severity": 3
		}
	}
}
```

　

3 ウェイハンドシェイクのあとに、実際に Block されているログ

```json
{
	"firewall_name": "network-firewall-test02",
	"availability_zone": "ap-northeast-1a",
	"event_timestamp": "1673764392",
	"event": {
		"timestamp": "2023-01-15T06:33:12.737152+0000",
		"flow_id": 1655536452400602,
		"event_type": "alert",
		"src_ip": "10.1.1.102",
		"src_port": 4647,
		"dest_ip": "xx.xx.xx.xx",
		"dest_port": 22,
		"proto": "TCP",
		"alert": {
			"action": "blocked",
			"signature_id": 5,
			"rev": 0,
			"signature": "aws:alert_established action",
			"category": "",
			"severity": 3
		},
		"ssh": {
			"client": {
				"proto_version": "2.0",
				"software_version": "OpenSSH_7.4"
			},
			"server": {
				"proto_version": "2.0",
				"software_version": "OpenSSH_7.4"
			}
		},
		"app_proto": "ssh"
	}
}
```





# 参考 URL

Workshop
https://catalog.workshops.aws/networkfirewall/en-US

Black Belt
https://d1.awsstatic.com/webinars/jp/pdf/services/BlackBelt202106_AWS_Network_Firewall_Basic.pdf
https://d1.awsstatic.com/webinars/jp/pdf/services/202110_AWS_Black_Belt_Network_Firewall_advanced01.pdf

AWS再入門ブログリレー2022 Network Firewall 編
https://dev.classmethod.jp/articles/re-introduction-2022-network-firewall/

AWS NETWORK FIREWALLのログ
https://mikunet.biz/tech/cc/aws-network-firewall-log/

S3に格納したNetwork FirewallのログをAthenaで抽出してみた
https://dev.classmethod.jp/articles/aws-nfw-alertlog-athena/

評価の流れが AWS Document で説明されている
https://docs.aws.amazon.com/ja_jp/network-firewall/latest/developerguide/firewall-rules-engines.html

AWS Network Firewall のルールグループと評価の流れを詳細に理解する ※ハマりポイントも解説しています
https://blog.serverworks.co.jp/network_firewall_rule

re:Post の Questions : Suricate 形式で特定のドメインを許可する設定が共有されている。
https://repost.aws/questions/QU1rEZzGniSdCxMJCaKweWnQ/state-full-domain-list

Network Firewall のいくつかの構成パターン
https://aws.amazon.com/jp/blogs/networking-and-content-delivery/deployment-models-for-aws-network-firewall-with-vpc-routing-enhancements/

ルールの評価順序の Strict 方式についてのわかりやすい Blog
https://aws.amazon.com/jp/blogs/news/hands-on-walkthrough-of-the-aws-network-firewall-flexible-rules-engine-part-2/

Network Firewall の Rule Group の設定例
https://docs.aws.amazon.com/network-firewall/latest/developerguide/suricata-examples.html