Compute Engine イメージを最初からビルドする

Google Compute Engine はさまざまなオペレーティング システムを実行できるため、任意のオペレーティング システムでイメージを最初からビルドし、Google Compute Engine の仮想マシン上で使用することができます。ただし、Google Compute Engine は固有の環境であり、すべてのイメージが最適に実行されるようにするには一定の要件があります。ここでは、公開イメージではなく各自のイメージを使用するユーザーを対象とした高度なトピックとしてこの要件について説明します。

ここで示す情報と推奨事項は一般的な内容であり、イメージをビルドする手順はオペレーティング システムによって異なる場合があります。具体的な手順については、ご使用のオペレーティング システムのドキュメントをご覧ください。イメージのビルドは高度なタスクであるため、イメージを最初からビルドするのは、特に新しいイメージを必要とするユーザーのみとすることをおすすめします。

基本的なオペレーティング システムの設定

このセクションでは、インスタンス内で起動できる基本的なイメージを設定する方法について説明します。これは一般的な推奨事項であり、オペレーティング システムによって異なる場合があります。具体的な手順については、オペレーティング システムのドキュメントをご覧ください。

推奨

  • タイムゾーンを UTC に設定します。

    sudo ln -sf /usr/share/zoneinfo/UTC /etc/localtime
    
  • ntp.conf に Google NTP サーバーを使用して(server metadata.google.internal iburst)、他のすべての NTP サーバーを削除します。

  • 起動時にホスト名をメタデータ サーバーから設定するようにイメージを設定します。次の例のようにすると、インスタンスのホスト名をメタデータから取得できます。

    curl --silent --max-time 10 --connect-timeout 3 -H "Metadata-flavor:Google" \
      http://metadata.google.internal/computeMetadata/v1/instance/hostname
    
  • カーネル メッセージと syslog メッセージを /dev/ttyS0 に記録して、gcloud compute instances get-serial-port-output でデバッグできるようにします。 カーネル コマンドライン オプションに console=ttyS0,38400n8 を追加して、カーネル メッセージをコンソールに出力します。

省略可

  • FIPS モードを有効にします。
  • イメージをビルドしながらパッケージの更新を考慮して、最初の起動時にパッケージを更新するロジックを追加します。

カーネルの設定

下記のハードウェア マニフェストに準拠している場合は、任意の OS カーネルを Google Compute Engine 上でビルドして実行することができます。次のガイドラインは、独自のカーネル バイナリのビルドに役立ちます。

ハードウェア マニフェスト

カーネルでサポートする必要がある端末のリストを以下に示します。

  • PCI ブリッジ: Intel Corporation 82371AB/EB/MB PIIX4 ACPI(rev 03)
  • ISA ブリッジ: Intel 82371AB/EB/MB PIIX4 ISA(rev 03)
  • イーサネット コントローラ:
    • Virtio-Net イーサネット アダプタ
    • ベンダー = 0x1AF4(Qumranet / Red Hat)、端末 ID = 0x1000、サブシステム ID 0x1
    • チェックサム オフロードをサポート
    • TSO v4 をサポート
    • UFO をサポート
    • GRO v4 をサポート
  • SCSI ストレージ コントローラ:
    • Virtio-SCSI ストレージ コントローラ
    • ベンダー = 0x1AF4(Qumranet / Red Hat)
    • 端末 ID = 0x1004、サブシステム ID 0x8
    • SCSI Primary Commands 4、SCSI Block Commands 3 をサポート
    • リクエスト キューを 1 つだけサポート
    • 永続ディスクで 4 KiB の物理セクターと 512 バイトの論理セクターを報告
    • ブロック デバイス(ディスク)のみをサポート
    • ホットプラグ / イベント機能ビットをサポート
  • シリアルポート:
    • 4 つの 16550A ポート
    • IRQ 4 で ttyS0
    • IRQ 3 で ttyS1
    • IRQ 6 で ttyS2
    • IRQ 7 で ttyS3

必須の Linux カーネル オプション

# to enable paravirtualization functionality.
CONFIG_KVM_GUEST=y

# to enable the paravirtualized clock (if applies to your kernel version).
CONFIG_KVM_CLOCK=y

# to enable paravirtualized PCI devices.
CONFIG_VIRTIO_PCI=y

