VM インスタンスへの安全な接続

このドキュメントでは、ゲスト属性を有効にしてホストキーを保存する、公共のインターネットから VM へのアクセスを防止するなど、Compute Engine 仮想マシン(VM)インスタンスに安全に接続するためのベスト プラクティスについて説明します。

始める前に

ゲスト属性を有効にしてホストキーを保存する

ホストキーとは、特定のホストまたはマシンを識別する鍵ペアのことです。ホストキーは、リモートホストに接続する際に、目的のマシンに接続していることを確認するために使用されます。

gcloud compute ssh を使用して Linux VM に接続している場合は、ホストキーをゲスト属性として保存することでセキュリティのレイヤを追加できます。

SSH ホストキーをゲスト属性として保存すると、中間者(MITM)攻撃などの脆弱性から保護できるため、接続のセキュリティが向上します。ゲスト属性が有効になっている場合、VM イの初回起動時に Compute Engine は生成されたホストキーをゲスト属性として保存します。その後、Compute Engine は保存されているホストキーを使用して、VM への以降の接続をすべて検証します。

ホストキーは、次の公開オペレーティング システム イメージのゲスト属性として保存できます。

  • Debian
  • Ubuntu
  • Red Hat Enterprise Linux(RHEL)
  • CentOS
  • SUSE Linux Enterprise Server(SLES)

ゲスト属性にホストキーを書き込むには、VM を初めて起動する前にゲスト属性を有効にする必要があります。VM の作成時に選択した VM またはプロジェクト全体でゲスト属性を有効にできます。

プロジェクトまたは VM でゲスト属性を有効にすると、ゲスト OS エージェントはホストキーをゲスト属性として自動的に公開します。プレーン SSH クライアントの代わりに gcloud compute ssh を使用する場合、gcloud ツールが次回接続時に属性を自動的に読み取り、known_hosts ファイルを更新します。

ホストキーをゲスト属性として保存するには、次の手順を行います。

  1. VM を初めて起動する前に、VM の作成時に選択した VM またはプロジェクト全体でゲスト属性を有効にします

  2. gcloud compute ssh を使用して VM に接続します。

    1. gcloud コマンドライン ツールの最新バージョンがあることを確認します。

      gcloud components update
      
    2. VM に接続します。

      gcloud compute ssh --project=PROJECT_ID \
       --zone=ZONE \
       VM_NAME
      

      次のように置き換えます。

      • PROJECT_ID: VM が含まれているプロジェクトの ID
      • ZONE: VM が存在するゾーンの名前
      • VM_NAME: VM の名前

      gcloud コマンドライン ツールにデフォルトのプロパティを設定した場合は、このコマンドから --project フラグと --zone フラグを省略できます。例:

      gcloud compute ssh VM_NAME
      
    3. 起動メッセージを確認します。たとえば、Debian オペレーティング システムでは次のメッセージが表示される場合があります。

      Writing 3 keys to YOUR_HOME_DIRECTORY/.ssh/google_compute_known_hosts
      Linux host-key-2 4.9.0-9-amd64 #1 SMP Debian 4.9.168-1+deb9u3 (2019-06-16) x86_64
      

ホストキーがこの VM のゲスト属性として保存されていることを確認するには、ホストキーの値を調べて、SSH 認証鍵が VM のゲスト属性に書き込まれていることを検証します(オプション 1)。または、シリアルポートを調べて、ホストキーが存在するかを確認します(オプション 2)。

オプション 1: ホストキーの値を確認する

gcloud コマンドライン ツールを使用して、SSH 認証鍵がゲスト属性に書き込まれていることを確認できます。

gcloud compute instances get-guest-attributes VM_NAME \
  --query-path="hostkeys/" \
  --zone=ZONE

次のように置き換えます。

  • VM_NAME: VM の名前
  • ZONE: VM が存在するゾーンの名前

出力は次のようになります。

NAMESPACE  KEY                  VALUE
hostkeys   ecdsa-sha2-nistp256  AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBBJAGpTm
                                V3mFxBTHK1NIu9a7kVQWaHsZVaFUsqF8cLxQRQ+N96/Djiiuz1tucHQ8vBTJI=
