第6章 接続と権限

目次

6.1. 認証
6.2. リモート接続の設定
6.3. VM ホストサーバ への接続

複数の VM ゲスト を受け持つ VM ホストサーバ が複数台存在するような環境では、 すぐに管理が行き詰まってしまいます。 libvirt には複数の VM ホストサーバ に対して 同時接続できるという機能があることから、これを利用してすべての VM ゲスト とそれらのグラフィカルコンソールを管理することができます。

権限のあるユーザだけがアクセスできるようにするため、 libvirt では各種の 接続タイプ (TLS, SSH, Unix ソケット, TCP) と認証メカニズム (socket, PolKit, SASL, Kerberos) が提供されています。

6.1. 認証

VM ゲスト を管理したり、それらのグラフィカルコンソールにアクセスしたりする 権利は、限られたユーザに対してのみ提供されるべきものです。これを実現するため、 VM ホストサーバ 側で下記のような認証方式を利用することができます:

  • パーミッションとグループ所有者を設定できる、 UNIX ソケットによるアクセス 制御。この方式は libvirtd 接続でのみ利用できます。

  • PolKit を利用した UNIX ソケットのアクセス制御。この方式はローカルの libvirtd 接続でのみ利用できます。

  • SASL (Simple Authentication and Security Layer) を利用した、ユーザ名と パスワードによる認証。この方式は libvirtd と VNC の両方で利用できます。 なお SASL での認証を行なう場合、サーバ側に実際のユーザアカウントを作成する 必要はありません。これは、ユーザ名とパスワードを独自のデータベース内に保存する ためです。なお、 SASL での認証接続は暗号化されます。

  • Kerberos による認証。この方式は libvirtd 接続でのみ利用できますが、 このマニュアルでは説明していません。詳しくは http://libvirt.org/auth.html#ACL_server_kerberos をお読みください。

  • パスワードのみの認証。この方式は VNC 接続でのみ利用できます。

[Important]libvirtd と VNC の認証について

VM ゲスト の管理機能にアクセスする機能とそれらのグラフィカルコンソールに アクセスする機能は、それぞれ別々に設定する必要があります。管理ツールへの アクセスを制限しても、それらの制限が VNC 接続に自動で反映されることは ありません

TLS/SSL 接続を利用して VM ゲスト へのリモートアクセスを行なう場合、各 クライアントのアクセス制御は、証明書の鍵ファイルの読み取り権限を特定の グループに付与して制限することによって、間接的に実現することができます。 詳しくは 6.2.2.5項 「アクセス制限 (セキュリティ面の考慮事項)」 をお読みください。

6.1.1. libvirtd の認証

libvirtd の認証は、 /etc/libvirt/libvirtd.conf で設定します。このファイルで設定した内容は、 Virtual Machine Manager や virsh など、すべての libvirt ツールに適用されます。

libvirt では 2 種類のソケットを提供しています。 1 つは監視用に使用する 読み込みのみのソケット、もう 1 つは管理用に使用する読み書き可能なソケット です。両方のソケットに対するアクセスは別々に設定します。既定では両方の ソケットは root.root が所有する設定になっています。 また、既定では読み書き可能なソケットに対するアクセス権は root だけに 制限 (0700) され、読み込みのみのソケットに対するアクセス権は 誰にでもできるように設定 (0777) されています。

下記では、読み書き可能なソケットに対してアクセス権を設定する手順を説明して います。読み込みのみのソケットに対しても同じ手順で設定できます。なお、すべての 手順は VM ホストサーバ 上で実施します。

[Note]openSUSE における既定の認可設定

openSUSE における既定の認証方法は、 UNIX ソケットを利用した アクセス制御です。この方法では root だけが認証されます。 VM ホストサーバ 内に存在する root 以外のユーザで libvirt ツールにアクセスすると 最初の 1 回だけ、 PolKit による root のパスワード認証が求められます。 パスワードが正しいことが確認されると、その時点でのセッションと今後の セッションでアクセスが許可されるようになっています。

それ以外にも、 libvirt を設定することで非特権ユーザに システム アクセスを許可するように設定することもできます。 詳しくは 6.3.1項 「非特権ユーザに対する システム アクセス」 をお読みください。

6.1.1.1. パーミッションとグループ所有者を利用した UNIX ソケット向けのアクセス制御

root 以外のアカウントに対してアクセスを許可するように設定する には、ソケットの所有者グループを変更することで実現することができます (下記の例では libvirt グループに設定する場合を示しています) 。この認可方法は、ローカル接続と SSH 接続に対して適用できます。

  1. まずソケットを所有させるグループが存在しない場合は、それを作成します:

    groupadd libvirt
    [Important]グループの存在について

    libvirtd を再起動するまでの間にグループを作成しなければなりません。 作成を行なっていないと、再起動が失敗します。

  2. アクセスを許可したいユーザをグループに追加します:

    usermod -A libvirt tux
  3. あとは設定ファイル /etc/libvirt/libvirtd.conf を下記のように変更します:

    unix_sock_group = "libvirt"1
           unix_sock_rw_perms = "0770"2
           auth_unix_rw = "none"3

    1

    所有者グループを libvirt に設定しています。

    2

    ソケットに対するパーミッションを設定しています (srwxrwx---) 。

    3

    その他の認証方法 (PolKit や SASL など) を無効化しています。 アクセスはソケットのパーミッションでのみ設定します。

  4. libvirtd を再起動します:

    rclibvirtd restart

