2017/12/16

esxtop のご乱心とその対処法について

vSphere の管理をしていると、vSphere Client などGUIからではらちがあかず、SSH でログオンして様々なコマンドで状況を確認、解消する事もよく出てきます。

特にパフォーマンス問題で力を発揮するのが esxtop コマンドです。Linux, UNIX の top コマンドのように仮想マシンや関連プロセスの稼働状況、IOの状況を表示、定期的に更新してくれる優れものです。
esxtop : とくにパフォーマンス問題で無くてはならない管理者の友です
ただ、様々な端末を使っていると、ときにこの esxtop の表示が乱れたり、vi や less が下記の画像のような表示をして正しくスクロールしてくれなくなる事があります。
esxtop ご乱心!

terminal is not fully functional のメッセージ
リターンを押すと一応表示されるが、若干挙動がおかしくなる

これはどうしてかを簡単に調べてみました。

● 端末画面制御

esxtop や vi, less といったコマンドの特徴は、ただ出力のテキストを垂れ流すのではなく、画面の任意の位置を書き換え、適切なところに表示を行おうとする、事です。こうした端末画面の制御のためのデータベースとして、termcap と terminfo があります。とか言うと何故画面制御にデータベースが関係する? となりますが、これはUNIXと「端末」の歴史にもつながってきます。

60年代やそれ以前、極めて初期のコンピュータでは出力は「紙」でした。プログラムからの出力は紙に印字されて出力されていました。その後にブラウン管への出力に移っていきましたが、ごく初期のブラウン管の出力とキーボードなどの入力の組み合わせた機械、すなわち「端末」(Terminal)では、やはり出力をそのまま、左から右、上から下へだだっと垂れ流すしかできませんでした。これを「ダム端末」と呼ばれてました。dumb=馬鹿とかのろまとかという意味で、まあシリアルケーブルなどを通じて送られてきたデータをただ垂れ流し表示するだけ、なんの能もないからそういう名前になったようです。

少し時代が経つと、少し賢い端末がでてきました。ダム端末に対してこれらは「インテリジェント端末」とも呼ばれました。インテリジェント端末の定義は時代により様々ですが、出始めの場合、文字に色がつけれる、Tektronixと言う会社の端末のように グラフィックの表示機能を備えたものとかがインテリジェント端末と呼ばれました。
(後にはパソコンベースの端末でローカルでのアプリケーションの実行やそれとホストとの連携ができるもの、などがインテリジェント端末と呼ばれるそうですが、私はこの頃はよく知りません。)

インテリジェント端末の時代になってただ出されたテキストを垂れ流しで表示するのではなく、文字の色を変えたり、画面の任意の位置にカーソルを動かして「左から右、上から下」ではない順序での表示が可能になりました。

このような画面の操作を行うのにつかわれたのが「エスケープシーケンス」などと呼ばれる一連のテキストです。これは出力のテキストに混ぜて送られ、送られた文字をただ表示するのではなく、その文字列が指示する動き、例えば次の文字を赤く表示する、カーソルの位置を上から20左から30に移動させる、を実施しました。ちょうどHTMLのタグみたいなものです。この一連のコードはエスケープ(0x1B)を先頭にする場合が多かったこともありエスケープシーケンスと呼ばれました。

エスケープシーケンスは後にISOの共通規格にもなりましたが、問題は、インテリジェント端末の出始めは必ずしも端末のエスケープシーケンスが同じ、ではありませんでした。ホスト上で動くソフトウェア、例えば vi とか esxtop、が次はカーソルを左上に動かして強調文字で「ABC」と書きたい、とか思っても、端末ごとに送るエスケープシーケンスは異なる、端末ごとにアプリ側で対応が必要となりました。ホストに繋ぐ端末機器を変えるたびにアプリ側の設定変更(あるいはコードの修正)が必要になりました。

これは不便だと登場したのが BSD UNIX の「termcap」というデータベースです。/etc/termcap というファイルに、端末ごとのエスケープシーケンス、カーソルを上に動かす時はこう、色を変える時はこう、っという定義を記載、環境変数 TERM によりどの端末の種類かを定義、esxtop のようなアプリケーションはTERMの端末種別を元に termcap から適切なエスケープシーケンスを読み出し、適切な操作ができるようになりました。
環境変数TERM
SystemV では terminfo というほぼ同じ仕組みが作られました。termcap との違いは「termcap はテキストで人が読める」「terminfo はテキストの定義を元にバイナリに変換、アプリからの読み込みが手っ取り早い」と、まあその程度です。

なお、いまどきの Linux, UNIX では terminfo の方を使うのが一般的となってます。

