【テクニカル・上級編】 GCP Cloud NATの基本アーキテクチャとポートアロケーション方式 – クラウドインフラと仮想化ネットワーク実践ガイド

境界線の向こう側:GCP Cloud NATの深淵とパケットの流儀

クラウドインフラの設計において、我々SREが最も頭を悩ませるのが「外の世界」との通信だ。プライベートなVPC内に閉じ込められたインスタンスが、いかにしてセキュアに、かつ低レイテンシでインターネットの広大な海へとパケットを送り出すか。その鍵を握るのが GCP Cloud NAT である。

公式ドキュメントには「マネージドNATサービス」としか書かれていないが、その内部で何が起きているのか。今回は、ポート枯渇という悪夢を回避し、TCPスタックを極限までチューニングするための「現場の知見」を紐解いていこう。

—

1. Cloud NATのアーキテクチャ:エンドポイント独立型マッピングの真実

Cloud NATの設計思想を理解する上で欠かせないのが、Endpoint-Independent Mapping (EIM) という概念だ。

従来のNATゲートウェイ(iptablesで力技で組んだものなど)は、送信元ポートが固定されないことが多く、特定の外部サーバに対して同一セッションを維持するのが困難だった。しかし、GCPのCloud NATは、同一の内部IPとポートからの通信であれば、外部接続先がどこであろうと「同じマッピング」を再利用する。

これにより、クライアント側で発生しがちな「ポートの無駄遣い」を劇的に抑制できる。なぜなら、一度確立したマッピングはセッション継続中、あるいはタイムアウトまで維持されるため、同一宛先への再接続時にポート再割り当てという高コストな処理をスキップできるからだ。

ポート動的割り当ての最適化

デフォルトの min_ports_per_vm は 64 だが、大規模なマイクロサービスを運用している場合、これは致命的な不足を招く。特に、keep-alive を無効にしたHTTP/1.1のクライアントが大量の同時接続を張ると、一瞬で 502 Bad Gateway や接続タイムアウトの嵐に見舞われることになる。

# 推奨される設定例:ポート割り当てを動的に拡張する
gcloud compute routers nats update nat-config \
    --router=my-cloud-router \
    --region=asia-northeast1 \
    --min-ports-per-vm=256 \
    --enable-dynamic-port-allocation

—

2. トランスポート層の最適化とTCPバッファチューニング

Cloud NATを通過する通信において、ボトルネックになりやすいのが「TCPウィンドウサイズ」と「輻輳制御」だ。特にGCPのネットワークスタックは強力だが、VM側のカーネルパラメータが標準のままだと、その帯域を活かしきれない。

カーネルパラメータのチューニング例

sysctl.conf に以下の設定を投入し、高スループット環境でのバッファあふれを防ぐべきだ。

# /etc/sysctl.conf
# TCPの受信バッファを拡張し、RTTが大きな通信でもスループットを維持する
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

# タイムウェイト状態のソケットを再利用し、ポート枯渇を回避
net.ipv4.tcp_tw_reuse = 1

これにより、Cloud NATとの間で張られるコネクションの効率が向上し、結果としてパケットの廃棄(ドロップ)が減る。これは単なるチューニングではなく、TCPハンドシェイクの再送待ちを減らすための「生存戦略」である。

—

3. セキュリティとパフォーマンスのトレードオフ:TLSハンドシェイク

Cloud NATを使用する際、HTTPS通信のパフォーマンスを左右するのはTLSハンドシェイクのRTTだ。ここで重要になるのが HTTP/2 または HTTP/3 (QUIC) への移行である。

HTTP/2 を採用すれば、一つのコネクション内で複数のストリームを多重化できるため、Cloud NATのポート消費を劇的に抑えつつ、TCPの3ウェイハンドシェイクを繰り返すオーバーヘッドから解放される。

また、もし可能であれば、TLS 1.3 を強制すべきだ。1.3ではハンドシェイクが1往復で完了する(0-RTTデータも利用可能)。これは物理的な距離によるレイテンシを最小化し、Cloud NATの内部マッピングテーブルを効率的に活用するための最短経路となる。

—

4. 重大なネットワーク脆弱性の回避策

Cloud NATを利用する際、見落とされがちなのが「ソースIPの偽装」や「不適切なコネクション追跡」によるリスクだ。

1. IPフラグメンテーションへの対処: NAT越しに巨大なパケットを投げる際、フラグメンテーションが発生すると、多くのFWやNATはパケットを破棄する。MTUを適切に設定し、MSS Clamping を考慮に入れることが重要だ。
2. ログ分析: Cloud Logging で NAT のログを有効にし、connection_count を監視せよ。特定のVMが異常な数のポートを消費している場合、それはDoS攻撃の踏み台になっているか、コード上のコネクションリークである可能性が高い。

# 監視用スクリプトの断片(概念コード)
# Cloud Logging APIを叩き、NATのポート枯渇をアラートする
def check_nat_usage(project_id, router_name):
    query = f'resource.type="nat_gateway" AND resource.labels.router_name="{router_name}"'
    # 接続数や破棄されたパケット数を集計して異常値を検知
    # ...

—

結びに:エンジニアとしての矜持

Cloud NATは単なる「ゲートウェイ」ではない。内部ネットワークと外部インターネットを繋ぐ、高度に抽象化された「プロトコル変換の舞台」である。

我々インフラアーキテクトがやるべきことは、デフォルト値に安住することではなく、パケットがどのポートを通り、どのウィンドウサイズで呼吸しているかを想像し続けることだ。マニュアルを読み終えた後に残る「なぜ?」という疑問こそが、システムをより堅牢に、そして美しく進化させる原動力となる。

次は、Cloud NATのログから見えてくる「見えない攻撃」の検知手法について深掘りしていこう。ネットワークの深淵は、まだ入り口に立ったばかりだ。

コメント

タイトルとURLをコピーしました