6.1.1.2. PolKit を利用した UNIX ソケットによるローカルアクセス制御

PolKit を利用した UNIX ソケットのアクセス制御は、ローカル接続の場合の openSUSE における既定の制御方法です。そのため、 libvirt の設定 変更を行なう必要はありません。 PolKit による制御が働いている場合は、 既定では両方のソケットともパーミッションが 0777 に設定され、ソケットに対してアクセスするアプリケーションは PolKit に よる認証を受けなければならなくなります。

[Important]PolKit の認証はローカル接続に対してのみ動作します

PolKit はリモートの認証に対応していないため、 PolKit による認証は、 VM ホストサーバ 上のローカル接続に対してだけ使用することができます。

libvirt のソケットにアクセスする場合、 2 種類のポリシーが存在します:

  • org.libvirt.unix.monitor: 読み込み専用の ソケットに対するアクセス

  • org.libvirt.unix.manage: 読み書き可能な ソケットに対するアクセス

既定では読み書き可能なソケットに対するアクセスポリシーは、 root のパスワードによる認証を 1 度だけ実施し、あとはその時点のセッションと 今後のセッションでアクセスが許可されるようになっています (auth_admin_keep_always) 。

root のパスワードを入力することなく、読み書き可能なソケットに対して アクセスを許可するようにするには、 2 種類の方法があります:

  1. polkit-auth コマンドを利用することで、制限のない アクセスを許すことができます:

    polkit-auth --user tux --grant org.libvirt.unix.manage    # 権限の付与
    polkit-auth --user tux --revoke org.libvirt.unix.manage   # 権限の取り消し
  2. /etc/PolicyKit/PolicyKit.conf ファイルでは、より 詳しいオプションを提供しています。既存の <config version="0.1"> から </config> までの間に、下記の XML テキストを 入力してください:

    <match action="org.libvirt.unix.manage">1
      <match user="tux">2
        <return result="yes"/>3
      </match>
    </match>

    1

    ポリシーの名前を指定しています。 org.libvirt.unix.manage とは、読み書き可能なソケットに対するアクセスを意味します。

    2

    権限を与えるユーザを指定しています。複数を指定したい場合は、 | で区切ってください (user="tux|wilber") 。

    3

    与える権限の種類を指定します。下記のいずれかを指定します: yes (制限なくアクセスを許可する), no (完全にアクセスを拒否する), auth_self または auth_admin (それぞれ権限が要求された場合に、自分自身のパスワードか root のパスワードを確認する), auth_self_keep_session または auth_admin_keep_session (権限が要求された場合に 自分自身のパスワードか root のパスワードを確認する。いったん 確認が完了すると、以後の同セッションでは確認を不要とする), auth_self_keep_always または auth_admin_keep_always (権限が要求された場合に 自分自身のパスワードか root のパスワードを確認する。いったん 確認が完了すると、以後ずっと確認を不要とする) 。

6.1.1.3. SASL を利用したユーザ名とパスワードでの認証

SASL はユーザ名とパスワードによる認証を提供するほか、データの暗号化 (既定では digest-md5) も提供します。 SASL は独自のユーザデータベースを 持っているため、 VM ホストサーバ 上に実際のユーザを作成する必要はありません。 また、 SASL を利用するには TCP 接続と、 TLS/SSL 接続が必要です。

[Important]暗号化しない環境での TCP と SASL 認証

暗号化をしない環境で TCP 接続の digest-md5 認証を行なう場合、これは 本番環境で利用するには十分なセキュリティを確保できません。このような 使用形態は、テスト環境でのみ使用されるべきものです。

[Tip]TLS/SSL を利用した SASL 認証

リモートからの TLS/SSL 接続を受け付ける場合、証明書の鍵ファイルに対する アクセス制限を行なうことで、 クライアント側 での アクセス制御を実現することができます。ただし、多数のクライアントからの アクセスを受け付ける場合は、設定を間違えてしまいやすい仕組みでもあります。 TLS 経由での SASL を利用し、サーバ側でのアクセス制御を併用してください。

SASL 認証を設定するには、下記の手順で行ないます:

  1. /etc/libvirt/libvirtd.conf 内の設定を、下記のように 変更します:

    1. TCP 接続に対して SASL を有効にする場合:

      auth_tcp = "sasl"
    2. TLS/SSL 接続に対して SASL を有効にする場合:

      auth_tls = "sasl"
  2. libvirtd を再起動します:

    rclibvirtd restart
  3. libvirt の SASL 設定ファイルは /etc/sasl2/libvirtd.conf にあります。通常は、この設定ファイルを既定値から変更する必要はありません。 しかしながら、 TLS 経由で SASL を使用するような場合は、処理の重複を防ぐために セッションの (SASL 内の) 暗号化を無効化することができます。セッションの暗号化を 無効にするには、 mech_list をコメントアウトしてください。 TCP 接続の場合は digest-md5 に設定しなければなりません:

    mech_list: digest-md5   # TCP 接続での必須設定
    #mech_list: digest-md5   # TLS/SSL 接続でのみ適用されるべき設定
  4. 既定では SASL のユーザは何も設定されていないため、誰もログインできません。 それぞれ下記のコマンドを利用してユーザの追加や一覧表示、削除を行なって ください:

    mercury:~ # saslpasswd2 -a libvirt tux                  # ユーザ tux の追加
    Password: 
    Again (for verification): 
    mercury:~ # sasldblistusers2 -f /etc/libvirt/passwd.db  # ユーザの一覧表示
    tux@mercury.example.com: userPassword
    mercury:~ # saslpasswd2 -a libvirt -d tux               # ユーザ tux の削除