hostkeys   ssh-ed25519          AAAAC3NzaC1lZDI1NTE5AAAAIM/WYBn3jIEW5t3BZumx0X/Htm61J6S9FcU8L
hostkeys   ssh-rsa              AAAAB3NzaC1yc2EAAAADAQABAAABAQDU3jReR/MoSttlWYfauW6qEqS2dhe5
                                Zdd3guYk2H7ZyxblNuP56nOl/IMuniVmsFa9v8W6MExViu6G5Cy4iIesot09
                                1hsgkG0U7sbWrXM10PQ8pnpI3B5arplCiEMhRtXy64rlW3Nx156bLdcxv5l+
                                7Unu4IviKlY43uqqwSyTv+V8q4ThpQ9dNbk1Gg838+KzazljzHahtbIaE1rm
                                I0L1lUqKiKLSLKuBgrI2Y/WSuqvqGEz+bMH7Ri4ht+7sAwykph6FbOgKqoBI
                                hVWBo38/Na/gEuvtmgULUwK+xy9zWg9k8k/Qtihc6El9GD9y

オプション 2: シリアルポートを確認する

  1. シリアルポート出力を表示します。
  2. [シリアルポート 1] を選択します。
  3. 次のメッセージを検索します。

    INFO Wrote ssh-rsa host key to guest attributes

    サポートされているオペレーティング システムをイメージで使用しているにもかかわらず、VM の初回起動前にゲスト属性の設定が有効になっていない場合、次のメッセージが表示される場合があります。

    Unable to write ssh-rsa host key to guest attributes

    このメッセージは、ホストキーが VM のゲスト属性として保存されていないことを示しています。作成する予定の追加の VM のホストキーを保存する場合は、VM の初回の起動前にゲスト属性を有効にします。

公共のインターネットから VM へのアクセスを防止する

Compute Engine でプロジェクトを開発する場合、公共のインターネットから VM に到達しないようにするには、次のようなさまざまなシナリオがあります。

  • ウェブサービスがまだ開発中で、機能が不完全であるか、まだ HTTPS を使うように構成されていないために、外部ユーザーに公開する準備が整っていない。
  • VM は、プロジェクト内の他の VM によってのみ消費されるように設計されたサービスを提供している可能性がある。
  • 企業のオフィスやデータセンターなど、専用の相互接続オプションを通じてのみ、VM に到達できる必要がある。

サービスが意図的にインターネットに接続されている場合でも、機密情報を守るため、サービスとの通信を対象のユーザー グループに制限し、SSH や HTTPS などの安全なチャネルを通じて行うことが重要です。

この記事では、外部 IP アドレスを持つ VM外部 IP アドレスを持たない VM と安全に通信するための方法をいくつか紹介します。

外部 IP アドレスを持つマシン上のサービスの保護

VM にパブリック IP アドレスがある場合、公開を意図したサービスとトラフィックのみに到達可能であり、公開されているサービスで転送中の機密情報が保護されることが重要です。このドキュメントで説明するように、外部 IP アドレスを持つ VM 上のサービスを保護するには、ファイアウォールHTTPS と SSLSSH 経由のポート転送SSH 経由の SOCKS プロキシなど、いくつかの方法があります。

ファイアウォール

まず行うべき防御は、ファイアウォールを使って、VM に到達できる人を制限することです。ファイアウォール ルールを作成することで、ネットワークやターゲット マシンの特定のポートセットへのすべてのトラフィックを、特定のソース IP アドレスに制限できます。

ファイアウォールはスタンドアロン ソリューションではありません。トラフィックを特定のソース IP に制限しても、ログイン認証情報、リソースやファイルを作成または破棄するコマンド、ログなどの機密情報は保護されません。一般公開されたマシンで、外部 IP を使用する Compute Engine VM などのウェブサービスを実行する場合は、適切なセキュリティを確保するために、ホストとデプロイされた VM の間の通信をすべて暗号化する必要があります。

また、ファイアウォールは常に適切なソリューションであるとは限りません。たとえば、ローミング ラップトップなど、静的な IP アドレスを持たない開発環境では、ファイアウォールは理想的ではありません。

