Cloud Functions 関数の IP を固定してみた。
こんにちは、みかみです。
やりたいこと
- アクセス元 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
参考
- Console を使用したクイックスタート | Cloud Functions ドキュメント
- Cloud Functions の料金 | Cloud Functions ドキュメント
- VPC ネットワークの使用 | Virtual Private Cloud ドキュメント
- サーバーレス VPC アクセスの構成 | Virtual Private Cloud ドキュメント
- 料金 | Virtual Private Cloud ドキュメント
- Cloud NAT を構成する | Cloud NAT ドキュメント
- Cloud NAT の料金 | Cloud NAT ドキュメント
- Google Cloud の無料プログラム | Cloud Cloud ドキュメント
- [GCP]Cloud Functionsで送信(静的)IPアドレスを固定したい話 | アイソルート開発者ブログ
- GCP CloudFunctionsの実行IPアドレスを固定化する方法 | Qiita