Windows の TeraTerm Pro Putty といったソフトウェアは、SSH や TELNET といったプロトコルで通信する機能を提供する一方、エスケープシーケンスを解釈し適切な表示を行う「端末」の役割も果たしてます。このため端末エミュレータとも呼ばれます。分かりやすいのは macOS の「ターミナル」や Ubuntu Linux などのターミナルアプリで、これらは「端末」としての表示のみを担当、SSH での通信は ssh コマンド、TELNET での通信は telnet コマンド、が担当しております。

余談ですが Windows 8 から 10 にかけて、ウィンドウズのコマンドプロンプトウィンドウもかなり機能強化されましたが、その一つとして端末エミュレータとしての機能強化もあります。マイクロソフト自身が OpenSSH を移植、Windows10 への標準搭載化を進めていますので、端末エミュレータとしての機能の受け皿が必要になった、というのもあります。

閑話休題、ともあれ termcap ないしは terminfo というデータベースを通じて端末の形式から正しいエスケープシーケンスを調べだし、適切な画面の制御ができるようになっている、というのが Linux, UNIX の端末画面制御になります。

なお、terminfo の情報は通常、/usr/share/terminfo 以下にあります。コンピュータの処理能力が非力だった時代からあるため、負荷軽減と検索の高速化のため、terminfo フォルダの下にサブフォルダを作成、1ファイル1端末種別 でファイルが格納されています。
macOS 10.12.6 Sierra での terminfo の設定ファイル数
1ファイル=1端末種別のため、約2600の端末機器に対応...ほとんどは使われないと思うけど。
macOS の場合、terminfo 以下には 2563ファイル存在、つまり 2563種類の端末に対応しています。

また、「ターミナル」アプリケーションでは、以下画面の10種類の端末形式に対応しております。
Mac の場合、ターミナルアプリのプロファイルにて、
プロファイルごとにどの端末の種別かを設定できる

vt100 はハードウェアだった端末でのデファクトスタンダードで、vt100互換、つまりvt100と同じエスケープシーケンスを受け付ける端末ハードウェアが多かったと伺っております。また、xterm は X Window System に付属のターミナルソフトで、rxvt は xterm を元に軽量化させたもので、一時期 流行ってたのを記憶しております。
( なお、私は NeXT(標準ターミナルアプリケーション) -> UX/OS(kterm) という流れで以降は Mac か Windows を端末に Solaris や Linux にリモートアクセスなので、xterm を少々使った事があるぐらいです。)

大まかに有名どころの端末のエスケープシーケンスに対応していると言えます。
この「ターミナルの宣言方法」を切り替えてから新規ターミナルウィンドウを開くと、環境変数TERMはその値に設定され、そして若干挙動がかわります。例えば、vt100 と xterm でそれぞれ less を実行、終了すると分かりやすいと思います。


● ESXi の端末情報データベース

さて、ようやく本題です。
ESXi Shell の環境も概ね Linux, UNIXの仕組みを継承しています。画面制御については実は terminfo を使っています。ではどれだけの端末の種類に対応してるでしょうか...。

ESXi Shell 環境での端末の種別。5行、すなわち5ファイルで、5端末種別、だけ...。
はい。たった5種類の端末にしか対応していません。内訳を見ると、screen, xterm, ansi, linux, vt102 です。screen は端末切り替えソフトの screen を使用の際に使われるもの、linux は Linux 起動時のコンソールで利用される端末の種別で、実際、コンソールでの ESXi Shell では環境変数TERM は linux に定義されています。
ローカルコンソールでの ESXi Shell
環境変数が linux になってるのが分かる
つまり、ssh接続などで一般的に使われる端末エミュレータとしては、xterm か vt102 しか対応していない、といえます。
Mac のターミナルアプリケーションのデフォルトの端末種別は「xterm-256color」です。ssh コマンドはデフォルトでローカルの環境変数TERMをリモートにも伝えてくれます。つまり ESXi にログインした場合、環境変数 TERM は xterm-256color が設定されますが、これは ESXi 側の terminfo に存在しない端末種別のため、esxtop のように画面制御ができずダム端末のようにテキストを流し込んでくるか、冒頭の less のように「制御できないけど、いい?」って聞いてくるようになります。

● どう対処すべきか

このような問題が生じている場合、簡単なのは送付する環境変数TERM を変えてしまうと言う事です。
例えば、以下のように env コマンドで環境変数TERMを xterm に変更後 ssh コマンドを実行すると、ESXi 側では xterm-256color ではなく xterm として扱ってくれます。

env コマンドで環境変数TERMを再設定してから ssh
結果、再設定したTERMの値が伝えられる
xterm-256color と xterm は、色に関するエスケープシーケンスが違うだけで互換性がありますので、このような無茶も通ります。

あとは、そもそも端末エミュレータ側の端末種別を xterm か  vt102 に設定してしまう、というのもあります。