HTTPS と SSL

本番環境用のウェブシステムでは、HTTPS/SSL を構成します。HTTPS/SSL を構成するには、HTTPS を終端する VM をセットアップするか、HTTPS 負荷分散を構成します。HTTPS/SSL により当初の複雑さが増え、以下の作業を行う必要があります。

  • ドメイン名を登録します。
  • 認証局から SSL 証明書を取得します。
  • 証明書を HTTPS ロードバランサとその接続された VM に登録するか、SSL 終端するウェブサーバーやプロキシを、1 つ以上の Compute Engine VM 上で構成します。

SSH 上のポート転送

gcloud コマンドライン ツールを使って特定のローカルポートでサーバーを起動します。これにより、SSH 接続を介してすべてのトラフィックをリモートホストに転送できます。

まず、安全な接続を確立する必要があるサービスを提供している VM とポートをメモします。次に、以下のコマンドを実行します。

gcloud compute ssh VM_NAME \
    --project PROJECT_ID \
    --zone ZONE \
    -- -NL LOCAL_PORT:localhost:REMOTE_PORT

次のように置き換えます。

  • VM_NAME は、接続する VM の名前です。
  • PROJECT_ID は、ユーザーの Google Cloud プロジェクト ID です。
  • ZONE: VM が実行されているゾーン(us-central1-a など)。
  • LOCAL_PORT: リッスンするローカルポート(2222 など)。
  • REMOTE_PORT: 接続しているリモートポート(8888 など)。

たとえば、ローカルポートを「2222」、リモートポートを「8888」を指定して、ブラウザで http://localhost:2222/ を開くと、HTTP 接続では、リモートホストに作成した SSH トンネルを使用して、SSH で指定の VM に接続します。HTTP で接続後、暗号化された安全な SSH 接続により同じマシンのポート 8888 に接続します。

gcloud コマンドは、SSH セッションがアクティブである間に SSH 接続を作成および維持します。SSH セッションを終了するとすぐに、http://VM_NAME:LOCAL_PORT を使用したポート転送は終了します。

複数のポート転送ルールを作成する場合は、フラグを繰り返すことで 1 つのコマンドライン上で複数のルールを指定できます。

gcloud compute ssh VM_NAME \
    --project PROJECT_ID \
    --zone ZONE \
    -- -NL LOCAL_PORT:localhost:REMOTE_PORT \
    -- -NL LOCAL_PORT:localhost:REMOTE_PORT

また、新たな gcloud コマンドを何度か実行して、個別のトンネルを作成することもできます。既存の接続にポート転送を追加または削除するには、その接続を終了して初めから再確立する必要があることに注意してください。

SSH 上の SOCKS プロキシ

クラウド環境にある複数のホストに接続する場合、ネットワークから直接検索するようにブラウザを変更するのが最も簡単な方法です。このアプローチでは、各ホストの IP アドレスを検索したり、各サービスのポートをオープンしたり、各ホスト / ポートペアについて SSH トンネルを作成する代わりに、短いホスト名を使用できます。

ここで使うアプローチは以下のとおりです。

  1. ネットワーク上のいずれかのホストへの単一の SSH トンネルをセットアップし、そのホスト上で SOCKS プロキシを作成します。
  2. その SOCKS プロキシホストを使用してすべての検索を行うようにブラウザの構成を変更します。

すべてのトラフィックがそのホストを使用してトンネリングされるため、ウェブを閲覧するときに、そのブラウザや特定のプロファイルを使用しないでください。この帯域幅はクラウド サービス専用にする必要があります。一般的に、別のブラウザ プロファイルを使用し、必要に応じて切り替えることをおすすめします。

SOCKS プロキシの起動

SOCKS プロキシを起動するには、次のコマンドを実行します。

gcloud compute ssh VM_NAME \
    --project PROJECT_ID \
    --zone ZONE
    --ssh-flag="-D" \
    --ssh-flag="LOCAL_PORT" \
    --ssh-flag="-N"

