Cloud Functions 関数の IP を固定してみた。

2021.10.08

こんにちは、みかみです。

やりたいこと

  • アクセス元 IP 制限があるシステムに、CLoud Functions からアクセスしたい
  • Cloud Functions の IP を固定したい

Cloud Functions 関数を作成

IPアドレス確認ページにアクセスしてレスポンスを print する、以下の Pythonコードを Cloud Functions 関数にデプロイしました。

from urllib import request

url = 'https://rakko.tools/tools/2/'

def get_source_ip(event, context):
    response = request.urlopen(url)
    content = response.read()
    response.close()

    html = content.decode()
    body = html.split('<textarea id="resultTextArea">')[1].split('</textarea>')[0]
    print(body)

手動でテスト実行してみます。

ログ出力結果から、アクセス元 IP は "グローバルIPアドレス" "107.178.234.30" とのことです。

少し時間を置いてから再度実行してみると

今度は "グローバルIPアドレス" "107.178.234.94" とのことで、やはり先ほどとは異なる IP アドレスからのアクセスになっています。

VPC を作成

VPC ネットワーク管理コンソールから、「VPC ネットワークを作成」します。

サーバレス VPC アクセスコネクタで指定するため、サブネットの CIDR 範囲は /28 で作成しました。

サーバレス VPC アクセスコネクタを作成

続いて、サーバレス VPC アクセスコネクタを作成します。

VPC ネットワークのナビゲーションメニュー「サーバレス VPC アクセス」から、「コネクタを作成」しました。

Cloud NAT を作成

管理コンソール「ネットワーク サービス」内の「Cloud NAT」から、「NAT ゲートウェイを作成」します。

合わせて、ルーターを新規作成し、

静的IPアドレスを取得しました。

Cloud Functions に サーバレス VPC アクセスコネクタを割り当て

Cloud Functions 編集画面「ランタイム、ビルド、接続、セキュリティの設定」を開いて「接続」タブをクリックし、「VPC コネクタ」に先ほど作成したサーバレス VPC アクセスコネクタを指定して、「すべてのトラフィックを VPC コネクタ経由でルーティングする」項目をチェックします。

編集内容のデプロイが完了したら、再度手動でテスト実行してみます。

アクセス元の IP が "35.200.22.202" になりました。 これが Cloud NAT に指定した静的 IP と一致していれば、期待通り NAT の固定 IP でのアクセスができているわけです。

NAT の IP を確認してみます。

「NAT IP アドレス」項目に記載の IP 35.200.22.202 と一致しています。

しばらく時間を置いて再度実行しても、今度は IP が変わることなく、同じ IP からアクセスしていることが確認できました。

Cloud Functions 関数から、固定 IP でアクセスすることができました。

料金

Cloud NAT に対しては、時間あたりの料金とデータあたりの料金が課金されます。

VPC やサブネットの作成には料金はかかりませんが、外部サービスなどへの下り(外向き)のトラフィックには課金が発生します。また、Cloud NATに紐付ける静的 IP アドレスには時間単位で課金が発生するとのことです。

Cloud Functions は、呼び出し回数とコンピューティング時間に応じて課金が発生しますが、月ごとに最初の 200 万回呼び出しまでは無料で利用することができます。

おまけ

