Google Cloud VPC / VPC Service Controls 入門 ― ちいかわ「人魚の島のひみつ」で学ぶ
こんにちは!今日はちょっと変わった切り口の話をさせてください。
私は普段、Python でアプリケーション(Web の API など)を書いているエンジニアです。ありがたいことに Google Cloud の Top Engineer を2年連続でいただいたりもしているのですが、それでもネットワークまわりは触るたびに新鮮に詰まります。アプリを書くのと、その下を通る配線を設計するのは、まったく別の筋肉なんですよね。
先日、その苦手な方をちゃんとやろうと思い立ち、Google Cloud の VPC を一から組み直す検証をしていました。丸2日ほど格闘して、ようやく全部つながった深夜、ふと思ったんです。
これ、人魚の島の話では?
⚠️ 以下、ちいかわ「島編(セイレーン編)」の核心に触れます。 未読の方はぜひ公式Xや単行本を先にどうぞ。
なお本記事は非公式のファンコンテンツで、権利者・関係各社とは一切関係ありません(詳細は末尾に記載しています)。
ざっくりおさらいすると、こういう話でした(1コマの画像と、論評に必要なセリフのみを引用します)。
- 「おいしいものが食べ放題の島での簡単なお仕事」というチラシを見て、ちいかわ達が島へ渡る
- 島では、歌で島民を眠らせて捕食する怪物セイレーンと、手下の人魚たちが暴れていた
- しかし真相は、島民の側の裏切りだった。かつて親友の片方が衰弱したとき、もう片方が「ずっと一緒に生きたい」と願い、人魚を食べると不老不死になれるという伝承を実行してしまう
- 2人は人魚を騙して捕らえ、スープにして食べた。永遠の命を手に入れた
- 仲間を殺されたセイレーンは激怒し、犯人を捜して島を襲い続けていた
- ちいかわ達がセイレーンを洞窟に封じて危機は去る。だが犯人の2人は罪を隠し通したまま島に残り、セイレーンも犯人を捜し続けている
……見てください。島の中にあった、持ち出してはいけないものが、島の中の正規の住人によって奪われ、二度と元に戻らなくなった話です。
私がその日ずっと設定ファイルに書いていたことと、構造がまったく同じでした。というわけで今日は、この島を借りながら Google Cloud のネットワークとセキュリティの基本を5つ解説してみます。びっくりするほど素朴な話しかしていませんので、ネットワークが苦手な方こそ読んでみてください。
順番は、島編と同じにします。つまり、チラシの話からです。
1. IAM ― 権限とは、チラシである
Google Cloud には IAM(アイアム:誰が何をしていいかを決める権限管理の仕組み)というものがあります。
これ、島編で言えばあのチラシがわかりやすいと思います。
「おいしいものが食べ放題の島での簡単なお仕事」