次のように置き換えます。

  • VM_NAME: 接続先の VM の名前。
  • PROJECT_ID: Google Cloud プロジェクト ID
  • ZONE: VM が実行されているゾーン(us-central1-a など)。
  • LOCAL_PORT: リッスンするローカルポート(1080 など)。

ここでは、リモートポートを指定する必要がないことに注意してください。SOCKS プロキシは、特定のリモートポートにバインドしないため、SOCKS プロキシを使用して行ったすべての接続は、接続先のホストとの相対で解決されます。

SOCKS プロキシを使用すると、VM の短縮名を使用して、プロキシ VM と Compute Engine ネットワークを共有する任意の VM に接続できます。さらに、特定の VM 上の任意のポートに接続できます。

このアプローチは、単純なポート転送による手法よりもはるかに柔軟ですが、プロキシを使用するようにウェブブラウザの設定を変更する必要があります。

次に、プロキシを使用するように Chrome または Firefox を構成します。

Chrome

Chrome はシステム全体のプロキシ設定をデフォルトで使用するため、コマンドライン フラグを使って異なるプロキシを指定する必要があります。デフォルトで Chrome を起動すると、すでに実行されているプロファイルの VM が作成されます。Chrome を複数のコピーで同時に実行できるようにするには、一方はプロキシを使用し、それ以外はプロキシを使用しないため、新しいプロファイルを必要とします。

新しいプロファイルを使って Chrome を起動します。存在しない場合は新しいプロファイルが自動的に作成されます。

Linux:

/usr/bin/google-chrome \
    --user-data-dir="$HOME/chrome-proxy-profile" \
    --proxy-server="socks5://localhost:1080"

macOS:

"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
    --user-data-dir="$HOME/chrome-proxy-profile" \
    --proxy-server="socks5://localhost:1080"

Windows:

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" ^
    --user-data-dir="%USERPROFILE%\chrome-proxy-profile" ^
    --proxy-server="socks5://localhost:1080"

localhost のポートは、以前 gcloud コマンドで使用した値を設定します(この例では 1080)。

Firefox

これらの設定を変更する前に、新しい Firefox プロファイルを作成することをおすすめします。新しいプロファイルを作成せずにホストがプロキシとして使われると、すべての Firefox VM に影響し、それは多くの場合望ましい動作ではありません。

別のプロファイルを使って Firefox を実行した後、SOCKS プロキシを設定できます。

  1. [オプション] を開きます。
  2. [詳細設定] > [ネットワーク] > [設定] を順にクリックし、[接続設定] ダイアログを開きます。
  3. オプション [手動でプロキシを設定する] を選択します。
    1. [SOCKS ホスト] セクションで、ホストとして「localhost」と入力し、以前に gcloud コマンドを実行したときに選択したポートを入力します。
    2. [SOCKS v5] を選択します。
    3. [リモート DNS] をチェックボックスをオンにします。
    4. 他のエントリはすべて空白のままにします。
  4. [OK] をクリックし、[設定] ダイアログ ボックスを閉じます。

外部 IP アドレスを持たない VM への接続

VM に外部 IP アドレス(HTTPS および SSL プロキシ ロードバランサ用のバックエンドである VM など)がない場合、そのインスタンスには、ネットワーク上の他の VM、Identity-Aware Proxy の TCP 転送機能、またはマネージド VPN ゲートウェイの使用によってのみアクセスできます。ネットワーク内の VM を、受信接続用の信頼できるリレー(踏み台インスタンス)としてプロビジョニングできます。さらに、下り(外向き)ネットワーク用のクラウド NAT を構成することも、外部 IP アドレスを持たない VM の維持やトラブルシューティングのためにインタラクティブ シリアル コンソールを構成することもできます。

踏み台インスタンス

次の図に示すように、踏み台インスタンスは、プライベート ネットワーク インスタンスを含むネットワークへの外部に面するエントリ ポイントを提供します。

踏み台インスタンスのアーキテクチャは、プライベート インスタンスのネットワークへの外部に面するエントリ ポイントとして機能します。

このホストは、要塞化や監査のための単一の場所を提供します。また、SSH 通信を有効または無効にするために開始および停止できます。踏み台インスタンスを使用すると、外部 IP アドレスがない VM に接続できます。このアプローチでは、開発環境に接続するだけでなく、追加のファイアウォール ルールを構成しないで外部アプリケーションのデータベース インスタンスを管理できます。

