多くの VM ゲスト が存在する複数の VM ホストサーバ を扱うようになると、管理に手間がかかるようになってしまいます。 libvirt
では、複数の VM ホストサーバ に対して一括で接続し、単一のインターフェイスから全ての VM ゲスト を管理することができるほか、それらのグラフィカルインターフェイスにも簡単に接続できるようになっています。
不正な接続をされないようにする目的で、 libvirt
ではさまざまな種類の接続 (TLS, SSH, Unix ソケット, TCP) に対応しています。これらでは、さまざまな認可メカニズム (ソケット, Polkit, SASL, Kerberos) を組み合わせて使用することができます。
VM ゲスト の管理やそれらのグラフィカルコンソールへのアクセスは、正当なユーザからのアクセスのみを受け入れるように設定する必要があります。このような目的を達成するため、 VM ホストサーバ 側では下記のような認証技術を使用することができます:
パーミッションやグループの所有権を利用した、 Unix ソケット向けのアクセス制御。この方式は、 libvirtd
の接続にのみ適用することができます。
Polkit を利用した Unix ソケット向けのアクセス制御。この方式は、ローカルの libvirtd
接続にのみ適用することができます。
SASL (Simple Authentication and Security Layer) を利用したユーザ名とパスワードによる認証。この方式は libvirtd
と VNC のどちらの接続でも利用することができます。 SASL での認証は、システムとは異なるユーザデータベースを利用して管理を行うことから、サーバ内にユーザを作成する必要はありません。また、 SASL への認証接続は暗号化されます。
Kerberos 認証。この方式は、 libvirtd
の接続にのみ適用することができます。また、本マニュアルでは説明していません。詳しくは https://libvirt.org/auth.html#ACL_server_kerberos をお読みください。
単独パスワード認証。この方式は、 VNC 接続にのみ適用することができます。
libvirtd
への認証と VNC への認証は個別に設定する必要がある件についてVM ゲスト の管理機能 (libvirtd
経由) へのアクセスとグラフィカルコンソールへのアクセスは、それぞれ別々に設定する必要があります。管理ツールへのアクセスを制限しても、その設定は VNC 接続への設定に自動的に適用されることは ありません 。
TLS/SSL 接続を介してリモートから VM ゲスト にアクセスする場合、クライアント側で使用する証明書の鍵ファイルの読み込み権限を特定のグループに限定することで、間接的にアクセスを制御することができます。詳しくは 11.3.2.5項 「アクセス制限 (セキュリティ面の考慮事項)」 をお読みください。
libvirtd
の認証 #Edit sourcelibvirtd
の認証は /etc/libvirt/libvirtd.conf
で設定します。ここでの設定は、 仮想マシンマネージャ や virsh
など、全ての libvirt
ツールに適用されます。
libvirt
では 2 種類のソケットを提供しています。 1 つは監視用の読み込み専用ソケット、もう 1 つは管理操作に使用するための読み書き可能なソケットです。それぞれのソケットに対する設定は、個別に行うことができます。既定のアクセス許可設定では、読み書き可能なソケットが root
にのみ許可されるように制限 ( 0700
) され、読み込み専用のソケットは誰にでもアクセスできるように公開 ( 0777
) されています。
下記の手順では、読み書き可能なソケットに対するアクセス許可設定方法を示しています。読み込み専用ソケットに対しても同じような手順で実施することができます。また、設定作業は VM ホストサーバ 内で行います。
openSUSE Leap での既定の認証方式は、 Unix ソケットに対するアクセス制御です。 root
のみに対してアクセスを許可しています。 VM ホストサーバ で root 以外のユーザが libvirt
ツールを使用しようとすると、 Polkit を介して root
のパスワード入力を求められます。パスワードを正しく入力することで、現在および将来使用できるようにアクセスが許可されます。
それ以外の方法としては、非特権ユーザに対して libvirt
の 「システム」 アクセスを許可する方法があります。詳しくは 11.2.1項 「非特権ユーザに対する 「システム」 アクセス」 をお読みください。
11.1.1.2項 「Polkit を利用した Unix ソケット向けのローカルアクセス制御」 |
11.1.1.1項 「パーミッションとグループの所有権を利用した Unix ソケット向けのアクセス制御」 |
11.1.1.1項 「パーミッションとグループの所有権を利用した Unix ソケット向けのアクセス制御」 |
11.1.1.3項 「SASL を利用したユーザ名とパスワードによる認証」 |
無し (証明書へのアクセスを制限することで、クライアント側でアクセス制御) |
root
以外のユーザに対してアクセスを許可するには、特定のグループがソケットを所有し、アクセスできるように設定する必要があります (下記の例では、 libvirt
グループに対して許可する例を示しています) 。この認証方式は、ローカルとリモートの SSH 接続で使用することができます。
グループが存在していない場合は、下記を実行してソケットを所有すべきグループを作成します:
>
sudo
groupadd libvirt
このグループは、 libvirtd
の再起動を行うまでに存在していなければなりません。存在していない場合、再起動が失敗します。
あとはグループに対してユーザを追加していきます:
>
sudo
usermod --append --groups libvirt tux
/etc/libvirt/libvirtd.conf
ファイル内の設定を下記のように変更します:
unix_sock_group = "libvirt"1 unix_sock_rw_perms = "0770"2 auth_unix_rw = "none"3
libvirtd
を再起動します:
>
sudo
systemctl start libvirtd
Polkit を利用した Unix ソケット向けのアクセス制御は、ローカルからの接続における openSUSE Leap の既定の認証方式です。そのため、 libvirt
側の設定は不要です。 Polkit の認証方式を有効化していれば、両方のソケットに対するパーミッションは 0777
に設定され、ソケットにアクセスしようとするそれぞれのアプリケーション側で、 Polkit による認証が必要になります。
Polkit はリモートに対する認証には対応していませんので、 VM ホストサーバ 自身からのローカル接続にのみ使用することができます 。
libvirt
のソケットへのアクセスに対しては、 2 種類のポリシーが存在しています:
org.libvirt.unix.monitor : 読み込み専用ソケットに対するアクセス制御
org.libvirt.unix.manage : 読み書き可能なソケットに対するアクセス制御
既定では、読み書き可能なソケットに対するアクセスのポリシーは、 root
のパスワード入力を一度だけ求め、その時点およびその後のセッションでは、そのまま権限を許可する設定になっています。
root
のパスワードを入力させることなく、一般ユーザからソケットにアクセスできるようにするには、 /etc/polkit-1/rules.d
内にルールを作成する必要があります。たとえば /etc/polkit-1/rules.d/10-grant-libvirt
ファイルを下記の内容で作成すると、 libvirt
グループに所属する全てのメンバーに対して、ソケットへのアクセスを許可するようになります:
polkit.addRule(function(action, subject) { if (action.id == "org.libvirt.unix.manage" && subject.isInGroup("libvirt")) { return polkit.Result.YES; } });
SASL はユーザ名とパスワードによる認証を提供する仕組みで、データの暗号化 (既定では digest-md5) にも対応しています。 SASL は独自のユーザデータベースを利用して認証を行う仕組みであるため、 VM ホストサーバ 内にユーザを作成する必要はありません。また、 SASL は TCP 接続を利用し、 TLS/SSL にも対応しています。
他の方法で TCP の接続が暗号化されていない限り、 digest-md5 暗号化による認証を行っても、本番環境では十分なセキュリティであるとは言えません。このような構成は、テスト環境でのみ使用することをお勧めします。
TLS/SSL によるリモートからのアクセスを許可する場合、 クライアント側で 証明書の鍵ファイルのアクセスを制限することで、間接的にアクセスを制御することができます。ただし、多くのクライアントを設定する場合、設定ミスを引き起こしやすい構成でもあります。 TLS による認証を行う際は、 SASL による認証も同時に行うものとして、サーバ側でも追加の制御を行うようにしてください。
SASL 認証を設定するには、下記の手順を実施します:
/etc/libvirt/libvirtd.conf
ファイル内の設定を下記のように変更します:
TCP 接続による SASL を使用したい場合:
auth_tcp = "sasl"
TLS/SSL 接続による SASL を使用したい場合:
auth_tls = "sasl"
libvirtd
を再起動します:
>
sudo
systemctl restart libvirtd
libvirt の SASL 設定は /etc/sasl2/libvirtd.conf
ファイル内に書かれています。通常は既定で設定されている内容を変更する必要はありませんが、 TLS と SASL を併用する場合、不要なオーバーヘッドを削減するため、セッション暗号化を無効化 (TLS の時点で既に暗号化されているため) することができます。これは、 mech_list
の行をコメントアウトすることで実現することができます。ただし、下記の設定は TLS/SASL を併用する場合にのみ設定するものし、通常の TCP 接続では digest-md5 のままにしなければなりません。
#mech_list: digest-md5
既定では SASL ユーザは何も設定されていませんので、誰もログインできない状態になります。下記のコマンドを利用して、ユーザを管理してください:
tux
というユーザを追加:saslpasswd2 -a libvirt tux
tux
というユーザを削除:saslpasswd2 -a libvirt -d tux
sasldblistusers2 -f /etc/libvirt/passwd.db
virsh
と SASL の認証の関係についてSASL 認証を使用している場合、 virsh
コマンドで接続を行うと、毎回ユーザ名とパスワードを尋ねられるようになります。 virsh
をシェルモードで動作させると、この手間を省くことができます。
VM ゲスト のグラフィカルコンソールへのアクセスは libvirt
の管理範囲外であり、ハイパーバイザ側で管理されているものであることから、 VNC 認証については必ず設定しておく必要があります。メインとなる設定ファイルは /etc/libvirt/<ハイパーバイザ名>.conf
です。本章では QEMU/KVM ハイパーバイザを説明していますので、設定ファイルは /etc/libvirt/qemu.conf
になります。
KVM とは異なり、 Xen の VM にはパスワードによる認証しか設定できません。詳しくは下記にある libvirt
の設定オプションのうち、 <graphics type='vnc'...
の箇所をご覧ください。
VNC の認証は 2 種類の認証方式 (SASL, 単独パスワード認証) に対応しています。 libvirt
側で SASL 認証を使用している場合、 VNC 認証でも同じものを使用することをお勧めします。もちろん同じデータベースを使用するように設定することができます。
3 種類目のアクセス制限方式として、 VNC サーバでの TLS 暗号化の使用という方式もあります。この場合、 VNC クライアント側に x509 クライアント証明書を配置することになります。これらの証明書へのアクセスを制限することで、クライアント側で間接的にアクセスを制限することになります。詳しくは 11.3.2.4.2項 「VNC over TLS/SSL: クライアント設定」 をお読みください。
SASL はユーザ名とパスワードによる認証を提供するだけでなく、データの暗号化の機能も提供します。また、 SASL は独自のデータベースを使用する方式であるため、 VM ホストサーバ 内にユーザを作成しておく必要もありません。 libvirt
に対して SASL の認証を設定する場合、 TLS/SSL 接続を利用することもできます。これらの接続の設定方法について、詳しくは 11.3.2.4.2項 「VNC over TLS/SSL: クライアント設定」 をお読みください。
VNC 向けに SASL 認証を設定するには、下記の手順を実施します:
まずは SASL の設定ファイルを作成します。作成にあたっては、既存の libvirt
向けファイルを使用することをお勧めします。既に libvirt
向けに SASL を設定してある環境で、ユーザ名とパスワードを含む全ての設定を共通で使用したい場合は、下記のようにしてシンボリックリンクを作成するだけでかまいません:
>
sudo
ln -s /etc/sasl2/libvirt.conf /etc/sasl2/qemu.conf
VNC にのみ SASL を設定する場合や、 VNC 専用に個別の設定を作成したい場合は、既存のファイルをコピーして雛形として使用することをお勧めします:
>
sudo
cp /etc/sasl2/libvirt.conf /etc/sasl2/qemu.conf
あとは必要に応じて内容を修正してください。
/etc/libvirt/qemu.conf
にある設定ファイルを、下記のように修正します:
vnc_listen = "0.0.0.0" vnc_sasl = 1 sasldb_path: /etc/libvirt/qemu_passwd.db
最初のパラメータは、 VNC サービスが待ち受けるべきアドレスを指定するものです。この場合、ローカルホストだけでなく、全てのアドレスから接続できる設定になります。 2 つ目のパラメータは、 SASL 認証を有効化するための設定です。
既定では SASL ユーザは何も設定されていませんので、誰もログインできない状態になります。下記のコマンドを利用して、ユーザを管理してください:
tux
というユーザを追加:>
saslpasswd2 -f /etc/libvirt/qemu_passwd.db -a qemu tux
tux
というユーザを削除:>
saslpasswd2 -f /etc/libvirt/qemu_passwd.db -a qemu -d tux
>
sasldblistusers2 -f /etc/libvirt/qemu_passwd.db
libvirtd
を再起動します:
>
sudo
systemctl restart libvirtd
設定を変更する前から VM ゲスト を動作させていた場合は、それら全てを再起動します。再起動を行わない場合、 VNC では SASL を使用することができません。
現時点では、 SASL 認証は 仮想マシンマネージャ と virt-viewer
でのみ対応しています。これらのビューアは、 TLS/SSL 接続にも対応しています。
VNC サーバへのアクセスは、パスワード単独での認証で制限することもできます。この場合、全ての VM ゲスト に対してグローバルパスワードを設定するか、それぞれのゲストに対して個別にパスワードを設定することができます。なお、後者は VM ゲスト の設定ファイル内に記述します。
パスワード単独で認証を設定する場合、それぞれの VM ゲスト に対してパスワードを設定している場合でも、グローバルパスワードを設定しておくことをお勧めします。これにより、マシンごとのパスワードを設定し忘れた場合でも、代替となるパスワードが設定されることになりますので、最低限の保護は実現することができます。なお、グローバルパスワードは、マシンに対してそれ以外のパスワードが設定されていない場合にのみ適用されます。
/etc/libvirt/qemu.conf
にある設定ファイルを、下記のように修正します:
vnc_listen = "0.0.0.0" vnc_password = "パスワード"
最初のパラメータは、 VNC サービスが待ち受けるべきアドレスを指定するものです。この場合、ローカルホストだけでなく、全てのアドレスから接続できる設定になります。 2 つ目のパラメータはパスワードです。パスワードは最大で 8 文字まで設定することができます。
libvirtd
を再起動します:
>
sudo
systemctl restart libvirtd
設定を変更する前から VM ゲスト を動作させていた場合は、それら全てを再起動します。再起動を行わない場合、 VNC ではパスワード認証を使用することができません。
/etc/libvirt/qemu.conf
にある設定ファイルを下記のように修正し、ローカルホストだけでなく、全てのアドレスから接続できるようにします:
vnc_listen = "0.0.0.0"
次にエディタを利用して、 VM ゲスト の XML 設定ファイルを開きます。下記の VM_名 には、実際の VM ゲスト の名前を入れてください。また、起動されるエディタは $EDITOR
で指定されたエディタになります。何も値を設定していない場合、 vi
エディタを使用します。
>
virsh edit VM_名
type='vnc'
という属性が書かれた <graphics>
タグを探します。たとえば下記のように書かれているはずです:
<graphics type='vnc' port='-1' autoport='yes'/>
この箇所に passwd=パスワード
の形式で属性を追加して、ファイルを保存したあとエディタを終了します。なお、パスワードは最大 8 文字まで設定することができます。
<graphics type='vnc' port='-1' autoport='yes' passwd='PASSWORD'/>
libvirtd
を再起動します:
>
sudo
systemctl restart libvirtd
設定を変更する前から VM ゲスト を動作させていた場合は、それら全てを再起動します。再起動を行わない場合、 VNC ではパスワード認証を使用することができません。
VNC プロトコルは安全なプロトコルであるとは考えられていません。パスワードは暗号化されて送信されるものの、暗号鍵と暗号化されたパスワードの両方を傍受することができてしまえば、解読できてしまう危険性があるためです。そのため、 TLS/SSL で別途暗号化を行って VNC 接続するか、 SSH の暗号化トンネルを介して接続することをお勧めします。 virt-viewer
や 仮想マシンマネージャ, Remmina (詳しくは 4.2項 「Remmina: リモートデスクトップクライアント」 をお読みください) では、いずれの方式にも対応しています。
libvirt
を利用してハイパーバイザに接続するには、まず Uniform Resource Identifier (URI) を指定する必要があります。この URI は virsh
や virt-viewer
(VM ホストサーバ 内で root
から接続する場合を除きます) で必要となるほか、 仮想マシンマネージャ でも任意で指定することができます。 仮想マシンマネージャ では URI ではなく、接続パラメータ (例: virt-manager -c qemu:///system
) と呼ばれることもあるほか、 URI をグラフィカルなインターフェイスで作成することもできます。詳しくは 11.2.2項 「仮想マシンマネージャ による接続の管理」 をお読みください。
ハイパーバイザ1+プロトコル2://ユーザ名@ホスト名3/接続の種類4
ハイパーバイザを指定します。 openSUSE Leap では | |
リモートのホストに接続する場合、ここでプロトコルを指定します。 | |
リモートのホストに接続する際のユーザ名とリモートホスト名を入力します。ユーザ名を指定しない場合、このコマンドを呼び出したユーザの名前 ( | |
|
test:///default
ローカルでのテスト用ハイパーバイザへの接続を行います。
qemu:///system
もしくは xen:///system
ローカルホストにある QEMU ハイパーバイザや Xen ハイパーバイザに接続します。このとき、完全なアクセス権限 (system) を取得します。
qemu+ssh://tux@mercury.example.com/system
もしくは xen+ssh://tux@mercury.example.com/system
リモートのホスト mercury.example.com にある QEMU ハイパーバイザや Xen ハイパーバイザに接続します。このとき、接続は SSH トンネル経由で行います。
qemu+tls://saturn.example.com/system
もしくは xen+tls://saturn.example.com/system
リモートのホスト mercury.example.com にある QEMU ハイパーバイザや Xen ハイパーバイザに接続します。このとき、接続は TLS/SSL トンネル経由で行います。
さらに詳しい情報や例について、詳しくは https://libvirt.org/uri.html にある libvirt
のドキュメンテーション (英語) をお読みください。
Unix ソケット認証を利用する場合、それがユーザ名/パスワード認証であっても、 Polkit による認証であっても、ユーザ名は必ず指定しておく必要があります。これは全ての SSH 接続やローカル接続にも当てはまります。
SASL 認証 (TCP もしくは TLS 接続) を使用する場合や、 TLS 接続で追加のサーバ側認証を行わない場合は、ユーザ名を指定する必要はありません。 SASL の場合、ユーザ名は処理されません。ここでユーザ名を指定していても、 SASL のユーザ名とパスワードの入力を求めるプロンプトが別途表示されます。
上述のとおり、 QEMU ハイパーバイザへの接続は 2 種類のプロトコル (session
と system
) を利用することができます。 「session」 を指定した場合、クライアント側のプログラムと同じ権限で動作することになります。この種類の接続は、さまざまな機能 (たとえば USB/PCI のデバイス割り当てや仮想ネットワークの設定、 libvirtd
へのリモートアクセスなど) が制限されていることから、デスクトップ仮想化向けに用意されている仕組みです。
「system」 の接続はサーバの仮想化のために用意されている接続で、機能面の制限が無い代わりに、既定では root
のみに対してアクセスを許可しています。しかしながら、 libvirt
に対する DAC (Discretionary Access Controll; 任意アクセス制御) ドライバの追加により、非特権ユーザに対しても 「system」 接続を許可することができるようになっています。たとえば tux
に対して 「system」 接続を許可するには、下記のようにします:
Unix ソケット経由でのアクセス許可を、 11.1.1.1項 「パーミッションとグループの所有権を利用した Unix ソケット向けのアクセス制御」 に書かれている手順で有効化します。左記の例では、 libvirt を libvirt
というグループの全てのメンバーに対して許可し、このグループのメンバーに tux
を追加しています。これにより、 tux
は virsh
や 仮想マシンマネージャ を利用して接続することができるようになっています。
/etc/libvirt/qemu.conf
ファイルを編集して、下記の設定を変更します:
user = "tux" group = "libvirt" dynamic_ownership = 1
これにより、 VM ゲスト を tux
から開始することができるようになるとともに、ゲストに対するリソース (仮想ディスクなど) の割り当てについても、 tux
からアクセスおよび変更できるようになります。
tux
をグループ kvm
のメンバーに追加します:
>
sudo
usermod --append --groups kvm tux
この手順は VM ゲスト を開始する際に使用する /dev/kvm
へのアクセスを許可するために必要となるものです。
libvirtd
を再起動します:
>
sudo
systemctl restart libvirtd
仮想マシンマネージャ では管理対象となるそれぞれの VM ホストサーバ に対して 接続
を設定します。この接続には、対応するホスト内にある全ての VM ゲスト が含まれています。既定では、ローカルホストへの接続は設定済みで、接続も行われた状態になります。
全ての設定済みの接続は 仮想マシンマネージャ のメインウインドウ内に表示されます。接続済みのものには小さな三角形が描かれ、これを押すことで接続先の VM ゲスト の一覧を展開したり、折りたたんだりすることができます。
接続されていないものは灰色で描かれ、 未接続
と表示されます。ダブルクリックを行うか、マウスの右ボタンを押して、表示されたコンテキストメニューから を選択すると、接続を行うことができます。また、同じコンテキストメニューから を押すことで、接続を削除することもできます。
既存の接続を編集することはできません。接続を変更したい場合は、必要なパラメータで新しい接続を作成したあと、古いほうを削除してください。
仮想マシンマネージャ 内に新しい接続を追加するには、下記の手順を実施します:
› を選択します。
ホストの
( もしくは ) を選択します。リモート接続を設定する場合は、 11.3項 「リモート接続の設定」 をお読みください。
を選択します。詳しくはリモート接続の場合、 ユーザ名@ホスト名
の形式で、 に接続先を入力します。
TCP や TLS の接続の場合は、ユーザ名を指定する必要はありません。これらのプロトコルの場合は、ユーザ名は無視されます。しかしながら SSH 接続の場合、 root
以外のユーザで接続する際には、ユーザ名の指定が必要となります。
仮想マシンマネージャ の起動時に自動的に接続したくない場合は、
のチェックを外してください。最後に
を押すと、設定を保存することができます。libvirt
の大きな利点の 1 つとして、 1 箇所から複数のホスト内にある VM ゲスト を管理することができる、という点があります。本章では、リモート接続を行う際のサーバ側およびクライアント側の設定方法について説明しています。
qemu+ssh
もしくは xen+ssh
) #Edit sourceVM ホストサーバ に対して SSH 経由でリモート接続を行う場合、必要な接続は SSH 接続だけとなります。それぞれ SSH デーモンが動作しているかどうか ( systemctl status sshd
) と、ファイアウオールで SSH
のポートが開いていることを確認しておいてください。
SSH 接続の場合のユーザ認証は、従来型のファイルのユーザおよびグループの所有権、およびパーミッションでの制御 (11.1.1.1項 「パーミッションとグループの所有権を利用した Unix ソケット向けのアクセス制御」 で説明しています) で行います。ユーザ tux ( qemu+ssh://tux@mercury.example.com/system
もしくは xen+ssh://tux@mercury.example.com/system
) での接続は何も設定することなく行うことができますので、 libvirt
側で特に設定を行う必要はありません。
SSH 経由での接続 (qemu+ssh://ユーザ名@システム
もしくは xen+ssh://ユーザ名@システム
) を行う場合、 ユーザ名 に対するパスワードを入力する必要があります。これは 22.6項 「公開鍵認証」 の手順に従って公開鍵認証を設定することで、回避することができます。また、接続元のマシンで gnome-keyring
を使用すると、さらに便利になります。詳しくは 22.9項 「gnome-keyring を利用した公開鍵ログインの自動化」 をお読みください。
qemu+tls
もしくは xen+tls
) #Edit sourceTLS/SSL による暗号化で TCP 接続を行い、 x509 証明書を利用して認証を行う環境の構築は SSH よりずっと複雑になりますが、拡張性をずっと高めることができます。この方式は、管理者の人数がしばしば変化するような VM ホストサーバ を管理する必要がある場合にお使いください。
TLS (Transport Layer Security) では証明書を利用することで、 2 台のコンピュータ間の通信を暗号化します。接続を開始する側のコンピュータが常に 「クライアント」 となり、 「クライアント証明書」 を利用して接続を行います。また、接続を受け付ける側のコンピュータが常に 「サーバ」 となり、こちらも 「サーバ証明書」 を利用することになります。このような方式により、 VM ホストサーバ を中央のデスクトップから一括管理することができるようになっています。
どちらのコンピュータからも接続を行うような場合、双方がクライアント証明書とサーバ証明書の両方を持つ必要があります。これはたとえば、 VM ゲスト を一方のホストから他方のホストに移行させるような場合に当てはまります。
また、それぞれの x509 証明書には、対応する機密鍵ファイルが存在しています。証明書ファイルと機密鍵ファイルは一対で使用します。また、正しく証明書が認識されるようにするため、証明機関 (CA) と呼ばれる機関で署名され、発行された証明書を使用することをお勧めします。また、クライアントの証明書もサーバの証明書も、同じ CA から発行されているものでなければなりません。
TLS/SSL によるリモート接続は、 2 台のコンピュータ間で特定の方向で認証を行い、通信を確立する処理を行うためのものです。特定のユーザにのみアクセスを許可したい場合は、クライアント側で証明書にアクセスすることのできるユーザを制限してください。詳しくは 11.3.2.5項 「アクセス制限 (セキュリティ面の考慮事項)」 をお読みください。
libvirt
では SASL を利用してサーバ側でユーザ認証を行うこともできます。こちらについては 11.3.2.6項 「TLS ソケット向けの SASL を利用した中央管理型ユーザ認証」 をお読みください。
VM ホストサーバ が接続を受け付ける側になります。そのため、 VM ホストサーバ には サーバ 証明書をインストールする必要があります。 CA の証明書もインストールする必要があります。証明書の準備を整えたら、 libvirt
側で TLS サポートを有効化することができます。
サーバ証明書を作成し、対応する CA の証明書とともにエクスポートします。
VM ホストサーバ 側で下記のとおりディレクトリを作成します:
>
sudo
mkdir -p /etc/pki/CA/ /etc/pki/libvirt/private/
下記のようにして証明書をインストールします:
>
sudo
/etc/pki/CA/cacert.pem>
sudo
/etc/pki/libvirt/servercert.pem>
sudo
/etc/pki/libvirt/private/serverkey.pem
11.3.2.5項 「アクセス制限 (セキュリティ面の考慮事項)」 で説明している内容に従って、証明書へのアクセスを制限するようにしてください。
対応するソケットに対して TLS のサポートを有効化し、 libvirtd
を再起動します:
>
sudo
systemctl stop libvirtd.service>
sudo
systemctl enable --now libvirtd-tls.socket>
sudo
systemctl start libvirtd.service
既定では、 libvirt
は TCP ポート 16514 で TLS 接続を受け付けます。ファイアウオール側でこのポートを開いておいてください。
libvirtd
を再起動する場合の注意事項libvirt
で TLS を有効化した場合は、必ずサーバの証明書も設定しておいてください。証明書が設定されていないと、 libvirtd
の再起動が失敗します。また、証明書を変更した場合も、 libvirtd
の再起動が必要となります。
クライアントとは、接続を行うのことを指します。そのため、 クライアント 証明書をインストールする必要があります。また、 CA の証明書についてもインストールを行う必要があります。
クライアント証明書を作成し、対応する CA の証明書とともにエクスポートします。
クライアント側では下記のディレクトリを作成します:
>
sudo
mkdir -p /etc/pki/CA/ /etc/pki/libvirt/private/
下記のようにして証明書をインストールします:
>
sudo
/etc/pki/CA/cacert.pem>
sudo
/etc/pki/libvirt/clientcert.pem>
sudo
/etc/pki/libvirt/private/clientkey.pem
11.3.2.5項 「アクセス制限 (セキュリティ面の考慮事項)」 で説明している内容に従って、証明書へのアクセスを制限するようにしてください。
下記のコマンドを実行して、クライアントとサーバの設定をテストします。下記では、 mercury.example.com の箇所に VM ホストサーバ の名前を指定してください。なお、サーバ側の証明書を作成した際に使用したものと同じ、完全修飾ドメイン名を指定する必要があります。
#QEMU/KVM virsh -c qemu+tls://mercury.example.com/system list --all #Xen virsh -c xen+tls://mercury.example.com/system list --all
設定が正しく行われていれば、 VM ホストサーバ 内の libvirt
に登録されている、全ての VM ゲスト の一覧が表示されるはずです。
現時点では、 TLS を利用した VNC 接続の暗号化は、少数のツールでしかサポートしていません。 tightvnc
や tigervnc
などの一般的な VNC ビューアは、 TLS/SSL に対応していません。 仮想マシンマネージャ と virt-viewer
を除くと、 TLS/SSL に対応しているビューアは remmina
のみとなります (詳しくは 4.2項 「Remmina: リモートデスクトップクライアント」 をお読みください) 。
TLS/SSL を利用して VNC 経由でグラフィカルコンソールにアクセスするには、 VM ホストサーバ を下記のように設定する必要があります:
まずはファイアウオールの設定を行い、サービス VNC
向けのポートを開きます。
/etc/pki/libvirt-vnc
ディレクトリを作成し、このディレクトリ内に証明書へのリンクを作成します:
>
sudo
mkdir -p /etc/pki/libvirt-vnc && cd /etc/pki/libvirt-vnc>
sudo
ln -s /etc/pki/CA/cacert.pem ca-cert.pem>
sudo
ln -s /etc/pki/libvirt/servercert.pem server-cert.pem>
sudo
ln -s /etc/pki/libvirt/private/serverkey.pem server-key.pem
/etc/libvirt/qemu.conf
ファイルを編集して、下記のパラメータを設定します:
vnc_listen = "0.0.0.0" vnc_tls = 1 vnc_tls_x509_verify = 1
最後に libvirtd
を再起動します:
>
sudo
systemctl restart libvirtd
VNC の TLS 設定は、 VM ゲスト の起動時にのみ設定することができます。そのため、設定変更を行う前から起動している VM ゲスト が存在した場合、それらを再起動する必要があります。
クライアント側でやるべきことは、選択したクライアントで認識される場所に、 x509 のクライアント証明書を配置するだけです。ただ残念なことに、 仮想マシンマネージャ と virt-viewer
は、それぞれ別々の場所に証明書を配置する仕組みになっています。 仮想マシンマネージャ は全てのユーザに反映できるシステム全体の場所のほか、ユーザごとの個別の場所も用意されています。 Remmina (詳しくは 4.2項 「Remmina: リモートデスクトップクライアント」 をお読みください) では、リモートの VNC セッションの接続を開始する際に証明書の場所を尋ねます。
virt-manager
) リモートのホストに接続するには、まず 仮想マシンマネージャ を 11.3.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 |
11.3.2.5項 「アクセス制限 (セキュリティ面の考慮事項)」 で説明している内容に従って、証明書へのアクセスを制限するようにしてください。
x509 証明書は 2 つのものから作られています。 1 つは一般に公開する証明書そのもの、そしてそれに対応する機密鍵です。これらの両方を使用することで認証を行うことができる仕組みです。そのため、クライアント証明書と機密鍵にアクセスができてしまえば、あとは自由に VM ホストサーバ にアクセスできることになってしまいます。サーバ証明書の場合、証明書と機密鍵にアクセスできてしまえば、誰でも VM ホストサーバ になりすますことができてしまいます。このようなことが発生しないようにするため、少なくとも機密鍵については、できる限りアクセス制限を厳しく設定する必要があります。これを実現するのに最も簡単な方法は、アクセスパーミッションを利用してアクセスを制限する方法です。
サーバ証明書は QEMU のプロセスが読み込むことができる必要があります。 openSUSE Leap の QEMU では、 libvirt
ツールが起動するプロセスは 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
グループのメンバーとして追加すると、機密鍵ファイルにアクセスできるようになります。
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 --append --groups libvirt tux
VNC 経由で VM ゲスト のグラフィカルコンソールにアクセスするために使用する、ユーザごとのクライアント証明書は、ユーザのホームディレクトリ以下の ~/.pki
内に配置します。 SSH 等とは異なり、これらの証明書を使用する VNC ビューアは、機密鍵ファイルのパーミッションを確認しません。そのため、ユーザごとの証明書は、単純に自分自身が読み込めるようにパーミッションを設定するだけで十分となります。
既定では、対応する証明書を設定しているクライアントであれば、 VM ホストサーバ はどのクライアントからでも接続を受け付けます。このような理由から、 SASL によるサーバ側での認証を追加で設定できるようになっています (詳しくは 11.1.1.3項 「SASL を利用したユーザ名とパスワードによる認証」 をお読みください) 。
上記の方法以外にも、 DN (Distinguished Name; 識別名) のホワイトリストを設定して、アクセスを制限する方法もあります。この場合、対応する DN の証明書を持つクライアントのみが接続できることになります。
具体的には、 /etc/libvirt/libvirtd.conf
ファイル内の tls_allowed_dn_list
に、許可する DN の一覧を記述してください。この一覧にはワイルドカードを設定することもできます。ただし、空のリストを指定してはなりません。この場合、全ての接続を拒否することになってしまいます。
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
を再起動します:
>
sudo
systemctl restart libvirtd
TLS では、直接的なユーザ認証を行うことはできません。実現するとすれば、 11.3.2.5項 「アクセス制限 (セキュリティ面の考慮事項)」 で説明している手順に従って、クライアント側で証明書に対する読み込みアクセス権 (パーミッション) を設定することができるくらいです。ただし、中央管理型でサーバベースのユーザ認証が必要となる場合、 libvirt
では TLS 上で SASL (Simple Authentication and Security Layer) を使用するようにして、ユーザ認証を行うことができます。設定方法に関する詳細は、 11.1.1.3項 「SASL を利用したユーザ名とパスワードによる認証」 をお読みください。
virsh
がサーバに接続できない #Edit source下記の順序で確認を行ってください:
ファイアウオール側の問題 (TCP ポート 16514 がサーバ側で開く必要がある) ではありませんか? |
クライアント証明書 (証明書そのものと機密鍵) が、 仮想マシンマネージャ/ virsh を起動したユーザから読み込むことができますか? |
接続時にサーバ証明書と同じ完全修飾ドメイン名を指定していますか? |
サーバ側で TLS が有効化されています ( listen_tls = 1 ) か? |
サーバ側で libvirtd を再起動していますか? |
まずは 仮想マシンマネージャ を利用して、リモートのサーバに接続できることを確認します。問題なく接続ができていることを確認したら、仮想マシンが TLS サポート付きで開始されているかどうかを確認します。下記の例では、 sles
という名前の仮想マシンに対して確認を行っています。
>
ps ax | grep qemu | grep "\-name sles" | awk -F" -vnc " '{ print FS $2 }'
上記のコマンドの出力に下記のような内容が含まれていない場合は、 TLS サポート付きで起動されていないことになりますので、設定を行って仮想マシンの再起動を行ってください。
-vnc 0.0.0.0:0,tls,x509verify=/etc/pki/libvirt