この手の問題をググると、「だったら terminfo に設定追加すれば良いじゃん」的な答えが散見されますが、残念ながら ESXi Shell の環境には tic コマンド(terminfo でテキストの設定からバイナリの設定にコンパイルするコマンド)が存在しないので、やるとすると少々面倒です。また、ESXi Shell 環境というかあのファイルシステムにあまり独自のファイルを置くのはあまり推奨されません。やるなら tardisk とか ramdisk の仕組みをよく調べて、ESXi の動き、何処のファイルが温存されどれが消えうるかを確認、これらの意味をよく分かった上で実施すると良いでしょう。

ともあれ、vSphere の管理者にとって esxtop が使えない環境は最悪です。環境変数TERMをうまく扱う事でそんな環境はなくしていきましょう。


最後に、個人的な感想ですが、「いや、vt100互換が実際には vt102互換である事ぐらいは知ってるけどさ、何も馬鹿正直に vt102 だけを置いて vt100 を置かないってのもないんじゃねえの?」とか思いましたよ、ええ。


2017/10/26

Fall Creators Update で OpenSSH が標準搭載に(ただしBeta)

ふと、Windows10 の設定アプリにて、「アプリと機能」の「オプション機能の管理」から、「機能の追加」を見たところ、OpenSSH のサーバとクライアントを Windows10 のオプションとして導入できるようになっていた。


以前よりマイクロソフトは Windows 向けに OpenSSH の移植を行っていたが、どうやらこれがとうとうOS側に搭載されるようになったようだ。まだβ版で以下に述べるように少々問題があるが、エスケープシーケンスが強化されてきているコマンドプロンプトウィンドウとあわせることで、TeraTermPutty といったターミナルエミュレータ抜きで SSH によるリモートアクセスが可能になる点は歓迎したい。

せっかくなので OpenSSH Client の方をインストールしてみた。モジュールは %SYSTEMROOT%\System32\OpenSSH 以下にインストールされる。システム環境設定のPATHにも設定されるのだが、これは次にサインインするセッションから有効なため、インストールを行ったそのセッションではパスが設定されないことに注意。インストールが終わったら一度サインアウト/サインインをしなおすようにしよう。

たまたま macOS Sierra で sshd が動いているのでこちらに接続してみた。パスワードを用いた場合はあっさりとログインできた。



\Users\<アカウント名>直下に .ssh フォルダを作成、config ファイルを作成する事で ssh クライアントの設定を行う事もできる。



しかし、ssh-keygen を用いて鍵を作成しようとしたところ、RSA, DSA などはそもそも作成できず、ed25519 については作成できているものの、id_ed25519 ファイルの作成で失敗する。おそらく、\ と / が混在したパスがデフォルトで指定されているために見受けられる。



では、と id_ed25519 ファイルのパスを手入力してみたところ、/ だとパスの区切りとして認識できないのか失敗し、\ は「¥¥」にエスケープされてしまい、これまた失敗してしまう。今のところ、ssh-keygen でキーの作成には成功していない。

それでは、とこれまで使っていた TeraTerm を使って公開鍵と秘密鍵を作成、macOS 側の ~/.ssh/authorized_keys に公開鍵を登録してみた。TeraTerm  でこの公開鍵と暗号鍵でパスフレーズによる認証ができた事を確認した後、今回の ssh コマンドでも試してみた。


結果がこれである。


ssh コマンドも id_ed22519 ファイルが読めていないように見受けられる。これもパスの問題の模様だ。この事から、公開鍵による認証は現時点ではできないと言える。



また、ESXi にサインインしようとしたところ、暗号化方式が合致せずサインインできなかった。


この ESXi は 6.5.0 build-4887370 なのだが、/etc/ssh/sshd_config では以下の暗号化およびメッセージ認証符号が以下に設定されている。
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,3des-cbcMACs hmac-sha2-256,hmac-sha2-512,hmac-sha1
...正直、これは少々後ろ向きというかトラッディショナルというかいまどきな設定に見受けられる。なお、macOS Sierra での sshd の設定では Ciphers も MACs も特に設定されていないが、デフォルトで以下のように設定されている。


macOS Sierra と Windows10 の ssh でそれぞれのバージョン、対応している暗号(Cipher)およびメッセージ認証符号(MAC)を出力させたが、バージョンは 7.4p1 と 7.5p1 でほぼ同じだが、対応している Cipher と MAC が段違いである事が分かった。



しかも、この出力が正しいなら ESXi とは Cipher: aes256-ctr, MAC:hmac-sha2-256 あたりでネゴシエーションしそうなのだが、どうも記載されている全ての Cipher,MACが使えるわけでもないようだ。