踏み台インスタンスの完全な強化は、本ドキュメントの範囲外ですが、実施する最初のステップには以下のものが挙げられます。

  • 要塞と通信できるソース IP の CIDR 範囲を制限します。
  • 踏み台インスタンスからのみプライベート VM への SSH トラフィックを許可するように、ファイアウォール ルールを構成します。

デフォルトでは、VM 上の SSH は、認証用に秘密鍵を使用するように構成されます。踏み台インスタンスを使用する場合、まず踏み台インスタンスにログインし、次にターゲット プライベート VM にログインします。このように、踏み台インスタンスが「ジャンプ サーバー」と呼ばれる理由である 2 段階ログインがあるため、ターゲット マシンにアクセスする方法として、ターゲット マシンの秘密鍵を踏み台インスタンスに保存する代わりに ssh 転送を使用する必要があります。これは、踏み台インスタンスとターゲット VM に同じ鍵のペアを使用する場合でも必要です。踏み台インスタンスは、鍵ペアの公開鍵にしか直接アクセスできないためです。

踏み台インスタンスを使用して Google Cloud ネットワーク上の他の VM に接続する方法については、踏み台インスタンスを介した接続をご覧ください。

ssh 転送などの方法で外部 IP アドレスを持たない VM に接続する方法については、外部 IP アドレスを持たない VM への接続をご覧ください。

TCP 転送での IAP

SSH と IAP の TCP 転送機能を使用すると、SSH 接続が HTTPS にラップされます。IAP の TCP 転送機能は、それをリモート VM に送信します。

IAP を使用してリモート VM に接続する方法については、IAP を TCP 転送に使用するをご覧ください。

VPN

Cloud VPN では、既存のネットワークを IPsec 経由で Google Cloud ネットワークに接続し、VPN ゲートウェイ デバイスにアクセスできます。これにより、各自の構内から Compute Engine VM のプライベート IP インターフェースへの、トラフィックの直接のルーティングが可能になります。公開リンク経由で Google に転送される途中のトラフィックは暗号化されます。

Compute Engine で VPN を使用するためのセットアップ、構成、使用方法については、Cloud VPN のドキュメントをご覧ください。

VM の外部 IP アドレスではなく、既存の VPN を介して Google Cloud ネットワーク上の VM に接続する方法については、外部 IP アドレスを持たない VM への接続をご覧ください。

Cloud NAT を使用した下り(外向き)トラフィック

VM に外部 IP アドレスが割り当てられていない場合、VM は他の Google Cloud サービスを含む、外部サービスに直接接続できません。これらの VM が公共のインターネット上のサービスに到達できるようにするには、ネットワーク上の VM の代わりにトラフィックをルーティングできる Cloud NAT を設定して構成します。単一の VM の可用性が高く、複数の VM の高スループットのトラフィックをサポートすると考えてはいけません。

インタラクティブ シリアル コンソール アクセス

VM に外部 IP アドレスがなくても、トラブルシューティングやメンテナンスを目的として VM を操作することが必要な場合があります。前述のように、踏み台インスタンスをセットアップすることは 1 つの方法ですが、ニーズに見合うよりも多くのセットアップが必要になる可能性があります。外部 IP アドレスを持たない VM のトラブルシューティングを行う場合は、シリアル コンソールでのインタラクティブ アクセスの有効化を検討してください。これにより、SSH を使って VM のシリアル コンソールを操作し、シリアル コンソールに対してコマンドを実行できます。

詳しくは、シリアル コンソールとのやり取りをご覧ください。

HTTPS および SSL プロキシ ロードバランサ

HTTPS および SSL プロキシ ロードバランサのバックエンドである VM には、ロードバランサを介してアクセスするための外部 IP アドレスは不要です。これらのリソースに直接アクセスするには、外部 IP アドレスを持たない VM への接続に記載されている方法を使用する必要があります。

詳細については、それらのロードバランサに関するロードバランサのドキュメントをご覧ください。