# to enable access to paravirtualized disks.
CONFIG_SCSI_VIRTIO=y

# to enable access to the networking.
CONFIG_VIRTIO_NET=y

推奨される Linux カーネル オプション

# to enable high performance interrupt delivery (needed for Local SSD)
CONFIG_PCI_MSI=y

ネットワークの設定

高パフォーマンスのネットワーク機能を確保するには、以下の推奨設定を使用する必要があります。Google Compute Engine のネットワークについて詳しくは、ネットワークとファイアウォールに関するドキュメントをご覧ください。

強く推奨

  • ISC DHCP クライアントを使用します。 他のクライアントを使用することもできますが、テストされていません。
  • パフォーマンスを最大限に高めるために、MTU を 1460 に設定します。Google Compute Engine の DHCP サーバーは、このパラメータを、ほとんどのクライアントで考慮される interface-mtu オプションとして処理します。

推奨

  • IPv6 はサポートされていないため、無効にします。
  • インスタンスで MAC アドレスが記憶されないようにします。次に例を示します。

    rm -f /etc/udev/rules.d/70-persistent-net.rules
    

省略可

  • 送信トラフィックを制限する場合を除き、オペレーティング システムのファイアウォールを無効にします。
  • Google Compute Engine には受信トラフィック用のファイアウォールが用意されています。ファイアウォールについて詳しくは、ネットワークとファイアウォールをご覧ください。

パッケージのインストール

Google Compute Engine では、オペレーティング システムが円滑に実行されるようにするために、小規模なパッケージ セットをインストールする必要があります。

必要なパッケージ

  • Python 2.6~3.5
  • sshd

強く推奨

パッケージの設定時には、以下を必ず実行してください。

  • 自動更新を有効にする
  • すべてのパッケージを最新バージョンに更新する

省略可

Google Compute Engine イメージ パッケージ

Google は、Google Compute Engine で正しく動作するようにオペレーティング システムを設定するツールセットを提供しています。これらのツールをインストールし、更新するには、カスタム イメージに Google Cloud レポジトリを追加します。また、これらのツールのソースコードをダウンロードして自分でビルドすることもできます。

これらのスクリプトの中には、ご使用のディストリビューションで動作させるためにカスタマイズが必要になるものもあります。変更が必要な場合は、GitHub プロジェクトをフォークして、そのバージョンのプロジェクトに変更内容を保存することができます。このフォークにより、正規のスクリプトに影響を与えずにカスタマイズを行うことができ、今後改善する際に統合することもできます。パッチをお送りいただくこともできますが、サードパーティの投稿者契約を結ぶ必要があります。

SSH の設定

通常はインスタンスに SSH 経由でログインするため、安全な SSH の設定を使用してイメージを実行する必要があります。

推奨

  • root での SSH ログインを無効にします。
  • パスワード認証を無効にします。
  • ホストベースの認証を無効にします。
  • 厳密なホスト鍵チェックを有効にします。
  • ServerAliveInterval を使用して接続を開いたままにします。

SSH ホスト鍵の削除

このイメージから作成されたインスタンスが一意の SSH ホスト鍵を持つようにするには、イメージから SSH ホスト鍵を削除する必要があります。これにより、新しいインスタンスの初回起動時に ssh 起動スクリプトで鍵が生成されるようになります。鍵は次のように削除します。

rm /etc/ssh/ssh_host_key
rm /etc/ssh/ssh_host_rsa_key*
rm /etc/ssh/ssh_host_dsa_key*
rm /etc/ssh/ssh_host_ecdsa_key*

独自の設定ファイルを定義する際に、例として示す次の SSH 設定ファイルをベースにすると便利です。/etc/ssh/ssh_config ファイルの場合は、以下の設定から開始します。

Host *
Protocol 2
ForwardAgent no
ForwardX11 no
HostbasedAuthentication no
StrictHostKeyChecking no
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc
Tunnel no

# Google Compute Engine times out connections after 10 minutes of inactivity.
# Keep alive ssh connections by sending a packet every 7 minutes.
ServerAliveInterval 420

/etc/ssh/sshd_config ファイルの場合は、以下の設定から開始します。

# Disable PasswordAuthentication as ssh keys are more secure.
PasswordAuthentication no