[Tip]virsh と SASL 認証

SASL 認証を使用している場合、 virsh コマンドを 実行するたびにユーザ名とパスワードの入力を求められます。これを回避する には、 virsh をシェルモードで起動してください。

6.1.2. VNC 認証

VM ゲスト のグラフィカルコンソールに対するアクセス制御は、 libvirtQEMU で制御されているものではないため、 VNC 認証の 設定には追加の作業が必要になります。中心となる設定ファイルは /etc/libvirt/qemu.conf です。

VNC 認証では 2 種類の認証方法を提供しています。 1 つは SASL による認証、 もう 1 つはパスワードだけを利用する認証です。 libvirt の認証に SASL を使用している場合は、 VNC 認証に対しても SASL を利用しておくことを強く お勧めします。これは同じデータベースを共有することができるためです。

VM ゲスト に対するアクセスを制限するための 3 つめの方法として、 VNC サーバ上で TLS による暗号化を使用する方法があります。これは VNC クライアント側に x509 クライアント証明書を配置して認証する方法で、これらの 証明書に対するアクセスをクライアント側で制御することで、アクセスを間接的に 制限することができるようになります。詳しくは 6.2.2.4.2項 「TLS/SSL を利用する VNC: クライアントの設定」 をお読みください。

6.1.2.1. SASL を利用したユーザ名とパスワードでの認証

SASL はユーザ名とパスワードによる認証を提供するほか、データの暗号化 も提供します。 SASL は独自のユーザデータベースを持っているため、 VM ホストサーバ 上に実際のユーザを作成する必要はありません。また、 libvirt に対して SASL を利用するには、 TLS/SSL 接続を利用することもできます。 これらの接続を設定する方法については、 6.2.2.4.2項 「TLS/SSL を利用する VNC: クライアントの設定」 をお読み ください。

VNC 用に SASL 認証を設定するには、下記の手順で行ないます:

  1. まずは SASL の設定ファイルを作成します。 libvirt 向けに用意された ファイルをお使いになるのがお勧めです。既に libvirt 向けに SASL を設定していて、同じユーザ名/パスワードのデータベースを 利用したい場合は、単純にリンクを作成するだけでかまいません:

    ln -s /etc/sasl2/libvirt.conf /etc/sasl2/qemu.conf

    VNC にのみ SASL を設定したい場合や、 libvirt とは異なる設定を使用 したい場合は、既存のファイルをベースとして使用するため、いったんコピー してから必要な修正を行なってください:

    cp /etc/sasl2/libvirt.conf /etc/sasl2/qemu.conf
  2. 既定では SASL のユーザは何も設定されていないため、誰もログインできません。 それぞれ下記のコマンドを利用してユーザの追加や一覧表示、削除を行なって ください:

    mercury:~ # saslpasswd2 -a libvirt tux                  # ユーザ tux の追加
    Password: 
    Again (for verification): 
    mercury:~ # sasldblistusers2 -f /etc/libvirt/passwd.db  # ユーザの一覧表示
    tux@mercury.example.com: userPassword
    mercury:~ # saslpasswd2 -a libvirt -d tux               # ユーザ tux の削除
  3. /etc/libvirt/qemu.conf 内の設定を 下記のように修正します:

    vnc_listen = "0.0.0.0"
    vnc_sasl = 1

    最初のパラメータでは、 VNC をすべてのインターフェイスに対して (ローカルホストだけでなく) 公開し、接続を受け付けるように設定して います。 2 つめのパラメータでは SASL 認証を有効にしています。

  4. libvirtd を再起動します:

    rclibvirtd restart
  5. 設定を変更する前から起動していたすべての VM ゲスト について、再起動を 行ないます。 VM ゲスト を再起動しない場合、 VNC 接続時の SASL 認証は 有効化されません。

[Note]対応する VNC ビューア

現時点では TLS/SSL 接続と SASL 認証に対応した VNC ビューアは、 Virtual Machine Manager, virt-viewer, vinagre の 3 種類です。

6.1.2.2. パスワードのみの認証

VNC サーバへのアクセスは、 VNC パスワードで制御することもできます。 すべての VM ゲスト に対して設定するグローバルパスワードを設定すること ができるほか、各ゲストに対して個別のパスワードを設定することもできます。 後者の場合、 VM ゲスト の設定ファイルを編集する必要があります。

[Note]グローバルパスワードの設定について

パスワードのみの認証を使用している場合、それぞれの VM ゲスト に対して 個別のパスワードを指定している場合でも、グローバルパスワードを設定して おくことをお勧めします。これはマシン単位でのパスワードを設定し忘れて しまった場合でも、お使いの仮想マシンを 第二の パスワードで 保護できるためです。また、グローバルパスワードは、その他のパスワードが そのマシンに設定されなかった場合にのみ使用されます。

手順6.1 グローバル VNC パスワードの設定

  1. /etc/libvirt/qemu.conf 内の設定を下記のように 変更します:

    vnc_listen = "0.0.0.0"
           vnc_password = "パスワード"

    最初のパラメータでは、 VNC をすべてのインターフェイスに対して (ローカルホストだけでなく) 公開し、接続を受け付けるように設定して います。 2 つめのパラメータではパスワードを設定しています。 パスワードに設定可能な最大の長さは 8 文字です。

  2. libvirtd を再起動します:

    rclibvirtd restart
  3. 設定を変更する前から起動していたすべての VM ゲスト について、再起動を 行ないます。 VM ゲスト を再起動しない場合、 VNC 接続時のパスワード 認証は有効化されません。

