Serverless NEGを使用して、GAEにIPv4の固定IPアドレスでIP制限をする
はじめに
この記事は ミライトデザイン Advent Calendar 2021 の 23日目の記事となっています。
前回は「docker-laravel の Docker 構成をちゃんと理解する【Dockerfile 編 - PHP】」という記事を書いてくれた takuma でした。
docker-compose 編もあるので、そっちも見てみてください。
さて、今回の記事は、IP制限をGAE(Google App Engine)で実現したいユースケースがあったのですが、GAEは自動的にIPv6に対応するそうで、半固定のIPv6に対しては固定IPで制限ができないという事象がありました。
色々方法はあると思いますが、今回はServerless NEGを使用しロードバランサ経由でGAEにアクセスすることで、IP制限の実現ができたのでそちらの紹介をします。
NEGとは?
そもそもNEGというのは「Network Endpoint Group」の略です。
名前の通り複数のネットワークエンドポイントをまとめたものとなっていて、ロードバランサのエンドポイントとして指定が可能となっています。
NEGにはいくつか種類があり、今回のケースではServerless NEGというものを使用します。
以下の画像はGKE(Google Kubernetes Engine)での画像ですが、イメージしやすいと思ったので持ってきました。
Container-native load balancing on GKE now generally available | Google Cloud Blog より引用
従来のGKEのロードバランサは iptables で再度負荷分散をするという2段階ロードバランシングだったのを、NEGを使用することで直説負荷分散できるといった内容を紹介してくれています。
NEGとは何かという方にはイメージしやすいのではないでしょうか。
【NEGの種類】
- Zonal NEG
- Internet NEG
- Serverless NEG
- Hybrid connectivity NEG
- Private Service Connect NEG
公式:Network endpoint groups overview | Load Balancing | Google Cloud
Serverless NEGとは?
Serverless NEGというのはサーバーレスサービスに対して使用できるNEGです。
NEGは今までGCE(Google Compute Engine)やGKEにしか使用できなかったようですが、Serverless NEGの登場により「App Engine」「Cloud Functions」「Cloud Run」のサーバーレスサービスでも使用ができるようになりました。
そのため、ロードバランサのエンドポイントにサーバーレスサービスを指定し、ロードバランサでIPv4を指定することでGAEにはIPv4でのアクセスとなり、本来やりたかった固定IPの制限が可能になるということです。
環境構築手順
では実際に環境を作ってみましょう。
大きく手順としては以下の通りです。
- GAEをデプロイする
- 静的IPアドレスを取得する
- Serverless NEGを作成する
- バックエンドサービスを作成する
- ロードバランサを設定する
GAEをデプロイする
GAEのアプリケーションがデプロイされている上でIP制限をかけたいというユースケースのため、ここではGAEのデプロイ詳細は省略します。
Laravelの例ですが、IPの確認をするためにエンドポイントに以下のアクションを追加しておくとGAEへのリクエストIPの確認ができます。
public function ip(Request $request): array
{
return [
'ip' => $request->ip(),
'ips' => $request->ips(),
'client_ip' => $request->getClientIp(),
'client_ips' => $request->getClientIps(),
'X-Appengine-User-Ip' => $request->header('X-Appengine-User-Ip'),
];
}
GAEでIPを確認する場合は X-Appengine-User-Ip
ヘッダーから取得して確認します。
公式:Request Headers and Responses | App Engine standard environment for PHP 7 docs | Google Cloud
静的IPアドレスの作成
ロードバランサのエンドポイントに使用するため静的IPアドレスを作成しておきます。
gcloud compute addresses create [IPアドレス論理名] \
--ip-version=IPV4 \
--global
以下のコマンドで予約されている IPv4 アドレスを控えときましょう。
gcloud compute addresses describe [IPアドレス論理名] \
--format="get(address)" \
--global
GUI上でも作成されていることが確認できます
Serverless NEGの作成
GAE用のServerless NEGを作成します。
なお、リージョンについてはGAEと同じリージョンにする必要があります。
gcloud compute network-endpoint-groups create [ServerlessNEG論理名] \
--region=[リージョン名] \
--network-endpoint-type=serverless \
--app-engine-app \
--app-engine-service=default
作成されたことを以下のコマンドで確認します。
gcloud beta compute network-endpoint-groups list
NAME LOCATION ENDPOINT_TYPE SIZE
[ServerlessNEG論理名] [リージョン名] SERVERLESS 0
GUI上でも作成されていることが確認できます。
バックエンドサービスの作成
バックエンドサービスを作成し、バックエンドとして先ほど作成した Serverless NEG を追加します。
gcloud compute backend-services create [バックエンドサービス論理名] \
--global
NAME BACKENDS PROTOCOL
[バックエンドサービス論理名] HTTP
バックエンドサービスにServerless NEGを追加
gcloud compute backend-services add-backend [バックエンドサービス論理名] \
--global \
--network-endpoint-group=[ServerlessNEG論理名] \
--network-endpoint-group-region=[リージョン名]
バックエンドサービスが作成され、Serverless NEGが追加されているかを以下のコマンドで確認しましょう。
gcloud beta compute backend-services list
NAME BACKENDS PROTOCOL LOAD_BALANCING_SCHEME HEALTH_CHECKS
[バックエンドサービス論理名] [リージョン名]/networkEndpointGroups/[ServerlessNEG論理名] HTTP EXTERNAL
GUI上でも確認ができます。
ロードバランサーの設定
まずは受信リクエストをバックエンドサービスにルーティングするためのURLマップを作成します。
gcloud compute url-maps create [ロードバランサ論理名] \
--default-service [バックエンドサービス論理名]
NAME DEFAULT_SERVICE
[ロードバランサ論理名] backendServices/[バックエンドサービス論理名]
ターゲットhttpプロキシを作成しロードバランサに追加
URL マップにリクエストをルーティングするターゲット HTTPS プロキシを作成します。
HTTP ロードバランサの場合、HTTP ターゲット プロキシを作成します
gcloud compute target-http-proxies create [ターゲットhttpプロキシ論理名] \
--url-map=[ロードバランサ論理名]
NAME URL_MAP
[ターゲットhttpプロキシ論理名] [ロードバランサ論理名]
フロントエンド(forwarding rule)をロードバランサに追加
gcloud compute forwarding-rules create [フロントエンド論理名] \
--address=[控えていたIPアドレスを指定] \
--target-http-proxy=[ターゲットhttpプロキシ論理名] \
--global \
--ports=80
ロードバランサ・フロントエンドの確認
以下のコマンドで作成したものを確認しましょう。
$ gcloud compute forwarding-rules list
NAME REGION IP_ADDRESS IP_PROTOCOL TARGET
[フロントエンド論理名] [IPアドレス] TCP [ターゲットhttpプロキシ論理名]
GUIでも確認
ロードバランサにリクエストしてみる
作成したロードバランサにリクエストをしてみましょう。
取得したIPアドレスをURLに入力してアクセスするとデプロイしたアプリケーションの画面が表示されます。
自分の場合はLaravelのアプリケーションをデプロイしたので、Webcomeページが表示されます。
固定IPでアクセスできるかを確認してみる
もともとデプロイしていたアプリケーションのIPを確認するとIPv6でアクセスされていることが確認できます。
次に作成したロードバランサにアクセスしてIPv4でアクセスされていることを確認します。
GAEへアクセスされているIPを調べるために追加したエンドポイントを叩いて X-Appengine-User-Ip
の値を確認すると、固定IPとなっているかと思います。
おわりに
クライアントがIPv6でアクセスしてきたとしても、GAEにはIPv4でアクセスできていることが確認できたと思います。
GAEでは自動でIPv6に対応するため、IPv4の固定IPでIP制限が必要な場合は今回紹介した方法で試してみてください。
この後DNSの設定やSSLの設定をすることで実用化できると思いますが、今回は省略します。
できれば余裕があるときに追記していけたらと思います。
参考
- Google App Engineのアプリは自動的にIPv6対応に - Publickey
- NEG とは何か. はじめに | by Yuki Furuyama | google-cloud-jp | Medium
- Google Cloud Serverless NEG | google-cloud-jp
- サーバーレス NEG の設定 | 負荷分散 | Google Cloud
- NEG(Network Endpoint Group)を使った負荷分散 - Carpe Diem
- Serverless NEG + GAE を試してみる | apps-gcp.com
- Serverless NEG(Network Endpoint Group)を設定しGAEと連携してみた - Qiita