# Disable root login, using sudo provides better auditing.
PermitRootLogin no

PermitTunnel no
AllowTcpForwarding yes
X11Forwarding no

# Compute times out connections after 10 minutes of inactivity.  Keep alive
# ssh connections by sending a packet every 7 minutes.
ClientAliveInterval 420

# Restrict sshd to just IPv4 for now as sshd gets confused for things
# like X11 forwarding.

セキュリティに関する推奨事項

常に安全なオペレーティング システム環境を提供する必要がありますが、安全な環境とアクセス可能な環境を両立することは困難です。 下記の予防策の多くは必須ではありませんが、実施することを強くおすすめします。安全でない仮想マシンは攻撃を受けやすくなり、消費するリソースが高コストになる可能性があります。

OS のセキュリティのベスト プラクティス

  • デフォルトでインストールされるソフトウェアの量を最小限に抑えます(たとえば、OS の最小インストールを実行します)。
  • 自動更新を有効にします。
  • デフォルトでは、SSH、DHCP、NTPD 以外のすべてのネットワーク サービスが無効になっています。 Postfix などのメールサーバーがローカルホストからの接続のみを受け入れている場合は、そのメールサーバーを実行することができます。
  • sshd 以外の外部リスニング ポートは許可しないでください。
  • SSH ブルート フォース ログイン試行を防ぐために、denyhosts パッケージをインストールします。
  • デフォルトのインストールからユーザー以外の不要なアカウントをすべて削除します。
  • /etc/passwd で、ユーザー以外のすべてのアカウントのシェルを /sbin/nologin または /usr/sbin/nologin に設定します(nologin がインストールされている場所に応じて設定します)。
  • /etc/shadow で、パスワードにソルト付き SHA512 を使用するように OS を設定します。
  • パスワードの安全度を高めるために pam_cracklib を設定します。
  • ログインに 3 回失敗したアカウントを 5 分間ロックするように pam_tally を設定します。
  • /etc/shadow で、root アカウントがデフォルトでロックされるように設定します。root アカウントをロックするには、次のコマンドを実行します。

    usermod -L root
    
  • /etc/ssh/sshd_config で次の行を追加して root を拒否します。

    PermitRootLogin no
    
  • デフォルトで実行されているすべてのネットワーク接続サービス用に AppArmor プロファイルまたは SELinux プロファイルを作成します。

  • 可能な場合はファイル システム機能を使用して、S*ID ビットの必要性をなくし、より詳細に制御できるようにします。
  • ネットワーク接続ソフトウェアのコンパイル時に、コンパイラとランタイムのエクスプロイト対策を有効にします。例として、GNU Compiler Collection(GCC)で提供される対策の一部と、それらの対策を有効にする方法を以下に示します。
    • スタック スマッシュの防止: -fstack-protector で有効にします。 デフォルトでは、このオプションは 8 バイトを超えるスタック割り当てバッファを持つ関数を保護します。4 バイト以上のバッファを持つ関数を対象にして保護を強化するには、--param=ssp-buffer-size=4 を追加します。
    • アドレス空間配置のランダム化(ASLR): -fPIC -pie で位置に依存しない実行可能ファイルをビルドして有効にします。
    • glibc の保護: この保護は -D_FORTIFY_SOURCE=2 で有効にします。
    • グローバル オフセット テーブル(GOT)の保護: このランタイム ローダー機能は -Wl,-z,relro,-z,now で有効にします。
    • フォーマット文字列が欠落している場合のコンパイル時エラー: -Wformat -Wformat-security -Werror=format-security
  • カーネル モジュールの読み込みと読み込み解除を許可する CAP_SYS_MODULE を無効にします。Linux カーネルではこの機能のサポートは終了しています。この機能を無効にするには、次のコマンドを実行します。

    echo 1 > /proc/sys/kernel/modules_disabled
    
  • カーネル シンボル テーブルを削除します。

    sudo rm /boot/System.map
    

カーネルのビルド オプション

次のオプションは、独自のカーネルをビルドする際に Google Compute Engine で推奨されるセキュリティ設定です。

強く推奨

