GCP VPCファイアウォール完全攻略:優先度・ステートフル処理の裏側と、現場でハマる「通信断」の防ぎ方
こんにちは。数々の修羅場をくぐり抜けてきたシニアSREの私です。
本番環境のリリース前夜、突然APIサーバーへの疎通がパッタリと途絶え、Cloud Monitoringのダッシュボードが真っ赤に染まる……。クラウドインフラを触るエンジニアなら、誰もが一度はこの冷や汗をかく経験をしていることでしょう。
GCP(Google Cloud)のVPCネットワークにおいて、パケットの生死を握る最大の関所が「VPCファイアウォールルール」です。一見すると「IPとポートを指定して通す/落とすだけ」のシンプルな機能に見えますが、その内部挙動である優先度の評価ロジックやステートフル(Stateful)なコネクション追跡の仕組みを正確に理解していないと、思わぬハマり穴に足を取られます。
今回は、パケットがGCPの仮想ネットワークをどのように駆け抜け、ファイアウォールによってどう裁かれているのか、現場のリアルな知見を交えて徹底解説します。
—
1. ファイアウォールルールの評価順序と「プライオリティ(Priority)」の罠
AWSのSecurity Group(SG)を使ったことがある人は、GCPのファイアウォールに初めて触れたとき戸惑うかもしれません。AWSのSGは「インスタンス単位でルールの和集合(許可が優先)」として評価されますが、GCPのVPCファイアウォールはグローバルなネットワーク全体に適用され、優先度(Priority)の数値順に評価されます。
0から65535までの数値が持つ意味
GCPのファイアウォールルールでは、0 から 65535 までの整数で優先度を指定します。
- 数値が小さいほど優先度が高い(例:
1000は2000よりも先に評価される)。 - 最も優先度が高いのは
0。
ここで重要なのは、「最初にマッチしたルールが適用され、それ以降のルールは評価されない(First Match Wins)」という原則です。一般的なステートフルファイアウォールの挙動そのものですが、ルールが増えてくると「意図しない上位のルールにパケットが吸い込まれてしまう」という事故が頻発します。
暗黙的ルール(Implicit Rules)の存在を忘れるな
自分で作成したカスタムルール以外に、GCPのすべてのVPCには削除できない「暗黙的ルール」が最下層に存在します。
| 優先度 | 方向 | 動作 (Action) | 送信元 / 宛先 | プロトコル / ポート |
| :— | :— | :— | :— | :— |
| 65535 | イングレス (Ingress) | 拒否 (Deny) | 0.0.0.0/0 (すべて) | すべて |
| 65535 | エグレス (Egress) | 許可 (Allow) | すべて (0.0.0.0/0) | すべて |
- イングレスの暗黙的拒否(Priority: 65535):
明示的に許可しない限り、外部からのすべての受信パケットは容赦なくドロップされます。「ファイアウォールを作ったのに繋がらない」という場合の9割は、この暗黙的拒否に引っかかっています。
- エグレスの暗黙的許可(Priority: 65535):
デフォルトでは、インスタンスから外への送信はすべて許可されています。ただし、セキュリティ要件が厳しい環境では、これを Deny に書き換えて外向きの通信をホワイトリスト制にすることも可能です。
—
2. コネクションの命運を握る「ステートフル(Stateful)」の挙動
GCPのVPCファイアウォールは、すべてのルールがステートフルとして動作します。インフラエンジニアにとっては当たり前ですが、この挙動を正しく把握していないと、エグレス(送信)とイングレス(受信)の設計で矛盾を生みます。
ステートフル処理の実際
1. リクエスト送信(イングレスまたはエグレス):
ローカルの仮想マシン(VM)から外部へ、あるいは外部からVMへ通信を開始するとき、ファイアウォールルールが評価されます。ここで許可(Allow)されると、GCPの仮想ネットワーク基盤はその通信の「コネクション状態(ステート)」をトラッキングテーブルに記録します。
2. レスポンス受信:
通信の相手側からの応答パケットが戻ってきたとき、戻りの通信に対するファイアウォールルールは評価されません。 コネクションが確立されている(トラッキングされている)ため、戻りパケットは自動的に通過します。
> ⚠️ ここが現場の落とし穴:
> 「インバウンド(イングレス)で外部からのアクセスをすべて拒否しているから、アウトバウンド(エグレス)も自由に通して大丈夫だろう」と油断してはいけません。もし厳格なセキュリティ要件でエグレスルールを絞る場合、ステートフルの戻りパケットの動向を意識しないと、思わぬ通信断を引き起こします。
—
3. 実践:GCP CLI (gcloud) によるファイアウォール設定と検証
理屈はこれくらいにして、実際に手を動かしてみましょう。
ここでは、特定のWeb APIサーバー(TCPポート 443)に対して、特定の社内IPレンジからのみアクセスを許可し、それ以外を拒否する堅牢なイングレスルールを gcloud コマンドで構築します。
設定のハンズオン(gcloud CLI)
以下のコマンドを実行して、優先度を緻密にコントロールしたファイアウォールルールを作成します。
# 1. 社内からのHTTPSアクセスを最優先(Priority: 1000)で許可する
gcloud compute firewall-rules create allow-corporate-https-ingress \
--network=production-vpc \
--direction=INGRESS \
--priority=1000 \
--action=ALLOW \
--rules=tcp:443 \
--source-ranges=203.0.113.0/24 \
--target-tags=web-api-server \
--description="Allow HTTPS traffic from corporate network to API servers"
# 2. その他のすべての外部からのトラッキングされていないアクセスを明示的にブロックする(Priority: 1500)
# ※暗黙的拒否(65535)の前に、監査ログを残しやすいように明示的なDenyルールを置くベストプラクティス
gcloud compute firewall-rules create deny-all-other-ingress \
--network=production-vpc \
--direction=INGRESS \
--priority=1500 \
--action=DENY \
--rules=all \
--source-ranges=0.0.0.0/0 \
--target-tags=web-api-server \
--description="Explicitly deny all other ingress traffic not matching higher priorities"
パラメーターのポイント
--target-tags=web-api-server: このタグが付与されたVMインスタンスにのみルールが適用されます。ネットワーク全体に無駄な負荷をかけないための必須プラクティスです。--rules=tcp:443: プロトコルとポートを指定します。tcpのほかにudpやicmpも指定可能です。
—
4. デバッグと疎通確認:パケットの生死をどう見極めるか?
「設定は完璧なはずなのに、なぜかAPIクライアントからタイムアウトエラーが返ってくる……」
そんな現場の絶望的な状況で、SREが取るべき現実的なデバッグ手順を伝授します。
ステップ1: curlとPythonによるレイヤー7/4の切り分け
まずは、クライアント側からパケットが実際にどこまで到達しているかをスクリプト等で確認します。Pythonの urllib や requests、あるいはシンプルな curl を使います。
# 疎通確認用Pythonスクリプト (api_ping.py)
import urllib.request
import urllib.error
target_url = "https://<API_SERVER_EXTERNAL_IP>/healthz"
try:
# タイムアウトを3秒に設定し、接続の成否を確認
req = urllib.request.Request(target_url, headers={"User-Agent": "SRE-Debug-Client"})
with urllib.request.urlopen(req, timeout=3) as response:
print(f"SUCCESS: Status Code -> {response.status}")
except urllib.error.HTTPError as e:
# サーバー側まで到達し、HTTPステータスが返ってきた場合(ファイアウォールは通過している)
print(f"HTTP ERROR: {e.code} - ファイアウォールは通過しています。アプリ層の確認が必要です。")
except urllib.error.URLError as e:
# ネットワークレベルで弾かれている、またはタイムアウトした場合
print(f"NETWORK ERROR: {e.reason} - ファイアウォールでブロックされているか、ルーティングの異常です。")
except Exception as e:
print(f"UNEXPECTED ERROR: {e}")
ステップ2: ファイアウォールルールのログ(Firewall Rules Logging)の活用
GCPでは、ファイアウォールルールのヒット状況をCloud Loggingに記録する機能があります。もし原因不明のドロップが発生しているなら、該当するルールでログを有効化しましょう。
# 既存のルールでログ記録を有効化するコマンド
gcloud compute firewall-rules update allow-corporate-https-ingress \
--enable-logging
ログが有効化されると、Google Cloud Consoleの「ログエクスプローラ」で以下のようなクエリを叩くことで、どのパケットがどのルールにマッチして許可/拒否されたかをリアルタイムで追跡できます。
resource.type="gce_subnetwork"
logName="projects/<YOUR_PROJECT_ID>/logs/compute.googleapis.com%2Ffirewall"
jsonPayload.connection.src_ip="203.0.113.50"
これで、パケットがどのプライオリティの防壁で弾き返されたのかが一目瞭然になります。
—
まとめ
GCPのVPCファイアウォールルールは、クラウドネットワークの安全性を保つための最初の、そして最も強力な砦です。
- 優先度(Priority)は小さい数字ほど強く、最初にマッチしたルールで評価が終了する。
- 暗黙のルール(Ingressは拒否、Egressは許可)の存在を常に念頭に置く。
- ステートフルな挙動を理解し、往復のパケットフローを意識して設計する。
この3点を押さえておけば、複雑なマイクロサービスアーキテクチャやマルチVPC環境であっても、ネットワーク起因の障害に怯えることはもうありません。現場のインフラを、ご自身の確かな技術で守り抜きましょう!
コメント