公開鍵による認証ができない、Cipher,MAC が今風のしかない事から接続先が限られるなど、現時点では諸々問題がありこれ一個で、とはいかない。他の SSH クライアントは用意しておくべきだろう。とはいえまだβ版だ。そのうちこれらの問題は解決していくだろう。


コマンドとしての動作は十分に軽快で、OS標準で提供され、サードパーティーのアプリを入れなくて良いという点では評価ができるかと思われる。

2017/10/20

Flash 27.0.0.170 で WebClient がクラッシュする

普段使ってない vSphere 6.5 の vCenterServer アクセス、WebClient を使おうとした時に、ブラウザ内で「プラグインがクラッシュしました」などと表示され WebClient がいつまでもあがってこず難儀してしまったのでメモ。

これは、WebClient 側の問題で、VMware の KB (2151945) にも記載がある。
残念ながら現時点では解決策はない。ワークアラウンドとしては
  • Flashプラグインのβ版を導入する
  • 前のバージョンの Flash プラグインに無理矢理ダウングレードする
  • HTML5の vSphere Client ないしは C# の vSphere Client を使う
の三つだ。正直どの対応もいかがなものかと思うのだが、vSphere 6.5 の場合これまで使っていた Windows アプリ(C#) の vSphere Client も使えないし、HTML5版はまだばまだメインで使うには辛いのでダウングレードを試してみた。

macOS の Macbook Pro のため、
  1. Adobe のサイトから Flash のアンインストーラをダウンロード、実行
  2. こちらのサイトから 27.0.0.159 の Flashプラグインをダウンロード、インストール
  3. システム環境設定の Flash Playerペインから Flash の自動アップアップデートを禁止
という手順になった。
なお、1. のアンインストーラーは PPAPI の Flash も NPAPI の Flash もどちらも消してしまうので要注意だ。また、上記にリンクされている 27.0.0.159 の Flashプラグインは各OS版がまとめて入っているので少々大きい。使うのは「27_0_r0_159」フォルダのなかの「flashplayer27_0r0_159_mac.dmg」と「flashplayer27_0r0_159_macpep.dmg」だけだ。flashplayer27_0r0_159_mac.dmg が NPAPI 版のプラグインで、flashplayer27_0r0_159_macpep.dmg が PPAPI 版プラグインだ。

NPAPI はもはや Firefox しか使ってない古いインターフェイスのもので、PPAPI は Chrome および Safari が使っているより新しいインターフェイスになる。

私は Chrome を使っていないのと、普段使いの Safari と WebClient へのアクセス用のFirefox を分けていたのもあり、NPAPI 版の「flashplayer27_0r0_159_mac.dmg」飲みをインストールした。

結果、WebClient が使えるようになったが、Flash の利用には制限をかけておいた方がいいのかも知れない。










2017/08/31

仮想マシンとハードウェアクロック

PCの中には時間を刻むハードウェアが内蔵されており、今が何月何日の、何時何分何秒かを把握しております。歴史的な事情からこのハードウェアは単一ではなく、複数のものが存在していたりします。かつては RTC (Real Time Clock)という仕組みだけでしたが、これがあまり精度が良くなかった、使い勝手が悪かったなどの理由で HPET が登場し、CPU には TSC というタイマーが用意されたのでこれを使って時刻を図ることが行われ、また ACPI には ACPI PMT というこれまた時間を計る機能が存在します。

ともあれ、OS は起動時にPCハードウェアのこれらの時計から時間を取得、カウンターを利用して、取得後どれぐらい経過したかを知り、OS自身で時間を管理しております。
例えば Linux の場合は、OSの終了時に hwclock コマンドを使ってPCのハードウェア側にOSが把握している時間をかき込みます。Windows などの場合もおそらくOS終了時に時刻を書き戻しているでしょう。この理由は、PCのハードウェア上の時刻はずれていることがままあるためです。

この PC上のハードウェアの時計は「どの時間帯」の時間を記録しているでしょうか?実はこれは決まっていません。ほとんどの場合、ハードウェアの時計はローカルタイム、現地時間を記録してます。一方、ハードウェアの時計が UTC(世界標準時) であることを前提としているシステムもあります。例えば ESXi がそうです。ESXi は物理ホスト上のハードウェアの時計に UTC での時間をかき込み、起動時も UTC であることを前提に読み込みをします。

一方、Windows や Linux では、OSの内部では UTC をベースに構成されていますが、時刻の表示時には指定されたタイムゾーンを加味して現地の時間を表示しております。ハードウェアの時計に対しても、ローカルタイムがかき込まれているものと考えるのがデフォルトとなってます。先の hwclock コマンドも、OSから読み出した時間を /etc/localtime ファイルの示す時間帯を考慮した現地時間でかき込みます。


● 仮想マシンの時間

VMware の場合、初回起動時には ホストOSの時間がそのまま使われます。VMware Player や Workstation, Fusion では、新しい仮想マシンを作成して起動、BIOS設定画面に入ると現地時間での時刻が表示されます。
かつての ESX でもそうでした。ESX の場合、COS(サービスコンソール) の Linux 上の /etc/localtime を参照して仮想マシンの仮想的なハードウェアの時計に「ローカル時間」をかき込んでました。
ESXi の場合、/etc/localtime のようなタイムゾーンを把握する枠組みがありません。vSphereClient などで時間を見ると現地時間が表示されますが、これらはクライアントソフトウェア側で変換して表示しているもので、ESXi との時間のやりとりは UTC をベースとしています。

このため、ESXi で仮想マシンを作成、初回の起動時にBIOS時間を見ると、UTCで表示されます。日本の場合、9時間前の時刻が表示されていることになります。

新規に作成した仮想マシン
17:42 頃のものだが、8:42となっており、初回起動時は9時間ずれてるのが分かる
二度目以降の起動では少々事情が異なります。ゲストOSが終了時に(仮想の)ハードウェアの時計に時間を設定した時、VMware はそのかき込まれた時間と自身が把握している時間を比較、「差分」を検知します。ESXi の場合、上のOSが「日本時間」をかき込んでくると、9時間早い時間がかき込まれたことを検知します。この差分は nvram ファイルに保存されます。

二度目以降の起動時は、自身の時刻にこの差分を加味した時刻を、仮想マシンのハードウェアの時計としてセットします。先の例の場合、UTCに9時間を加えた時刻をハードウェアの時計とします。これは日本時間になります。ゲストOSはこの時間を読み込みますので、結果として正しい時間になります。
この挙動は VMware のこのドキュメントの「Virtual CMOS RTC」に記載されています。


● 他のハイパーバイザの仮想マシン

Hyper-V の場合は Windows の時刻管理に準じるためあまり深いことを考える必要がありません。

今回、この記事を書く動機になったのは KVMについてのハードウェアの時計がどうなってるかを調べたことからでした。KVM では、仮想マシンのモニタである qemu-kvm コマンドの引数 -rtc にどう設定するかによって決まります。主に以下2つのオプションが使われます。

  • clock : 時刻を何処で管理するか
    • clock=vm : 仮想マシン側で独自に時刻を管理する
    • clock=host : ホストの時間をそのまま利用する
  • base : 仮想マシンの起動時、(仮想の)ハードウェアの時計を何処に設定するか
    • base=2010-12-03T01:02:00 : 2010/12/03 01:02:00 に設定する
    • base=utc : UTCでの現在時間に設定する
    • base=local : ホストOSのタイムゾーンを加味した現地時間に設定する

OpenSUSE のドキュメントの例をみると
qemu-kvm [...] -rtc clock=vm,base=2010-12-03T01:02:00
となってますが、これは「時刻は仮想マシンで独自に管理」「2010 12/03 1:02:00 をハードウェアの時計の開始時間」として設定することを意味します。

(AHVについては記述が誤っていたため一旦削除しました。あらためて正しい情報を書きます。)

2017/04/06

【余談】Hammerspoon に移行

手元の Mac の OSをアップデートしたら Karabiner が利用できなくなってしまった。
どうも  macOS Sierra に非対応のとのこと。Karabiner はカーネルにモジュール(KEXT)を読み込ませ、カーネル内部のキーイベントを操作することでキーバインドの変更を実現している模様だが、そのためカーネルの変更に弱い面がある。

一方の Apple はセキュリティ面やOSの安定稼働の面から、KEXT による拡張を抑制する方向にある。Microsoft も 64bit 移行やOSのアップグレードの機会を通じて電子署名されていないデバイスドライバはロードできないようにしているし、iOS のようなモバイルデバイスのOSでは、もはやカーネルにモジュールを追加することすら不可能になっている。

幸い、Karabiner では Karabiner Elements という新しいキーリマップソフトウェアを開発、そこから従来の Karabiner の機能を追加していく形で刷新するようで、これは期待が持たれる。とはいえ、一からの作り直しなのでしばらくは Karabiner なしの生活に耐えなければならないようだ。

私が Karabiner を使ってる理由は、実のところ「Microsoft Office で Emacs キーバインド(のサブセット)が使いたい」 につきる。Karabiner Elements では現在のところアプリケーションごとのキーマップというのは実装されてないので、これは対応できないことになる。

いい加減 面倒になってきたので色々探して試した結果、Hammerspoon を利用することに落ち着いた。Hammerspoon はキー入力などのイベントを Lua という言語を使ってカスタマイズするもので、単なるキーリマップ以上の操作もできるようだ。
また、Accessibility API を通じてキーイベントを取得、操作を行う。公式のAPI を通しているため、OSのアップデートによる影響も(KEXTを使うのに比べると)低い訳だ。

Hammerspoon は ~/.hammerspoon/init.lua というスクリプトを読み、これに応じて処理をおこなう。私のスクリプトは以下の通りだ。

詳細は、この gist のコメントを見てほしい。

2017/02/18

【TIPS】外付けSSD

普段は Macbook Air (2012) で VMware Fusion を使っていますが、本体のストレージ容量が256GBしかないのでやりくりには苦労します。仮想マシンもインストール用ISOイメージもGB単位で容量を食うので、こまめに掃除しないとあっという間にあふれてしまいます。

そこで、前職の頃から外付けSSDを接続してこちらに仮想マシンを配置、使用しております。
こんな感じです。

外付けSSDドライブ。下の袋は函館に旅行したときに買ってたものを利用

Transcend の TS512GESD400K という 512GB の外付けSSDで、今だと 25,000円程度で入手できます。前職では会社に買ってもらって利用していたのですが退職時に会社支給の Macbook Air と共に返却、ただ使い勝手が良く気に入ってたので退職後、自分でも買い直した次第です。(なお、Macbook Air はたまたま知己が買い換えで余らせてたものを引き取ったのですが、奇しくも前職で使ってたのと同じ2012年ものとなりました。)

仮想マシンやISOイメージはこちらに格納して、Fusionを利用するときだけドライブを接続して使ってます。小さく軽いため鞄に入れてても気になりませんし、USB3.0のポートに繋いでいる限りは、内蔵SSDで仮想マシンを起動しているとの体感的な速度差は感じません。

唯一の注意点は、付属のUSB3.0ケーブルを使うこと、って事ですか。高速通信をがんがんかけるので、品質の良くないケーブルを使うとたちまち不安定になります。
付属品は太くて取り回しが少々不便なのですが、そのぶん安定しております。

検証ごとにリンククローンで仮想マシンを作ってるせいもあるのですが、この中に常時20ないしそれ以上の仮想マシンが入ってます。

Macbook Air の場合(というか最近の Mac のノート全般で) 本体のストレージ交換は酷く面倒な上、交換用のドライブも高価です。

若干はかさばりますが、リーズナブルな価格での増量ができる、外付けSSDは悪くない選択肢かと思われます。





Windows Server 2016 仮想化ベースのセキュリティ

Windows Server 2016 では様々なレイヤーでのセキュリティの強化が実装されていますが、その中の一つに「仮想化ベースのセキュリティ」と呼ばれる一連の機能があります。

機能名としては「Device Guard」や「Credential Guard」など呼ばれるものです。その詳細についてはマイクロソフトのこちらのページをご参照頂ければと思います。

ポイントとしては上記ページの以下の図が分かりやすいかと思います。

https://technet.microsoft.com/ja-jp/library/mt483740(v=vs.85).aspx より引用


これは Credential Guard の例ですが、ドメイン環境でのサインイン時に、ActiveDirectory から得られた認証情報(Credentials)は、通常ですと OS のメモリ空間のどこかに存在します。このため、カーネル内を含めメモリを読むことができる特権を得られれば、それをメモリから読み取り、奪い取ることができてしまいます。そのアカウントのパスワードを知らずとも、得られた認証情報をつかうことでそのユーザーとしてドメイン内のリソースへアクセスできてしまいます。

Credential Guard を有効にすると、Hyper-V による仮想化を利用して認証情報が切り離されます。 (厳密には異なりますが)ざっくりとしたイメージとしては本来の Windows Server を実行する仮想マシンと、認証情報だけを抱えた小さな仮想マシンの2つが Hyper-V にのっかっているという感じです。

仮想マシン同士のメモリ空間はハイパーバイザーによって分断されており、ある仮想マシンのメモリ空間の端から端までアクセスしても、他の仮想マシンのメモリ空間にはアクセスできません。これらは Intel-VT や SLAT といったハードウェアの機構により実現されており、ハイパーバイザー上のゲストOSやアプリケーションでは越えることができません。
つまり、別空間に切り離された認証情報を従来と同じ方法では盗めない、切り離された秘匿情報は正当なAPIを通じてのみアクセスが許可されます。

これが、Credential Guard です。また、仮想化ベースのセキュリティの一例となります。


要件は冒頭のページを見て頂ければと思いますが、ざっくりとは以下の感じです。
  • OS: Windows 10 Enterprise ないしは Windows Server 2016
  • CPU: 64bit CPU, Intel VT (AMD-V)および SLAT対応
  • TPM: 1.2 ないし 2.0 対応 (1.2の場合は Windows10 1511以降)
あと、セキュアブートも必要となってきます。

物理PC上での利用が前提(Windows 10 の場合仮想マシン上はサポート外)ですが、Windows Server 2016 と Windows 10 で可能となった、nested Hyper-V を使えば仮想マシン上でも試すことはできます。

そこで、実際に仮想マシンで Credential Guard を有効にしてみました。


● 事前準備

まず、Hyper-V 上で G2 仮想マシンを作成します。
従来型の G1仮想マシンは BIOSベースのファームウェアで、ブートドライブとしてIDEのエミュレーションが、デフォルトのNICもエミュレーションベースのものになります。物理PCとの互換性は高いのですが、性能的に制約がある次第です。

G2 仮想マシンは UEFIベースのファームウェアで稼働し、IDEやNICのエミュレーションをしません。高性能の代わりに Hyper-V に対応していないOSはインストールできません。もっとも、Windows ならば Vista 以降、Linux でも最近のものなら標準で Hyper-V 向けのデバイスドライバーを持っており後から統合サービス(IC)をインストールしなくても良くなってます。

あと、重要なポイントとして、G2仮想マシンは UEFI上でのセキュアブートを実現しているという点です。今回はセキュアブート環境を用意したいために、G2を選択しています。


Windows Server 2016 をインストールして、Windows Update の実行など一般的な処理をおこなっておきます。別に ServerCore でも構わないのですが、後での動作確認を楽にするためにデスクトップエクスペリエンスありを利用しております。

一旦シャットダウン後、Enable-NestedVM.pl を利用して仮想マシン上での Hyper-V の実行を許可します。方法がよく分からない場合は、こちらの動画を参照してください。

その後、仮想マシンを再び起動し、Hyper-V の役割を有効化します。
以前の Windows10 ではこのときに「分離ユーザーモード」 の機能も有効化する必要がありました。
が、Windows Server 2016 および最近の Windows10 では分離ユーザーモードの選択肢が存在しません。OSに標準組み込みになったので特に選択する必要眼漠なったようです。

Hyper-V の役割のインストールに伴い再起動が発生するので、一回再起動しておきます。

これで、Credential Guard を有効化するための準備は完了です。


● Credential Guard の構成

Credential Guardの設定はグループポリシーを通じて行います。今回はドメインに参加していない1台だけのため、mmc.exe を起動、スナップインの追加でグループポリシーの編集を追加、ローカルコンピューターポリシーを編集しますが、ドメイン環境下の場合、GPOを配布することでドメイン下のメンバーサーバなどにまとめて一気に設定をすることもできます。

ともあれ、設定するポリシーは以下になります。



「コンピューターの構成」->「管理テンプレート」->「システム」->「DeviceGuard」の下に、「仮想化ベースのセキュリティを有効にする」があります。これをダブルクリックしてます。



まずは上のラジオボタンを未構成から「有効」にします。

次に、「プラットフォームのセキュリティレベルを選択する」を今回は「セキュアブートと DMA保護」から、「セキュアブート」だけにします。前者のDMA保護は VT-d (ないしは IOMMU) で実現されていますが、Hyper-V上の仮想マシンではVT-d/IOMMUのエミュレーションは行われていないためです。

OKをおして保存後、ポリシーを確実に読み込ませるために、OSを再起動しておきます。
ドメイン環境でGPOをドメインコントローラから配信している場合は、再起動前に gpupdate /force を実行しておくといいかもしれません。
(GPOは更新されて即時に展開されるわけではなく、ある程度時間をかけて浸透していきます。クライアント側から gpupdate を実行することで、強制的に最新のポリシーをドメインコントローラに取りに行かせるわけです。もちろん、検証や数台のサーバからの実施ならばいいのですが、大量のサーバから gpupdate で即時取得を繰り返すのはドメインコントローラに負荷がかかるのでご注意ください。)
 
これで構成は完了です。


● Credential Guard の確認

では実際にメモリをダンプして Credentail を読み取れなくなったか確認してみましょう...、ではさすがに洒落にならないので、UIから動作確認します。

コマンドラインなどから msinfo32.exe を実行すると、システム情報というウィンドウが立ち上がります。左側のツリーでは標準選択されてている「システムの要約」をそのまま、右側の一覧をスクロールダウンしてくと、最後の方に Device Guard から始まる情報がいくつか記載されています。



まず、「Device Guard 仮想化ベースのセキュリティ」 が「実行中」になっているかがポイントだ。構成されていない場合はこれが「無効」になっており、構成されていても条件が整わなくて起動していない場合は「有効(停止中)」などになります。

次の、「Device Guard の必要セキュリティプロパティ」 が、仮想化ベースのセキュリティを実行させるにあたり必要となる機能で、その次の「Device Guard の利用可能なセキュリティプロパティ」が、実行している環境が提供できる機能の一覧になります。

つまり、必要側に書かれてる機能が利用可能側に記載がない場合、仮想化ベースのセキュリティは機能不足で稼働しないものになります。

構成済みの Device Guard セキュリティサービス が、GPOなどで構成したサービスです。ここでは Credential Guard が記載されていることが分かります。一方、その下の「実行中の Device Guard セキュリティサービス」が実際に稼働しているサービスを指します。こちらも Credential Guard の記載がある、つまりは Credential Guard が有効である事が分かります。

また、上から9行目ほどに「セキュアブート」がありますが、これが「有効」なものは、UEFIからはじまりブートローダー、OS、デバイスドライバと起動時から順に読み込まれていったモジュールがすべて有効な電子署名が施されている、改ざんされていないことを示します。


●うまく構成できていない例

たとえば Hyper-V は有効にしたものの、GPOをまだ設定していない場合には、以下のように「仮想化ベースのセキュリティ」 が単に「無効」と表示されます。




プラットフォームのセキュリティレベルを「セキュアブートとDMA保護」にしたにも関わらず、VT-d, IOMMU などがない場合は、以下のようになります。


必要なセキュリティプロパティに「DMA保護」 が入っていますが、その下の利用可能なセキュリティプロパティに「DMA保護」はありません。条件を満たさなかったためセキュリティサービスとして Credential Guard が表示されていないのが分かります。


また、VMware Fusion で構成を試してみた例がこちらです。Fusion でも nested VM を有効にして、Hyper-V をインストールしたのですが、Credential Guard が有効になってません。よくよく見るとDMA保護だけではなく、仮想化の基本サポート以降の機能がまったくありません。従って、Credential Guard は元より、仮想化ベースのセキュリティも実行されていません。


そもそも、VMware の仮想マシンではセキュアブートが使えません。
例の上から9行目のセキュアブートの項目を見ても「サポートされていません」になっているのが分かります。

セキュアブートが有効でない都言うことは、OS起動時のブートローダを改ざんしたり、間にプロセスを介入させることで仮想化ベースのセキュリティを有効化する前に悪意あるコードを混ぜ込むことが可能となってしまいます。いくらハイパーバイザーでセキュリティを保とうとしても、あく怒るコードの方が先にハイパーバーザーとして起動されてしまう恐れがある訳です。

そのためか、これまでみてきたように仮想化ベースのセキュリティでは、セキュアブートが「必要なプロパティ」として要求されています。

2017/02/09

vExpert 2017 受賞しました

vExpert 2017 受賞しました。どうもありがとうございます。

https://blogs.vmware.com/vmtn/2017/02/vexpert-2017-award-announcement.html

昨年1年を振り返るとやはりあまり活発な活動をしてたとは言えないので、今年はもう少し活動できれば、とか思っております。

2017/01/18

[TIPS] VMware Fusion で無差別モード時の認証を行わないようにする

VMware Fusion Professional の場合、環境設定にあるネットワークの設定にて、「無差別モードに入るには認証が必要です」のチェックを外すことで、仮想マシンが Promiscous Mode に入ろうとしたときに表示される認証を省くことができる。

ネットワークの設定
このパネルは Professional でのみ表示される

チェックを外すと、警告が出るので「続ける」を押す
この警告にもあるとおり、無差別モードを仮想マシンに許すと、その仮想ネットワーク内の通信や、ブリッジの場合はそのネットワークを流れる通信を確認することが可能になり、さらには偽装したパケットの送信もできるようになる。非常に危険なので通常は無差別モードを設定しようとした瞬間に認証がかかって、Fusion の利用者にあらかじめ確認を取るようになっている。

しかし、たとえば ESXi をFusion 上の仮想マシンとして実行する場合、「そのネットワークからくる ESXi 上の仮想マシンのMACアドレスのパケットを受け取る」「そのネットワークに ESXi 上の仮想マシンのパケットを送り出す」という操作、つまりは仮想マシン自身以外のMACアドレスのパケットの読み書きが必要になり、無差別モードが必須となる。

毎回確認されるのも面倒な場合は、このチェックを外すのもいいだろう。


なお、チェックを「外す」事で、/Library/Preferences/VMware Fusion 以下に、 promiscAuthorized という空のファイルが作成される。

promiscAuthorized ファイルが存在する
言い換えれば、この空のファイルを作れば無差別モード時の認証は行われなくなる。

このため、ネットワークの設定パネルのない、通常の VMware Fusion でも以下のコマンドで無差別モード時の認証をなくすことができる。

sudo touch "/Library/Preferences/VMware Fusion/promiscAuthorized"

パスが空白を含むので、ダブルクォートでくくるのを忘れないこと。