今回動作確認に利用させていただいた ラッコツールズ さんの IPアドレス確認 ページ、curl などでアクセスしてみると・・・

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
                                     <!-- ...JdHH""""""""""MHHgJ...
                                .-W9"!                      ?""Mg..
                            .JT"`                                .THa,
                         .."!                                        ?Ha.
                       .#^                                             .Wm.
                     .M"                                                 (MJ.
                   .M"                                                     WMMNg..
                .-@'   .MMMN,                                          ..(; TMMMM"
            ..gNJJZ^ .M8rrvrdM,               dMMNNgJ,                7T"=   dM[
        ..gMMMMMMNgggM8rrrrrrrdN.                 `!!                         X,     `   `   `   `
         ?MMMMMMMMNgMSrrrrrrrrrd@                                             .N
    `       ?MMMMMB0rrrrrrrrrwq#!    `   `                `  `  `  `           d]
       `  .+MSrrrrrrrrrrrwggg#^             `     ..                  `   JMN. .N
         JM0rrrrrrrrrrrAM"`                      (MMN,                    dMM}  d{
       .MBrrrrrrrrrrrrwM^                        MMMM]               ......T"  .db
      .MSrrrrrrrrrrrrrdF                         ,HM9`            .dMF     ?4,   ?m.
     .MSrrrrrrrrrrrrrrM%           `   `                        .MMMM]       ,N.  .W,  `  `  `  `
     MBrrrrrrrrrrrrrrrM]                                       .MMMMMM,       .b    Up
    .#rrrrrrrvwrrrrrrrwM,                                      (MMMMMMMMNNNNMMMM     Wc
   .MSrrrrrrwM#TNmrrrrrdM,                `  `          `  `   ,MMMMMMMMMMMMMMMF    ..NJdY"""""""7'
   .#rrrrrrwMFM  ?NgvrrrrMm.     ......-JJ+++&++JJ(......       (HMMMMMMMMMMMM"  7!   M{
   d@rrrrrrdN+h,   (NsrrrrdN/7!`                          ??~.     ?"""W"""=`         M:
   dKrrrrrwM??J\     WmrrrrwMp                                         ?          `~?dB"YG+...
   MSrrrrrdF .#       ?NyrrrrdN,                   ....+77!`          .)         ...JD       ?""G..
   MwrwkrrdF.MMN....J-..MmrrrrZM, .     .p   ...7""`       .?!       .f          .JMa.
   MwrdSrrM]  .MMMMMMMMMMe?rrrrrT=N.dex.J#4Y"`          .J^        ..N........JkY"   7Q.
   WmyMKrrM] .MMMMMMMMMMMMk.1rrrro.WMMNgMMMMN,.       .V!       ..dMMMMMMMMMMMMMa.  ...(S,
    .T"WMH"`dMMMMMMMMMMMMMMN,?rrrrr,/MMMMMMMMMMMNg-..H+....(gNMMMMMMMMMMMMMMMMMMMMF.MMMN,."
            .MMMMMMMMMMMMMMMMp.Orrrro,HMMMMMMMMMMM@jMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM>MMMMMMN.
            .MMMMMMMMMMMMMMMMMN,1rrvrw,TMMMMMMMMBjMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM2MMMMMMMMp
            MMMMMMMMMMMMMMMMMMMM,(rrvvzi..?WMM#QMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNMMMMMMMMMN.
           .MMMMMMMMMMMMMMMMMMMM#t.uzzuzzzzo,7MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN.
           MMMMMMMMMMMMMMMMMMMMMM,.Xzzzuzuzzzw,7MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMb
          .MMMMMMMMMMMMMMMMMMMMMMN-.zuzzzzuzuzzn,TMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM.
          dMMMMMMMMMMMMMMMMMMMMMMMb~.zzuzzzuzzzzzn,WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM[
         .MMM@MMMMMMMMMMMMMMMMMMMMMh_.Xzuzzzuzuzzzz+(MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM]
         .MMMXMMMMMMMMMMMMMMMMMMMMMMN,.Ozuzzzuzzuzzzw,TMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM]
         dMMMzMMMMMMMMMMMMMMMMMMMMMMMMe 1zzuzzzuzzuzzzl,MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM:
         MMMMvMMMMMMMMMMMMMMMMMMMMMMMMMN,?uzzzuzzzzuzzzw,TMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMF
         MMMM]MMMMMMMMMMMMMMMMMMMMMMMMMMMNJ?zzzuzuzzuzzzzi,MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM=
        .MMMMbJMMMMMMMMMMMMMMMMMMMMMMMMMMMMMm,?7wzzzzuzzzzw.UMMMMMMMMMMMMMMMMMMMMMMMMMMMY""!
        .MMMMM,MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNg.,?7CXzuzzuu?MMMMMMMMMMMMMMMMMMMMMMMM.
        .MMMMMb(MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNg.,?7Xzn,MMMMMMMMMMMMMMMMMMMMMMM[
        .MMMMMMp?MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNa,?w,TMMMMMMMMMMMMMMMMMMMMMF
        .MMMMMMMb?MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN,?i(MMMMMMMMMMMMMMMMMMMM#
        .MMMMMMMMN,WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMR.w,TMMMMMMMMMMMMMMMMMMM --><title>IPアドレス確認:自分のグローバルIPアドレスを調べる | ラッコツールズ🔧</title>
(省略)

ラッコが返ってきます!(らっこかわいいv

まとめ(所感)

思ったよりも簡単に Cloud Functions に固定 IP を設定することができました! NAT の固定 IP 設定や、ルートテーブルのエントリの作成も、管理コンソールの GUI 操作だけで特に迷うことなく実行できました。

なお、今回のシステム構成図は、下記アイソルートさまのブログで非常にわかりやすく紹介されています。

外部システムなどに対して、固定 IP からのアクセスが必要になるケースも多々あるかと思いますが、Cloud Functions を使えば、サーバを建てて処理する場合に比べると、遥かにお安く利用できてしまいます。

Cloud Functions だけでなく、App Engine や Cloud Run でもサーバーレス VPC アクセスが利用できるとのことなので、サーバレス実装の幅も広がり嬉しい限りですv

参考