カーネルのビルド時には次のオプションを設定することを強くおすすめします。

  • CONFIG_STRICT_DEVMEM=y
    • PCI 空間、BIOS コード、データ領域へのアクセスのみを許可するように /dev/mem を制限します。
  • CONFIG_DEVKMEM=n
    • /dev/kmem のサポートを無効にします。
    • カーネルメモリへのアクセスをブロックします。
  • CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
    • ユーザー空間の割り当てから保護する低仮想メモリを設定します。
  • CONFIG_DEBUG_RODATA=y
    • ページテーブルでカーネルの読み取り専用データを書き込み禁止としてマークし、このような const データへの誤った(正しくない)書き込みをキャッチします。カーネルコードの一部が 2 MB の TLB の対象にならなくなるため、このオプションはパフォーマンスにわずかに影響する可能性があります。
  • CONFIG_DEBUG_SET_MODULE_RONX=y
    • 読み込み可能なカーネル モジュールのテキストと読み取り専用データに対する意図しない変更をキャッチします。このオプションはモジュール データの実行も防ぎます。
  • CONFIG_CC_STACKPROTECTOR=y
    • -fstack-protector GCC 機能を有効にします。この機能では、戻りアドレスの直前のスタック上の重要な関数の先頭にカナリア値が配置され、実際に返される直前の値が検証されます。また、スタックベースのバッファ オーバーフロー(この戻りアドレスを上書きする必要がある)によってカナリアが上書きされると検出され、攻撃はカーネル パニックを使用して無効化されます。
  • CONFIG_COMPAT_VDSO=n
    • ASLR を強化するために、VDSO が予測可能なアドレスに配置されないようにします。この機能を有効にした場合は、VDSO が予測可能な古いスタイルのアドレスにマッピングされ、ジャンプ先のエクスプロイト コードの予測可能な場所が提供されます。 十分新しいバージョンの glibc(2.3.3 以降)を実行している場合はここで N を指定して、高度な VDSO マッピングを排除し、ランダム化された VDSO のみを使用します。
  • CONFIG_COMPAT_BRK=n
    • ヒープのランダム化は無効にしないでください。
  • CONFIG_X86_PAE=y
    • NX のサポートには PAE が必要であるため、32 ビットのカーネルの場合はこのオプションを設定します。 また、これにより、オーバーコミット以外を目的としたより大きなスワップ空間のサポートが可能になります。
  • CONFIG_SYN_COOKIES=y
    • SYN フラッド対策を提供します。

推奨

  • CONFIG_SECURITY_YAMA=y
    • これにより、通常の Linux 任意アクセス制御の範囲を超えるシステム全体の追加セキュリティ設定で DAC のサポートを拡張する Yama が選択されます。 現在、この設定は ptrace の範囲制限です。
  • CONFIG_SECURITY_YAMA_STACKED=y
    • Yama が利用可能な場合に、選択されたプライマリ LSM を使用して Yama が強制的にスタックされます。

カーネルのセキュリティ設定

カーネルのセキュリティを強化するには、カーネル設定ファイル /etc/sysctl.conf を使用すると便利です。このファイルの設定時には次の設定が推奨されます。

強く推奨

# enables syn flood protection
net.ipv4.tcp_syncookies = 1

# ignores source-routed packets
net.ipv4.conf.all.accept_source_route = 0

# ignores source-routed packets
net.ipv4.conf.default.accept_source_route = 0

# ignores ICMP redirects
net.ipv4.conf.all.accept_redirects = 0

# ignores ICMP redirects
net.ipv4.conf.default.accept_redirects = 0

# ignores ICMP redirects from non-GW hosts
net.ipv4.conf.all.secure_redirects = 1

# ignores ICMP redirects from non-GW hosts
net.ipv4.conf.default.secure_redirects = 1

# don't allow traffic between networks or act as a router
net.ipv4.ip_forward = 0

# don't allow traffic between networks or act as a router
net.ipv4.conf.all.send_redirects = 0

# don't allow traffic between networks or act as a router
net.ipv4.conf.default.send_redirects = 0

# reverse path filtering - IP spoofing protection
net.ipv4.conf.all.rp_filter = 1

# reverse path filtering - IP spoofing protection
net.ipv4.conf.default.rp_filter = 1

# ignores ICMP broadcasts to avoid participating in Smurf attacks
net.ipv4.icmp_echo_ignore_broadcasts = 1

