🪬

Serverless NEGを使用して、GAEにIPv4の固定IPアドレスでIP制限をする

2021/12/24に公開

はじめに

この記事は ミライトデザイン 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 ) での画像ですが、イメージしやすいと思ったので持ってきました。

network_endpoint_group
Container-native load balancing on GKE now generally available | Google Cloud Blog より引用

従来の GKE のロードバランサは iptables で再度負荷分散をするという 2 段階ロードバランシングだったのを、 NEG を使用することで直説負荷分散できるといった内容を紹介してくれています。

NEG とは何かという方にはイメージしやすいのではないでしょうか。

Serverless NEG とは

Serverless NEG というのは サーバーレスサービスに対して使用できる NEG です。

NEG は今まで GCE ( Google Compute Engine )GKE にしか使用できなかったようです。

しかし、 Serverless NEG の登場により「App Engine」「Cloud Functions」「Cloud Run」のサーバーレスサービスでも使用ができるようになりました。

そのため、ロードバランサのエンドポイントにサーバーレスサービスを指定し、ロードバランサで IPv4 を指定することで GAE には IPv4 でのアクセスとなり、本来やりたかった固定 IP の制限が可能になるということです。

環境構築手順

では実際に環境を作ってみましょう。

大きく手順としては以下の通りです。

  1. GAE をデプロイする
  2. 静的 IP アドレスを取得する
  3. Serverless NEG を作成する
  4. バックエンドサービスを作成する
  5. ロードバランサを設定する

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'),
    ];
}

静的 IP アドレスの作成

ロードバランサのエンドポイントに使用するため静的 IP アドレスを作成しておきます。

gcloud compute addresses create [IPアドレス論理名] \
    --ip-version=IPV4 \
    --global

以下のコマンドで予約されている IPv4 アドレスを控えときましょう。

gcloud compute addresses describe [IPアドレス論理名] \
    --format="get(address)" \
    --global

GUI 上でも作成されていることが確認できます。

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 上でも作成されていることが確認できます。

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 上でも確認ができます。

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 でも確認します。

GUI のスクリーンショット

GUI のスクリーンショット

ロードバランサにリクエストしてみる

作成したロードバランサにリクエストをしてみましょう。

取得した IP アドレスを URL に入力してアクセスするとデプロイしたアプリケーションの画面が表示されます。

自分の場合は Laravel のアプリケーションをデプロイしたので、 Webcome ページが表示されます。

GUI のスクリーンショット

固定 IP でアクセスできるかを確認してみる

もともとデプロイしていたアプリケーションの IP を確認すると IPv6 でアクセスされていることが確認できます。

GUI のスクリーンショット

次に作成したロードバランサにアクセスして IPv4 でアクセスされていることを確認します。

GAE へアクセスされている IP を調べるために追加したエンドポイントを叩いて X-Appengine-User-Ip の値を確認すると、固定 IP となっているかと思います。

GUI のスクリーンショット

おわりに

クライアントが IPv6 でアクセスしてきたとしても、 GAE には IPv4 でアクセスできていることが確認できたと思います。

GAE では自動で IPv6 に対応するため、 IPv4 の固定 IP で IP 制限が必要な場合は今回紹介した方法で試してみてください。

この後 DNS の設定や SSL の設定をすることで実用化できると思いますが、今回は省略します。

できれば余裕があるときに追記していけたらと思います。

参考

Discussion