手順6.2 VM ゲスト 固有の VNC パスワードの設定

  1. まずは下記のようにして、 VNC をすべてのインターフェイスに対して (ローカルホストだけでなく) 公開し、接続を受け付けるように設定します。

    vnc_listen = "0.0.0.0"
  2. エディタで VM ゲスト の XML 設定ファイルを開きます。下記の例では VM 名 の部分を VM ゲスト の名前に置き換えて ください。使用されるエディタは、既定では $EDITOR 変数で 指定されたものを使用します。この変数が設定されていない場合は、 vi を使用します。

    virsh edit VM 名
  3. type='vnc' という属性を持った <graphics> の要素を探します。たとえば下記の ような要素です:

    <graphics type='vnc' port='-1' autoport='yes'/>
  4. passwd=パスワード という 属性を追加し、ファイルを保存しエディタを終了します。パスワードに設定 可能な最大の長さは 8 文字です。

    <graphics type='vnc' port='-1' autoport='yes' passwd='PASSWORD'/>
  5. libvirtd を再起動します:

    rclibvirtd restart
  6. 設定を変更する前から起動していたすべての VM ゲスト について、再起動を 行ないます。 VM ゲスト を再起動しない場合、 VNC 接続時のパスワード 認証は有効化されません。

[Warning]セキュリティ

VNC プロトコルは安全なプロトコルとは考えられていません。パスワードは 暗号化されて送信されますが、攻撃者が暗号化されたパスワードと暗号鍵の 両方を傍受することができる場合、パスワードを解読できてしまいます。 そのため、 TLS/SSL を利用するか、もしくは SSH トンネルを経由するなどの 形で VNC を利用することをお勧めします。 virt-viewer や Virtual Machine Manager のほか、バージョン 2.30 以降の vinagre で それら両方の方式に対応しています。

6.2. リモート接続の設定

libvirt の大きな利点のうちの 1 つに、複数の異なるリモートホスト上に ある VM ゲスト を一括管理できるという機能があります。この章では、 リモートから接続できるようにするための、サーバ側およびクライアント側の 設定方法を説明しています。

6.2.1. SSH を利用したリモートトンネル (qemu+ssh)

VM ホストサーバ 上で SSH のトンネルを利用したリモート接続を行なう場合は、 SSH の接続を受け付ける設定だけを行なえば作業は完了します。それぞれ SSH デーモンが起動していること (rcsshd status) と、 SSH サービスがファイアウオール で開かれていることを確認してください。