# ignores bad ICMP errors
net.ipv4.icmp_ignore_bogus_error_responses = 1

# logs spoofed, source-routed, and redirect packets
net.ipv4.conf.all.log_martians = 1

# log spoofed, source-routed, and redirect packets
net.ipv4.conf.default.log_martians = 1

# implements RFC 1337 fix
net.ipv4.tcp_rfc1337 = 1

# randomizes addresses of mmap base, heap, stack and VDSO page
kernel.randomize_va_space = 2

推奨

# provides protection from ToCToU races
fs.protected_hardlinks=1

# provides protection from ToCToU races
fs.protected_symlinks=1

# makes locating kernel addresses more difficult
kernel.kptr_restrict=1

# set ptrace protections
kernel.yama.ptrace_scope=1

# set perf only available to root
kernel.perf_event_paranoid=2

イメージのパッケージ化

gcloud ツールまたは API を使用して、

ソースディスクから Compute Engine イメージを作成します

イメージを自分でパッケージ化するには、イメージ形式に関する次の要件を参考にしてください。

要件

アーカイブを Google Compute Engine に追加するには、次の要件を満たす必要があります。

  • アーカイブは、拡張子が .tar.gz の gzip 圧縮された有効な tarball である必要があります。
  • tar 形式は GNU または旧 GNU 形式である必要があります。
  • 起動イメージの場合もそれ以外のイメージの場合も、100 GB 以下の disk.raw ファイルが必要です。また、disk.raw ファイルのサイズは 1 GB 単位である必要があります。たとえば、ファイルは 10 GB または 11 GB になり、10.5 GB にはなりません。
  • disk.raw ファイルには MS-DOS(MBR)パーティション テーブルが必要です。

強く推奨

次の推奨事項では、イメージによって必要以上の容量が使用されないようにして、イメージの全体的なストレージ コストを削減します。

  • tarball をスパースとして作成します。
  • disk.raw をスパースとして作成します。

パーティション

イメージには、MS-DOS パーティション テーブルと互換性のあるプライマリとセカンダリの任意のパーティショニング スキームを用意できます。通常、Google が提供するイメージには次のパーティショニング スキームが用意されています。

  • MS-DOS パーティション テーブル
  • ext4 でフォーマットされた 1 つのプライマリ パーティション

Compute Engine へのイメージのアップロード

イメージの tarball をビルドしたら、そのイメージを Compute Engine プロジェクトに追加する前に、イメージを Google Cloud Storage バケットにアップロードする必要があります。

既存のイメージの tar ファイルからプロジェクトにカスタム イメージを追加するには、まずイメージを Google Cloud Storage に追加して Compute Engine プロジェクトにインポートする必要があります。イメージを Compute Engine に追加する方法は次のとおりです。

  1. tar ファイルを Google Cloud Storage にアップロードします。

    tar ファイルを Google Cloud Storage にアップロードするには、インスタンスにプリインストールされている gsutil コマンドライン ツールを使用します。

    1. gsutil を設定します。

      このインスタンスで gsutil を初めて使用する場合、かつサービス アカウントを使用して Google Cloud Storage と通信するようにインスタンスを設定していない場合は、gsutil config を実行して指示に従います。それ以外の場合は、この手順をスキップできます。

    2. バケットを作成します。

      バケットを作成する前に、バケットと命名のガイドラインを確認します。確認したら、次のコマンドを使用してバケットを作成します。

      $ gsutil mb gs://BUCKET_NAME
      

      Google Cloud Storage サービスを使用するには、まず Google Cloud Storage アカウントの課金を有効にする必要があります。Google Cloud Storage で使用量に対してどのように課金されるかについては、価格表をご覧ください。

    3. ファイルを新しいバケットにコピーします。

      $ gsutil cp /tmp/IMAGE_NAME.image.tar.gz gs://BUCKET_NAME
      

  2. 次に、RAW イメージをインポートする手順に従います。

トラブルシューティング

ビルド時にイメージに関する問題のトラブルシューティングを行うには、インスタンスのシリアル コンソールへのインタラクティブなアクセスを有効にして、そのコンソールに SSH クライアントから接続します。

詳しくは、シリアル コンソールの操作をご覧ください。

フィードバックを送信...