Cloudflare で gRPC を通す (2. ファイアウォール)

## はじめに
Cloudflare で gRPC を通すテスト、第2回です。

1. [プロキシ + Full TLS 化](https://qiita.com/KeioCF/items/fb300ff8bd059ca8ca72)
2. ファイアウォール <<====
3. [レートリミット](https://qiita.com/KeioCF/items/cad50f07d3af293b4e0f)
4. [ロードバランシング](https://qiita.com/KeioCF/items/055db44468311196af65)

## ファイアウォール

[ファイアウォール](https://developers.cloudflare.com/firewall/)を併用し、条件に応じた gRPC リクエストだけ、オリジンに届けようと思います。

gRPC サービスに対するアクセス(`質と量`)を具体的に把握し、`サービスの安定稼働`と`健全なセキュリティライフサイクルの継続`に役立てることを目指します。

もちろん、`簡単`に。

### 守るべきものを知る、セキュリティイベント (Security events) としてリクエストを可視化

HTTP ログが全リクエストを対象にするのと違い、セキュリティのイベントは設定したルールにマッチしないと可視化されません。

:::note
HTTP ログにもログ対象を[フィルタ](https://blog.cloudflare.com/logpush-filters-alerts/)するオプションは出てます。(執筆時点 Beta)
:::

まずは、gRPC サーバ宛のすべての HTTP リクエストをセキュリティのイベントにするため [Firewall rules](https://developers.cloudflare.com/waf/firewall-rules/) でルールを作成します。(全部許可)

![Screenshot 2023-01-31 at 18.19.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218045/8cfc26ea-a11d-17eb-d704-e572518084ca.png)

:::note
今回利用するツールは host ヘッダにポートを入れてきます。ルール作成で `Hostname` フィールドの equals マッチさせる場合、:443 は除いてホスト名だけ定義します。 (Analytics 系のフィルタで `Host` の equals マッチする場合は host ヘッダ通り :443 を入れます）
:::


[セキュリティイベント](https://developers.cloudflare.com/waf/security-events/) を開くと、ファイアウォールで処理をされた gRPC サーバ宛リクエストの概況が見えてきます。

簡単です。

ここから、いろいろな視点で`リクエストの質と量`を把握していきます。
悪質なものや想定外のものが把握されたら、ブロックし、サービスを健全に保ちたいところです。

デフォルトではファイアウォールの`アクション`をキーにした分析表示となります。(グラフの線が1本だけなので、発生したアクションは1つだけで、それは許可、ということがわかります。)
![Screenshot 2023-01-31 at 18.30.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218045/5af46a8c-65ae-cc85-573d-a9af8529f1d7.png)

同じデータを視点を変えて見てみます。`国` をクリックします。

![Screenshot 2023-01-31 at 18.34.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218045/d5927b53-b350-fb10-d2db-d74f62d75f20.png)

リクエストの送信元を国別で表示することができました。
縦軸のイベント数がアクション別に比べ3分の1に減っているのがわかります。

同じデータを`違う視点から簡単に分析`できるのが、`状況把握のスピードアップ`に効きますね。

:::note
とくに、攻撃の徴候があったり、トラブルシュートの際は、こういう簡便さが重要だと思います。
:::

スクロールダウンすると、グラフの元データ(統計とソースログの抜粋)が表示されています。

![Screenshot 2023-01-31 at 18.45.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218045/e80ab228-984e-6347-c111-8a941040ddb6.png)
![Screenshot 2023-01-31 at 18.45.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218045/4194bc09-9bc5-01ec-8a1e-3ff339ea1450.png)
各ログの詳細はクリックで確認することができます。
![Screenshot 2023-01-31 at 18.46.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218045/84799328-640b-3478-cabd-9aa2a09597dc.png)

:::note
閲覧している各項目は、ファイアウォールルール作成のフィールド、値としてそのまま反映できます。Read した要素で設定に Write できる、直感的でわかりやすいです。
:::



### gRPC のリクエストに接続条件を設定する
 
`Australia からの通信は想定外なので、拒否したい`と仮定して、ファイアウォールの設定を変更します。

gRPC ホストに対して Australia のみ Block するルールを定義していきます。

1. イベントから Australia で追加のフィルタを掛けます。
![Screenshot 2023-01-31 at 19.08.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218045/835fae58-e8f0-539e-1f9e-33d48418bca9.png)

2. フィルタを掛けた状態で、"ファイアウォールルールを作成" をクリックします。
![Screenshot 2023-01-31 at 19.09.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218045/962e98a1-8465-c936-5d4c-6a8dc718cdf2.png)

3. ルール作成の画面に飛びますが、指定したフィルタで`ルールの雛形が自動作成`されています。ルール名(必須)を追加し、アクションが Block であることを確認のうえ、保存します (`下書き`または`デプロイ`)。
![Screenshot 2023-01-31 at 19.13.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218045/c878032c-33c9-18d0-c9a5-b1659d08d709.png)

4. 作成された Block のルールを Allow の上に移動します。

![Screenshot 2023-01-31 at 19.28.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218045/61077b9f-b8ea-5de3-60d4-f5c370f2bb05.png)

:::note
ルールは上から順に[評価](https://developers.cloudflare.com/firewall/cf-firewall-rules/order-priority/)されます。
:::

:::note
ルールの保存ですが、`下書きを保存`は動作無効の状態で作成されます。 `デプロイ`は即動作し始めます。
![Screenshot 2023-01-31 at 20.13.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218045/3ee83b77-f1b1-f7ff-d26c-f3fafe47b542.png)
:::


:::note
`ファイアウォールルールを作成`から飛ぶとある程度自動作成してくれますが、直接のほうがやりやすい場合もありますので、場合に応じて使い分けます。
たとえば、セキュリティイベント側の表示フィルタ条件では `:443` 付きで指定しており、自動作成されたルールにもそのまま入力されていました。ただ、ファイアウォールルール設定の`ホスト名`で equals マッチさせるには `:443` を削る必要がありました。
:::

### ファイアウォールの効果

デプロイ保存したので、動作に即反映されました。

gRPC クライアントの表示は Australia では下記のようになりました。
`403 Forbidden` と ファイアウォールで Block されていることがわかります。
```
2023/01/31 10:30:29 Greeting: Hello australia
2023/01/31 10:30:32 Greeting: Hello australia
2023/01/31 10:30:35 Greeting: Hello australia
2023/01/31 10:30:38 Greeting: Hello australia
2023/01/31 10:30:41 could not greet: rpc error: code = PermissionDenied desc = unexpected HTTP status code received from server: 403 (Forbidden); transport: received unexpected content-type "text/plain; charset=UTF-8"
exit status 1
2023/01/31 10:30:44 could not greet: rpc error: code = PermissionDenied desc = unexpected HTTP status code received from server: 403 (Forbidden); transport: received unexpected content-type "text/plain; charset=UTF-8"
exit status 1
```

一方 gRPC サーバでは Austraria からのメッセージが消えました。
```
2023/01/31 10:30:34 Received: brazil
2023/01/31 10:30:35 Received: australia
2023/01/31 10:30:35 Received: japan
2023/01/31 10:30:37 Received: brazil
2023/01/31 10:30:38 Received: australia
2023/01/31 10:30:38 Received: japan
2023/01/31 10:30:40 Received: brazil
2023/01/31 10:30:41 Received: japan
2023/01/31 10:30:43 Received: brazil
2023/01/31 10:30:43 Received: japan
2023/01/31 10:30:46 Received: brazil
2023/01/31 10:30:46 Received: japan
```
:::note
有効化からグローバルのエッジでの動作反映までは`数秒`という点も魅力です。速さのチカラですね。
:::

### オブザバビリティ

#### Security events
イベントのグラフを見てみます。

アクション視点でみると、 Block が増えています。
Block でフィルタを掛け、ドリルダウンします。
![Screenshot 2023-01-31 at 19.40.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218045/895590ae-8fc5-e2bf-dd28-f7f26f180efc.png)

ドリルダウンしたものを国でみると、Australia がソースであることがわかります。
![Screenshot 2023-01-31 at 19.40.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218045/afd78ed7-77ac-47f4-10ed-ed653e5b3da6.png)

結果の把握も簡単にできました。
見ながらる、やりながら見る、動作テストにも最適です。

:::note
セキュリティイベントは[サンプリング](https://developers.cloudflare.com/waf/security-events/#known-limitations)データを元にすることがあり、必ずしも生のイベント数を反映はしませんので、ご注意ください。
:::

#### ログ

イベントのログはすでに解説しましたが、HTTP ログの方も確認してみます。前回同様 Instant Logs でサクッと行きます。
![Screenshot 2023-01-31 at 19.48.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218045/9efb654c-5551-f1bb-8358-5232da1fc154.png)


ClientCountry  `au` (Australia) という情報の他にも、リクエストの詳細が記載されています。

## まとめ
以上、 gRPC にファイアウォールを適用し、不要なトラフィックを除く目的を達成、また、そのトラフィックの詳細情報を確認することもできました。

サービスに対する外部からのアクセス(質と量)を具体的に把握し、サービスの安定稼働と健全なセキュリティライフサイクルの継続に役立てることができます。

第3回はレートリミットでオリジンへのリクエスト流入をコントロールしたいと思います。