SSH 接続に対するユーザ認証は、従来通りのユーザ/グループと、 パーミッションによるものです。詳しくは 6.1.1.1項 「パーミッションとグループ所有者を利用した UNIX ソケット向けのアクセス制御」 をお読みください。 tux での接続 (qemu+ssh://tuxsIVname;/system) は即時に使用できる もので、 libvirt 側では特に何も行なう必要はありません。

SSH 経由で qemu+ssh://ユーザ名@システム のように接続を行なった場合、 ユーザ名 に対する パスワードを入力する必要があります。パスワード入力は、 VM ホストサーバ 上の ~ユーザ名/.ssh/authorized_keys ディレクトリに公開鍵をコピーすることで避けることもできます。 詳しくは 項 「SSH 鍵のコピー」 (第13章 SSH: 機密を保護する通信, ↑セキュリティガイド) をお読みください。 マシン上で ssh-agent を使用するのも便利な方法です。こちらについては 項 「ssh-agent コマンドの使用」 (第13章 SSH: 機密を保護する通信, ↑セキュリティガイド) をお読みください。

6.2.2. x509 証明書を利用したリモートの TLS/SSL 接続 (qemu+tls)

TLS/SSL 暗号と x509 証明書による認証を行なう TCP 接続は、 SSH を設定する よりも手順が複雑ですが、大規模な環境には適切な選択です。また、管理者が 変わる可能性のある環境で複数の VM ホストサーバ を管理するような場合には、この 方法を選択してください。

6.2.2.1. 基本的な考え方

基本的には、 TLS (Transport Layer Security) は証明書を利用することで 2 台のコンピュータ間の通信を暗号化します。接続を開始するコンピュータは クライアント証明書 を使用する クライアント として、接続を受け付けるコンピュータは サーバ証明書 を使用する サーバ として扱われます。以下の説明では、 中央にあるデスクトップ機からお使いの VM ホストサーバ を管理する場合を例に しています。

なお、両方のコンピュータから接続が開始されることがある場合は、それぞれの コンピュータにクライアント証明書とサーバ証明書の 両方を 配置する必要があります。これはたとえば、一方のコンピュータから他方の コンピュータに VM ゲスト を移設するような場合に該当します。

それぞれの x509 証明書には、それに対応する機密鍵ファイルが存在します。 また、証明書自身の正当性を確認するには、証明書と機密鍵の両方の正しい 組み合わせが必要です。さらに証明書が正しい所有者から発行されたもので あることを確認するためには、証明機関 (CA) と呼ばれる中央機関から発行され 署名されたものである必要があります。なお、サーバ証明書とクライアント 証明書は同じ CA から発行されたものでなければなりません。

[Important]ユーザ認証

リモートからの TLS/SSL 接続を利用する場合、基本的には特定の方向に対する 2 台のコンピュータ間のみの通信を許可することになります。この場合、 クライアント側で証明書にアクセスできるユーザを制限することで、間接的に ユーザ制限を行なうことができます。詳しくは 6.2.2.5項 「アクセス制限 (セキュリティ面の考慮事項)」 をお読みください。 なお、 libvirt では SASL を利用したユーザ認証にも対応しています。 こちらについての詳細は 6.2.2.6項 「TLS ソケットを利用した SASL によ中央集中型ユーザ認証」 をお読みください。

6.2.2.2. VM ホストサーバ の設定

VM ホストサーバ は接続を受け付ける側のマシンです。そのため、 サーバ 証明書をインストールする必要があります。証明機関の証明書についても、 あわせてインストールしてください。証明書をインストールすると、 libvirt は自動的に TLS サポートが有効になります。

  1. A.2項 「x509 クライアント/サーバ証明書の生成」 の手順に従って サーバ証明書を作成し、 CA の証明書とともにエクスポートします。

  2. VM ホストサーバ 上で下記のように入力してディレクトリを作成します:

    mkdir -p /etc/pki/CA/ /etc/pki/libvirt/private/

    下記のようにして証明書をインストールします:

    /etc/pki/CA/cacert.pem
    /etc/pki/libvirt/servercert.pem
    /etc/pki/libvirt/private/serverkey.pem
    [Important]証明書へのアクセス制限について

    6.2.2.5項 「アクセス制限 (セキュリティ面の考慮事項)」 で説明しているように、証明書へのアクセスが制限されていること を確認しておいてください。

  3. /etc/libvirt/libvirtd.conf ファイルを エディタで開き、 listen_tls = 1 を設定します。 設定が終わったら libvirtd を再起動します:

    rclibvirtd restart
  4. 既定では libvirt は TLS の機密接続用に TCP ポート 16514 で待ち受け ます。必要であれば、ファイアウオールで左記のポートを開いてください。

[Important]TLS を有効化した形での libvirtd の再起動

libvirt で TLS を有効にした場合、サーバ証明書をインストールする必要が あります。サーバ証明書がインストールされていないと、 libvirtd の再起動 が失敗します。また、証明書を変更した場合にも libvirtd の再起動が必要 となります。

6.2.2.3. クライアントの設定と設定テスト

クライアントは接続を行なう側のマシンです。そのため、 クライアント 証明書をインストールする必要があります。 証明機関の証明書についても、あわせてインストールしてください。

  1. A.2項 「x509 クライアント/サーバ証明書の生成」 の手順に従って クライアント証明書を作成し、 CA の証明書とともにエクスポートします。

  2. クライアント側で下記のように入力してディレクトリを作成します:

    mkdir -p /etc/pki/CA/ /etc/pki/libvirt/private/

    下記のようにして証明書をインストールします:

    /etc/pki/CA/cacert.pem
    /etc/pki/libvirt/clientcert.pem
    /etc/pki/libvirt/private/clientkey.pem
    [Important]証明書へのアクセス制限について

    6.2.2.5項 「アクセス制限 (セキュリティ面の考慮事項)」 で説明しているように、証明書へのアクセスが制限されていること を確認しておいてください。

  3. 下記のコマンドを入力することで、クライアントとサーバ間の接続テストを 行なうことができます。下記の mercury.example.com には VM ホストサーバ の名前を指定してください。サーバ証明書を作成した時と同じ 完全修飾ドメイン名を入力します。

    virsh -c qemu+tls://mercury.example.com/system list --all

    設定が正しければ、 VM ホストサーバ 上で libvirt を利用して作成した、 すべての VM ゲスト の一覧が表示されます。

6.2.2.4. TLS/SSL を有効化した VNC 接続の有効化

現時点では TLS を利用した VNC 接続は、ごく少数のツールでしかサポート されていません。たとえばよく使われている tightvnctigervnc などのビューアでは TLS への対応は行なわれて いません。逆に動作が確認されているものとしては、 Virtual Machine Manager (virt-manager), virt-viewer, GNOME VNC ビューア vinagre などがあります。

6.2.2.4.1. TLS/SSL を利用する VNC: VM ホストサーバ の設定

TLS/SSL を利用して VNC のグラフィカルコンソールにアクセスするには、 VM ホストサーバ 側で下記の設定作業が必要です:

  1. お買いのファイアウオールで、 VNC サービスを開きます。

  2. 下記のように入力して /etc/pki/libvirt-vnc ディレクトリを作成し、このディレクトリに対して証明書のリンクを作成 します:

    mkdir -p /etc/pki/libvirt-vnc && cd /etc/pki/libvirt-vnc
    	ln -s /etc/pki/CA/cacert.pem ca-cert.pem
    	ln -s /etc/pki/libvirt/servercert.pem server-cert.pem
    	ln -s /etc/pki/libvirt/private/serverkey.pem server-key.pem
  3. /etc/libvirt/qemu.conf ファイルを編集し、 下記のようにパラメータを設定します:

    vnc_listen = "0.0.0.0"
    	vnc_tls = 1
    	vnc_tls_x509_verify = 1
  4. libvirtd を再起動します:

    rclibvirtd restart
    [Important]VM ゲスト の再起動について

    VNC の TLS 設定は VM ゲスト の起動時にのみ設定可能です。 そのため、設定を変更する前から起動していたすべてのマシンについて、 再起動を行なう必要があります。

6.2.2.4.2. TLS/SSL を利用する VNC: クライアントの設定

クライアント側で必要な唯一の作業は、選択したクライアントソフトウエアで 認識可能な場所に、 x509 のクライアント証明書を配置することだけです。 サポートされる各クライアント (Virtual Machine Manager, virt-viewer, vinagre) はそれぞれ別々の場所に証明書を配置する仕組み ですが、 Virtual Machine Manager と vinagre については、全ユーザに適用 するシステム全体の証明書を配置する場所と、ユーザごとの証明書を配置する 場所が別々になっています。

Virtual Machine Manager (virt-manager)

リモートのホストに接続するには、 Virtual Machine Manager に対して 6.2.2.3項 「クライアントの設定と設定テスト」 で説明している 設定手順を実施する必要があります。 VNC のクライアント証明書については、 下記のディレクトリに配置します:

システム全体で使用する証明書の場合
/etc/pki/CA/cacert.pem
/etc/pki/libvirt-vnc/clientcert.pem
/etc/pki/libvirt-vnc/private/clientkey.pem
特定のユーザだけが使用する証明書の場合
/etc/pki/CA/cacert.pem
~/.pki/libvirt-vnc/clientcert.pem
~/.pki/libvirt-vnc/private/clientkey.pem
virt-viewer

virt-viewer にはシステム全体で利用する証明書の 場所しか用意されていません:

/etc/pki/CA/cacert.pem
/etc/pki/libvirt-vnc/clientcert.pem
/etc/pki/libvirt-vnc/private/clientkey.pem
vinagre
システム全体で使用する証明書の場合
/etc/pki/CA/cacert.pem
/etc/pki/vinagre/clientcert.pem
/etc/pki/vinagre/private/clientkey.pem
特定のユーザだけが使用する証明書の場合
$HOME/.pki/CA/cacert.pem
~/.pki/vinagre/clientcert.pem
~/.pki/vinagre/private/clientkey.pem
[Important]証明書へのアクセス制限について

6.2.2.5項 「アクセス制限 (セキュリティ面の考慮事項)」 で説明されている内容に従い、証明書へのアクセスを制限していることを ご確認ください。

6.2.2.5. アクセス制限 (セキュリティ面の考慮事項)

それぞれの x509 証明書は 2 種類の部品から構成されています。 1 つは公開 されるべき証明書、もう 1 つは機密鍵です。クライアントは両方の部品を利用 することで認証を行なうことができます。そのため、クライアントの証明書と 機密鍵の両方を読むことができるユーザであれば、誰でも VM ホストサーバ に アクセスできることになります。一方、サーバ証明書のうち両方の部品がそろって いれば、どんなマシンでも VM ホストサーバ になりすますことができます。このような ことを防ぐため、少なくとも機密鍵についてはできるだけ不正にアクセスされない よう、制限を行なう必要があります。最も簡単な解決方法としては、鍵ファイルに 対してパーミッションによるアクセス制限を行なう方法があります。

サーバ証明書

サーバ証明書は QEMU プロセスから読み込むことができる必要があります。 openSUSE では、 libvirt ツールから起動される QEMU のプロセスの 所有者は root なっています。そのため、 root が証明書を 読み込むことができれば、それで十分ということになります:

chmod 700 /etc/pki/libvirt/private/
chmod 600 /etc/pki/libvirt/private/serverkey.pem

/etc/libvirt/qemu.conf ファイルを編集して QEMU のプロセス所有者を変更した場合は、それにあわせて鍵ファイルの所有者を 設定する必要があります。

システム全体で使用するクライアント証明書

システム全体で使用する鍵ファイルについてアクセスを制御するには、 特定のグループに対して読み込みアクセスを許可するように設定し、その メンバーだけが鍵ファイルを読み込めむことができるようにします。下記の 例では libvirt グループを 作成し、 clientkey.pem ファイルとその親 ディレクトリに対して、 libvirt の所有グループを設定しています。作業を行なうと、設定した所有者と グループにしかアクセスが許されないようになります。最後に tux を libvirt グループに追加することで、 tux から鍵ファイルにアクセス できるようになります。

CERTPATH="/etc/pki/libvirt/"
# libvirt グループの作成
groupadd libvirt
# ユーザ root とグループ libvirt に所有者を設定
chown root.libvirt $CERTPATH/private $CERTPATH/clientkey.pem
# パーミッションの設定
chmod 750 $CERTPATH/private
chmod 640 $CERTPATH/private/clientkey.pem
# ユーザ tux をグループ libvirt に追加
usermod -A libvirt tux
特定のユーザだけが使用する証明書

VM ゲスト のグラフィカルコンソールに VNC 経由でアクセスする際、 特定ユーザ向けのクライアント証明書は、ユーザのホームディレクトリ以下の ~/.pki に配置しておく必要があります。これらの 証明書を使用する VNC ビューアなどでは、機密鍵のパーミッションを確認 しない仕組みになっているため、ユーザ側の責任で機密鍵が他のユーザに 読み取られないよう設定する必要があります。

6.2.2.5.1. サーバ側からのアクセス制限

既定では各クライアントには適切なクライアント証明書が配置され、 TLS 接続が 有効になっている VM ホストサーバ に対して接続を行ないます。そのため、サーバ側で SASL を利用した追加のサーバ側認証を行なうことができるようになっています。 詳しくは 6.1.1.3項 「SASL を利用したユーザ名とパスワードでの認証」 を お読みください。

また、 DN (識別名; Distinguished Names) のホワイトリスト機能を利用して、 アクセス制限を行なうこともできます。この場合、 DN の一覧に書かれた クライアントだけが接続できるようになります。

許可する DN を一覧に追加するには、 /etc/libvirt/libvirtd.conf ファイル内の tls_allowed_dn_list を設定します。 この値ではワイルドカードによる指定も可能です。なお、何も指定しない場合は すべての接続が拒否されることに注意してください。

tls_allowed_dn_list = [
   "C=US,L=Provo,O=SUSE Linux Products GmbH,OU=*,CN=venus.example.com,EMAIL=*",
   "C=DE,L=Nuremberg,O=SUSE Linux Products GmbH,OU=Documentation,CN=*"]

証明書に書かれている DN を表示するには、下記のコマンドを入力します:

certtool -i --infile /etc/pki/libvirt/clientcert.pem | grep "Subject:"

なお、設定を修正したあとは下記のようにして libvirtd を再起動します:

rclibvirtd restart

6.2.2.6. TLS ソケットを利用した SASL によ中央集中型ユーザ認証

6.2.2.5項 「アクセス制限 (セキュリティ面の考慮事項)」 で書かれている 手順でクライアント側のパーミッションを設定し、間接的にユーザ制限を行なう ことはできますが、 TLS で直接的なユーザ認証を行なうことはできません。 しかしながら、 libvirt でサーバ側でのユーザ認証を行ないたい場合、 TLS に SASL (Simple Authentication and Security Layer) を追加することで、 直接的なユーザ認証を実現することは可能です。詳しい設定方法については 6.1.1.3項 「SASL を利用したユーザ名とパスワードでの認証」 をお読みください。

6.2.2.7. トラブルシューティング

6.2.2.7.1. Virtual Machine Manager/virsh からサーバに接続できない

下記の順序で確認を行なってください:

ファイアウオールでポートを開いていますか? (サーバ側で TCP ポート 16514 を開いておく必要があります)
Virtual Machine Manager や virsh を起動したユーザから、 クライアント証明書 (証明書自身と機密鍵) を読み取ることができるように なっていますか?
サーバの証明書に書かれた完全修飾ドメイン名 (FQDN) と、 接続時の完全修飾ドメイン名 (FQDN) が同じですか?
サーバ側で TLS が有効になっていますか? (listen_tls = 1)
サーバ側で libvirtd を再起動しましたか?
6.2.2.7.2. VNC 接続が失敗する

まずは Virtual Machine Manager を利用してリモートのサーバに接続できるかどうかを確認して ください。問題なく接続できる場合は、下記のようにしてサーバ上の仮想マシンで TLS が有効化されていることを確認します。下記の例は仮想マシンの名称が sles11 である場合を示しています。

ps ax | grep qemu | grep "\-name sles11" | awk -F" -vnc " '{ print FS $2 }'

下記のように表示されていない場合は、そのマシンで TLS を有効化されていない ということになります。 TLS を有効化して再起動してください。

 -vnc 0.0.0.0:0,tls,x509verify=/etc/pki/libvirt

6.3. VM ホストサーバ への接続

libvirt を利用してハイパーバイザに接続するには、 URI (統一資源識別子; Uniform Resource Identifier) を指定する必要があります。この URI は virshvirt-viewer を利用する 場合 (ただし VM ホストサーバ 上で root として作業している場合を除きます) に必要となるほか、 Virtual Machine Manager で必要に応じて使用します。 virt-viewer の場合は接続パラメータとして指定することができます (例: virt-manager -c qemu:///system) が、接続 URI の 作成をグラフィカルなインターフェイスで行なうこともできます。詳しくは 6.3.2項 「Virtual Machine Manager を利用した接続の管理」 をお読みください。

ハイパーバイザ1+プロトコル2://ユーザ@リモート3/接続種類4

1

ハイパーバイザを指定します。 openSUSE では下記のハイパーバイザのみを サポートしています: test (テスト用のダミー), qemu (KVM), xen (Xen) 。 なお、このパラメータは必須です。

2

リモートから接続を行なう場合、ここでプロトコルを指定します。プロトコルは 以下のいずれかを指定します: ssh (SSH トンネル経由での接続), tcp (SASL/Kerberos 認証を利用した TCP 接続), tls (x509 証明書を利用した認証付きの TLS/SSL 暗号化接続)

3

リモートから接続を行なう場合、ここでユーザ名とリモートのホスト名を 指定します。ユーザを指定しない場合は、コマンドを呼び出したユーザの ユーザ名 ($USER) が使われます。詳しくは下記をお読み ください。 TLS 接続の場合、ホスト名は x509 証明書と同じホスト名を 指定しなければなりません。

4

QEMU のハイパーバイザに接続しようとしている場合、 2 種類の接続タイプのうちからいずれかを選択します。完全なアクセス権を 取得したい場合は system を、制限されたアクセスを取得 したい場合は session を指定します。 openSUSE では session アクセスをサポートしていないため、 この文書内では system アクセスのみを説明しています。

ハイパーバイザの接続 URI 例

test:///default

ローカルのダミー用ハイパーバイザに接続します。テスト用に便利な方法です。

qemu:///system

ローカルホスト上の QEMU ハイパーバイザに接続し、完全なアクセス権 (system タイプ) を取得します。

qemu+ssh://tux@mercury.example.com/system

リモートの mercury.example.com ホスト上にある QEMU ハイパーバイザに接続 します。接続は SSH トンネルを介して行ないます。

qemu+tls://saturn.example.com/system

リモートの mercury.example.com ホスト上にある QEMU ハイパーバイザに接続 します。接続は TLS/SSL を介して行ないます。

詳細と指定例について、詳しくは http://libvirt.org/uri.html にある libvirt のドキュメンテーションをお読みください。

[Note]URI 内でのユーザ名

Unix ソケット認証を使用する場合、ユーザ名/パスワード認証や PolKit を 使用するかどうかに関わらず、ユーザ名を指定する必要があります。これは すべての SSH およびローカル接続に当てはまります。

SASL 認証を使用する場合 (TCP または TLS 接続) や、 TLS 接続で追加の サーバ側認証を行なわない場合は、ユーザ名を指定する必要はありません。 SASL の場合は、ここで入力したユーザ名は使用されず、ユーザ名と パスワードを別途に尋ねられることになります。

6.3.1. 非特権ユーザに対する システム アクセス

上述のとおり、 QEMU ハイパーバイザへの接続は、 2 種類のプロトコル (セッション および システム) で実現できます。 セッション 接続はクライアントプログラム と同じ権限で動作するもので、制限が存在する (USB/PCI デバイスの割り当てや 仮想ネットワークの設定ができなかったり、 libvirtd に対するリモートアクセスが 制限されたりします) 都合上、主にデスクトップの仮想化に利用します。

システム 接続はサーバの仮想化に利用するもので、機能面での 制限はありませんが、 root のみがアクセスできます。しかしながら、 DAC (Discretionary Access Control; 任意アクセス制御) ドライバを libvirt に追加 することで、非特権ユーザに対して システム アクセスを許可できる ようになります。 システム アクセスを tux に許可するには、 下記のようにします:

手順6.3 一般ユーザに対する システム アクセスの許可

  1. UNIX ソケットを利用したアクセス許可は、 6.1.1.1項 「パーミッションとグループ所有者を利用した UNIX ソケット向けのアクセス制御」 に示されています。 今回の例では、 libvirt は libvirt グループ内のすべてのユーザに対してアクセスを許可し、 tux ユーザをこのグループ のメンバーにしています。これにより、 tuxvirsh や Virtual Machine Manager を利用して接続できるようになります。

  2. /etc/libvirt/qemu.conf を編集し、下記の設定項目を 変更します:

    user = "tux"
    group = "libvirt"
    dynamic_ownership = 1

    これにより、 VM ゲスト は tux て起動されるようになり、ゲストに割り当てられたリソース (仮想ディスクなど) は、 tux でアクセス/変更 できるようになります。

  3. kvm グループに対して、 tux を追加します:

    usermod -A kvm tux

    この手順は、 VM ゲスト を起動するために必要なデバイス /dev/kvm にアクセスできるようにするために必要です。

  4. 最後に libvirtd を再起動します:

    rclibvirtd restart

6.3.2. Virtual Machine Manager を利用した接続の管理

Virtual Machine Manager では管理対象のすべての VM ホストサーバ に対して 接続 を使用します。それぞれの接続には、そのホストで提供されているすべての VM ゲスト が含まれます。既定では、ローカルのホストに対する接続が自動で 設定され、自動的に接続された状態になります。

すべての設定済みの接続は、 Virtual Machine Manager のメインウインドウ内に表示されます。 有効な接続には小さな三角形マークが表示され、それを押すことで接続先に ある VM ゲスト の一覧を展開したり折りたたんだりすることができます。

無効な接続はグレー (灰色) で表示され、 Not Connected として印が付けられます。接続でダブルクリックを行なうか、もしくは右ボタンを 押すことで表示されるコンテキストメニューから Connect を選択することで、接続することができます。また、同じコンテキストメニュー から Delete を選択することで削除を行なうこともできます。

[Note]既存の接続の編集

既存の接続を編集することはできません。接続を変更したい場合は、新しい接続を 作成して必要なパラメータを設定し、その後 古い ほうの接続を 削除してください。

Virtual Machine Manager で新しい接続を作成するには、下記の手順で行ないます:

  1. メニューから File+Add Connection を選択します。

  2. ホストのハイパーバイザを Hypervisor で選択します (Xen または QEMU/KVM) 。

  3. 次に接続のタイプを Connection で選択します。 Virtual Machine Manager を起動しているホスト自身に接続する場合は Local を選択します。リモート接続の場合はいずれかを選択します (詳しくは 6.2項 「リモート接続の設定」 をお読みください) 。

  4. リモート接続の場合は、 Hostname に接続先のホスト名を ユーザ名@リモートホスト の形式で指定します。 SSH 接続やローカル接続の場合は、ユーザ名を指定しなければなりません。

    [Important]ユーザ名の指定について

    TCP や TLS での接続の場合、ユーザ名を指定する必要はありません。 指定を行なっても無視されます。ユーザ名はローカル接続や SSH 接続の場合に 指定しなければなりません。指定を行なわない場合は、既定のユーザ root が使用されます。

  5. Virtual Machine Manager の起動時に接続が自動的に有効化されないようにしたい場合は、 Autoconnect のチェックを外します。

  6. 最後に Connect を押すと、設定完了です。


openSUSE KVM を利用した仮想化 13.1