出典: ナガノ『ちいかわ』2023年3月15日 ちいかわ公式X(@ngnchiikawa)投稿 https://x.com/ngnchiikawa/status/1635963443823136770 より引用
うさぎの顔にチラシが張り付いていて、それを見たちいかわとハチワレが丸太の陰で「ワァ!!」と驚いている場面です。
この構図が、権限の話としてよくできているなと思うんです。チラシは、顔に貼り付いている側からは読めません。 読まれたのは表の一行、「おいしいものが食べ放題の島での簡単なお仕事」だけ。その紙が実際にどこまでを許すのかは、誰も確かめていない。
エンジニアが設定ファイルに書く権限も、たいていこうです。ロール名の雰囲気だけ見て渡して、渡された側も自分に何が許されているか正確には把握しない。そして誰もあとから読み返さない。あの紙一枚が、そういう状態のまま、島での活動を可能にしたわけですね。
チラシを持っていれば、島に渡って働いていい。ちいかわ達が島に上陸できたのは、このチラシがあったからです。「あなたはここで、これをしてよい」と示すもの──それが権限であり、IAM が管理しているものの正体です。
エンジニアは毎日こういう設定を書いています。
# 「このプログラムは、データを読んでよい」というチラシを渡す
gcloud projects add-iam-policy-binding my-project \
--member="serviceAccount:sa-worker@..." \
--role="roles/bigquery.dataViewer"
そして、ここで1つ引っかかることがあります。
チラシは「島で働いてよい」という許可です。では、「人魚を食べてよい」という許可でもあるのでしょうか。
島民2人も同じでした。彼らは島に住んでいい立場でしたが、その立場は人魚を捕らえていい理由にはならない。でも──IAM から見ると、その2つの区別がつかないんです。正規の住人が、島の中で、島にあるものに触れている。記録の上では、何も異常がない。
だから誰も止められなかったし、今も罪を隠し通したまま島に残っている。
では、その区別は誰がつけるのか。答えは IAM の外側、「何を持っているか」ではなく「どこから来て、どこへ出ていくのか」で判断する仕組みにあります。ただしその話をするには、線を引く対象──つまり島そのものを先に見てもらう必要があります。遠回りに見えますが、まず島を作るところから始めさせてください。
2. VPC ― 島そのものの話
Google Cloud で何かを動かすとき、その裏には必ず VPC(ブイピーシー / Virtual Private Cloud:Google Cloud の中に作る、自分専用の閉じたネットワーク)があります。日本語にすると「仮想プライベートクラウド」ですが、要するに、
だだっ広い海の上に、自分の島を1つ確保する
という話です。
ここでちょっと面白いのが、Google Cloud ではプロジェクトを新しく作ると default という名前の VPC が最初から付いてくることです。何も考えずにすぐ使えます。
……ここでもまたチラシの話になってしまうのですが、default VPC は、あのチラシで言えば**「簡単なお仕事」の方**、という感じがしませんか。
実際、便利なんです。私も普段アプリを作るときはお世話になっています。ただこの島、世界中のリージョン(データセンターのある地域)すべてに自動で桟橋が生えているんですね。東京にも、アイオワにも、ベルギーにも、区画が勝手に用意されている。
とりあえず動かすには最高ですが、「どこから何が出入りしているか」を把握したい場面では桟橋が多すぎて追えない。なので今回は default を使わず、島を自分で作るところから始めました。
# 島をつくる(--subnet-mode=custom が「桟橋は自分で決める」の意味)
gcloud compute networks create vpc-sc-net --subnet-mode=custom
# 島の中に、住む区画を1つだけ用意する
gcloud compute networks subnets create sn-run-an1 \
--network=vpc-sc-net \
--region=asia-northeast1 \
--range=10.10.0.0/24
10.10.0.0/24 は区画の広さで、252 軒分の住所という意味です。ネットワークの教科書だと /24 は 254 軒と習うのですが、Google Cloud は各区画で4つの住所を自分用に予約するので、2つ少なくなります。この区画のことをサブネットと呼びます。今回は東京(asia-northeast1)に1つだけ作りました。
ここまでで「島ができた」状態です。まだ何の守りもありません。
3. ファイアウォール ― 港に検問を置く。ただし出る側にも
島ができたら、次は出入りの管理です。Google Cloud ではファイアウォールルール(通していい通信と、通してはいけない通信を仕分ける設定)として書きます。
ここで大事なのが、方向が2つあるということ。
| ことば | 読み | 意味 | 島で言うと |
|---|---|---|---|
| ingress | イングレス | 外から中に入ってくる通信 | 島に上陸してくる者 |
| egress | イーグレス | 中から外に出ていく通信 | 島から出ていく者 |
セキュリティの入門的な説明では、たいてい ingress の話ばかりされます。「怪しいやつを入れるな」ですね。島で言えばセイレーン対策です。もちろん大事です。
でも、通信には出ていく方向もあります。中にいる者が、中にあるものを外へ運び出す経路です。ingress をどれだけ固めても、こちらは1ミリも管理できていません。だから出口も締める。
……島編を最後まで読んだ方は、いま少し引っかかったかもしれません。その引っかかりは正しくて、5章で回収します。
私が今回書いた設定は、ほぼこれだけです。
# 決められた港(1つだけ)への通行は許可
gcloud compute firewall-rules create allow-egress-restricted-vip \
--network=vpc-sc-net \
--direction=EGRESS --action=ALLOW \
--rules=tcp:443 \
--destination-ranges=199.36.153.4/30 \
--priority=1000
# それ以外、島から出るのは全部禁止
gcloud compute firewall-rules create deny-egress-all \
--network=vpc-sc-net \
--direction=EGRESS --action=DENY \
--rules=all \
--destination-ranges=0.0.0.0/0 \
--priority=65534
priority(優先度)は数字が小さい方が強いというルールです。「原則すべて禁止(65534)、ただしこの港だけは許可(1000)」という書き方になっています。
まず全部閉じて、必要な穴だけ開ける。 これはセキュリティ設計の基本で、ホワイトリスト方式と呼ばれます。逆(原則許可して、悪いものだけ塞ぐ)は必ずどこかで漏れます。
塞ぎ忘れには気づけませんが、開け忘れは動かないのですぐ気づく。間違えたときに安全側に倒れる方を選ぶ、という発想ですね。
なお 0.0.0.0/0 は「全世界」なので、この書き方だと島の中の行き来まで塞いでいます。今回は住人が1人だけなので困りませんでしたが、複数のサービスを島に置くなら、内側向けの許可を別に足す必要があります。
4. Private Google Access ― 島の中だけで用を済ませる裏道
さて、ここで困ったことが起きます。
島から出るのを全部禁止してしまったので、島の住人が仕事をできなくなりました。
今回私が動かしていたのは、Google Cloud の Cloud Run(コンテナをそのまま動かせるサービス。「サーバーの面倒は見たくないけどアプリは書きたい」人間の味方です)に載せた API でした。この API は BigQuery(大量データを扱うデータベース)と Agent Platform(Gemini などの AI モデルを使うサービス)に問い合わせをします。
ところが、これらは全部「島の外」にいます。全面禁止したので当然つながりません。
じゃあ egress を開ければいいのかというと、それだと元の木阿弥です。ここで登場するのが Private Google Access(プライベートグーグルアクセス:島から外洋に出ることなく、Google のサービスにだけ行き来できる専用の通用口)という Google Cloud の仕組みです。
先ほど1つだけ許可していた 199.36.153.4/30 が、その通用口の住所でした。これは Google が公開している固定の住所で、全ユーザー共通です(/30 なので、実体は 199.36.153.4 から .7 までの4つです)。
# 区画に「通用口を使ってよい」という設定を入れる
gcloud compute networks subnets update sn-run-an1 \
--region=asia-northeast1 \
--enable-private-ip-google-access
ただ、ここに私はきれいにハマりました。丸1日溶かしました。
通用口を用意しても、住人はその場所を知らない。
住所を調べる仕組みを DNS(ディーエヌエス:「〇〇.com」のような名前を、実際の住所(IP アドレス)に変換する電話帳のようなもの)と言います。何もしないと、住人は普通の電話帳を引いて「外洋を渡った先」の住所を教えられてしまう。でもそっちは egress 禁止なので、いつまで経っても届かない。
通信できない原因が、通信の設定ではなく電話帳にあったわけです。これは自力ではなかなか気づけませんでした。
なので、島の中だけで通用する電話帳を作ってあげます。Google Cloud では Cloud DNS のプライベートゾーンという機能です。
# 島専用の電話帳をつくる
gcloud dns managed-zones create googleapis-zone \
--dns-name="googleapis.com." \
--networks=vpc-sc-net \
--visibility=private
# 「通用口はこの4つの住所です」と登録する
gcloud dns record-sets create restricted.googleapis.com. \
--zone=googleapis-zone --type=A --ttl=300 \
--rrdatas=199.36.153.4,199.36.153.5,199.36.153.6,199.36.153.7
# 「Google に用があるなら、あの通用口へ行きなさい」と書き込む
gcloud dns record-sets create "*.googleapis.com." \
--zone=googleapis-zone --type=CNAME --ttl=300 \
--rrdatas=restricted.googleapis.com.
行き先を書くだけでは足りなくて、その行き先の住所も同じ電話帳に載せておく必要があります。島専用の電話帳を作った時点で、島の住人は googleapis.com について外の電話帳を引かなくなるからです。A レコードを忘れると、案内した先が「そんな家はありません」になります。
これでようやく、住人は外洋に出ることなく用事を済ませられるようになりました。
道を作るだけでは足りなくて、道があることを教える地図まで用意して、はじめて人は歩ける。当たり前のようでいて、アプリばかり書いていると抜け落ちる視点でした。
5. VPC Service Controls ―「チラシは、人魚を食べていい許可ではない」
ここからが本題です。1章で立てた問いに戻ります。
ここまでの2〜4章は全部「経路」の設計でした。島を作り、港に検問を置き、通用口を通した。でも、経路をどれだけきれいに整えても、まだ防げないことが残っています。
正規の資格を持った者が、正規の経路で、持ち出してはいけないものを持ち出すケースです。
そう、島民2人がやったことです。3章で「引っかかったかもしれません」と書いたのは、これのことでした。彼らは侵入者ではありません。島の正規の住人でした。怪しい上陸もしていないし、禁じられた航路も使っていない。ただ、島の中にいた人魚を、島の中で捕らえて、食べた。3章で出口を締めましたが、あれは「どこ宛の通信か」しか見ていないので、これは止められません。
チラシは「島で働いてよい」という許可であって、「人魚を食べてよい」という許可ではありません。 1章の問いへの答えはこれです。そして、これを設定として書ける仕組みが、ちゃんとあります。
ただし先に正直なところを書いておくと、これから紹介する仕組みでも**「島の中で起きたこと」そのものは止められません**。止められるのは、それが島の外へ出ようとした瞬間です。人魚がスープになる前ではなく、そのスープを船に積もうとしたところで止まる。それでも、一番取り返しのつかない一線がそこにあるなら、塞ぐ価値はあります。
資格ではなく、境界で止める
ここで登場するのが VPC Service Controls(ブイピーシー サービスコントロール:資格とは別の軸で、データが境界の外に出ることを禁止する Google Cloud の仕組み)です。今回いちばん検証したかったのがこれでした。
ルールは、恐ろしくシンプルです。
島の中のものは、島の外に出せない。どんなチラシを持っていても。
具体的にどうなるか。私の API は、Google が公開している誰でも読める公開データ(bigquery-public-data という、練習用によく使われるデータ置き場)を読みに行っていました。権限的には何の問題もありません。世界中の誰でも読めるデータです。
それが、境界を有効にした瞬間に弾かれました。
403 Request is prohibited by organization's policy.
「読んでるだけなのに?」と思いますよね。私も最初はそう思いました。でも、これが正しいんです。
外のデータを読める経路が開いているということは、その経路で逆向きにも流せるということだからです。持ち込めるなら、持ち出せる。だから経路そのものを塞ぐ。「読むだけだから安全」という言い訳を、この仕組みは受け付けません。
そして何より、この仕組みが守ろうとしているのは取り返しのつかなさです。
人魚は、食べられてしまったら戻ってきません。2人が手に入れた不老不死も、返上できません。セイレーンの怒りも収まりません。一度起きたことは、なかったことにできない。だからあのビターな余韻だけが残る。
データもまったく同じです。流出したデータは、削除ボタンでは消えません。「後から取り消せないものは、そもそも出さない」──セキュリティの設計思想は、だいたいこの一点に集約されます。
余談 ―「チラシさえ持っていれば、どこから来てもOK」にもできる
ここで正直に書いておきたいことがあります。
実は VPC Service Controls には、「このチラシを持っている者なら、どの経路から来ても通す」という例外ルールを書く機能があります。禁止されている使い方ではありません。Google 自身が正式な機能として提供していて、案内もしています。
ただ、これを書いた瞬間に判断の軸が「どこから来たか」から「何を持っているか」に戻ります。つまり、1章の IAM だけの世界に逆戻りするということです。せっかく港を1つに絞ったのに、チラシ持参なら外洋のどこからでも上陸できることになる。今日ずっと書いてきた話が、その1行で消えます。
しかも厄介なのが、穴が開いていても動作は何も変わらないことです。アプリは正常に動き続けるので、設定を読み返さない限り誰も気づきません。ファイアウォールの閉め忘れは「動かない」のですぐわかるのに、こちらは静かです。
とはいえ、この機能が正解になる場面もあります。たとえば GitHub Actions のような外部のサービスからデプロイする場合、相手のアドレスが毎回変わるので経路では絞れません。こういうときは「何を持っているか」で判断するしかない。
大事なのは、どちらの軸で判断しているかを自分で把握しておくことだと思っています。「面倒だからチラシで通す」と「経路で絞れないからチラシで通す」は、設定ファイルの上ではまったく同じ1行なのに、意味がぜんぜん違う。
今回の私の検証では、この例外は使いませんでした。使ってしまうと「経路を通らないと弾かれる」ことを確かめられないからです。
おまけ ― 結界を張るとき、最初に閉め出されるのは自分
最後に、実際にやってみて一番おもしろかった話を。
境界を有効にした瞬間、私が自分の島に入れなくなりました。
自宅の PC は当然、島の外です。ログを見ることも、API を更新することも、管理画面を開くこともできない。プロジェクトのオーナー権限を持っているのに、です。「どんなチラシを持っているかではなく、どこから来たかで判断する」というのは、そういうことでした。
もちろん対策はあって、「この住所からの訪問だけは特別に許可する」という名簿(アクセスレベルと言います)を先に作っておきます。会社なら会社の回線、私の場合は自宅の回線を登録しました。
ここでやってはいけないのが、面倒だからと「どこからでも許可」にしてしまうこと。
❌ 0.0.0.0/0 ← 「全世界どこからでもOK」の意味
これを書いた瞬間、ここまで積み上げた設計が全部無意味になります。島に結界を張ったのに、門に「ご自由にお入りください」と貼るようなものです。
セキュリティの設定って、だいたいこうなんですよね。正しく設定するほど自分が不便になる。その不便さに耐えられるかどうかが、実は一番難しい。楽な道はいつでもすぐそこにあって、いつでも手が届いてしまう。
……「ずっと一緒に生きたい」という願いそのものは、まっすぐで、わかるものでした。あの2人が選んでしまったのも、たぶんそういう道だったのだと思います。
まとめ ― 今日覚えて帰ってほしい5つのことば
| ことば | 意味 | 島で言うと |
|---|---|---|
| IAM | 誰が何をしてよいかを決める権限管理 | 島で働いてよいと示すチラシ |
| VPC | Google Cloud の中に作る、自分専用の閉じたネットワーク | 島そのもの |
| ファイアウォール / ingress・egress | 出入りする通信を仕分ける設定と、その方向 | 港の検問。セイレーン対策だけでは足りない |
| Private Google Access | 外洋に出ずに Google のサービスへ行き来する通用口 | 島の中だけで用を済ませる裏道 |
| VPC Service Controls | 資格とは別の軸で、持ち出しそのものを禁じる境界 | チラシは人魚を食べていい許可ではない |
この5つ、入門ドキュメントだと別々のページに出てくる話です。でも実際に手を動かすと、つながりが見えてきます。
IAM は入口です。ほとんどの人はここから入るし、多くの場面ではここまでで足ります。ただ IAM だけでは「正規の住人が持ち出す」を止められない。そこから先の4つは、今回のように「島の中からしか外に出られない」構成にするなら、この順番でしか組めません。島がなければ検問は置けないし、検問を置いたら通用口が要る。通用口を作ったら地図が要る。そして全部整ってようやく、「持ち出し禁止」の結界が意味を持つ。
順番があるということは、どれか1つだけやっても効かないということでもあります。ネットワークのセキュリティが難しいと言われるのは、たぶんここです。
普段アプリを書いていると、こういう層はマネージドサービスがよしなにやってくれるので、意識しないまま過ごせてしまいます。でも一度自分で組んでみると、アプリの安全性が、アプリの外側でどれだけ支えられているかがよく見える。今回いちばんの収穫は、たぶんそれでした。
島編がずっと心に残るのは、悪意ある侵入者の話ではなく、内側にいた誰かが一線を越えてしまった話だからだと思います。そして残念ながら、現実の情報漏洩もその形をしていることが多い。
深夜に設定ファイルとにらめっこしながら、私はずっと島のことを考えていました。守るというのは、扉に鍵をかけることではなくて、持ち出す経路を1つずつ塞いでいく地道な作業なんだな、と。
……そして今日も、私は自分で作った結界の前で「あっ、家の回線のアドレスが変わってる」と言いながら、名簿を書き直しています。守りが固いというのは、そういうことなのでした。
(※本記事は非公式のファンコンテンツです。『ちいかわ』に関する権利は権利者に帰属し、当サイトは権利者・関係各社とは一切関係ありません。掲載した画像は、論評の対象として著作権法第32条に基づき1コマのみ引用したものであり、セリフの引用も論評に必要な範囲に限っています。作品の全体はぜひ公式Xや単行本でお楽しみください。)