オフィシャルサイト: xrdp.org, 日本xrdpユーザ会, GitHub:neutrinolabs/xrdp

xrdp

RHEL/CentOS 7 の VNCサーバは、VNCのページで検証したどの方式でもどうもあまり具合がよろしくない。特に非力なマシンで顕著な気がするのだが、認証の後いくら待ってもデスクトップが表示されず何度か接続しなおさないときちんとつながらないケースが散見される。CentOS 6 では、6.8 になった途端に、これまで実績のある実装方法で使っていてもデスクトップセッションが突然終了する不具合にしばしば悩まされる。そこで、代替手段として使ってみたのが、Xvnc などをバックエンドとして Microsoftリモートデスクトッププロトコルでラップする xrdp。これがなかなか調子がよく、まんまリモートデスクトップと同様に、ログアウトすれば Xセッションは終了するしクライアントをただ閉じればセッションは継続するというのも具合がよい。WindowsマシンへのVNCクライアントのインストールが要らないのも利点といえば利点だ。

Table of Contents

VNCサーバのインストール

ここでは Xvnc をバックエンドにする前提に立つので、VNCサーバがインストールされていなければならない。RHEL/CentOS 6 及び 7 では tigervnc-server 標準パッケージで提供されているのでインストールしておく。xrdp のバックエンドとしての用途だけなら設定は特に必要ない。

xrdpのインストール

RHEL/CentOS 7 の場合

EPELレポジトリの Yum Repo 定義をインストールする。例えば、

root# rpm -ivh \
 http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

そして xrdp をインストール。

root# yum install xrdp 

現在のところ、xrdp-0.9.x がインストールされる。

接続時、sesman がログオン対象ユーザの ~/.vnc/ ディレクトリに一時的な VNCパスワードファイルを作るので、ディレクトリ構造を作るために、一度だけ、目的のユーザで Xvnc を開始してすぐ終了させる。その際に VNCパスワードも入力させられるが、xrdp では .vnc/passwd ファイルは使われないので、気になるなら後で削除してもいい。

hoge$ vncserver :51
hoge$ vncserver -kill :51

X (gdm) の XDMCP を Enable する必要はない。ただしひとつだけ修正が必要。この xrdpパッケージ付属の /etc/xrdp/startwm.sh は RedHat系OSの LANG 環境変数取得に対応していないので、接続した時に英語環境になってしまう。そこで、startwm.sh にルーティンを足してやる。 xrdp のバージョンやパッケージのビルド方法によっては /usr/libexec/xrdp の場合もある。

root# patch -d /etc/xrdp < startwm.sh.diff

あとはお決まりの

root# systemctl start xrdp.service
root# systemctl enable xrdp.service 

以上! 終わり。接続の際は、リモートデスクトップの 画面 オプションの 画面の色 を 24ビット以下にしないとエラーとなりつながらない。

RHEL/CentOS 6の場合

RHEL/CentOS 7 と同様にインストールすることも可能ではあるが、それでインストールされるのは xrdp-0.6.x。まだいろいろと未熟なバージョンで、後継の備えるキーボード配列自動検出機能がうまく働いてくれない。そこで、安定版の最新ソースから RPMパッケージをビルドしてインストールする。ありがたいことに、コンパイル/インストールはもとより、ビルドに必要なツールの取得/インストールまで自動でやってくれるシェルスクリプト X11RDP-RH-Matic というものが提供されているのでそれを利用する。検証した時点では xrdp-0.9.0 がインストールできた。

もともとは、APTパッケージマネージャを使用するディストリビューション用に Kevin Cave さんの作った X11RDP-o-Matic というものが存在した。それを元にして、日本の meta さんが RPMパッケージマネージャ用にしつらえたのが X11RDP-RH-Matic というわけらしい。日本xrdpユーザ会 の発起人が meta さん。
与太話だが、X-o-Matic というメカ的なものが世の中にはたくさんある。筆者には Iptables の Patch-o-Matic がすぐに思い当たった。XX-o-なんとか という語感のメカ用語の発明者は、かの有名なトンデモSF Hitchhiker's Guide to the Galaxy の作者 Douglas Adams (1952-2001) ではないかと自分は勝手に信じ込んでいる。電話帳くらい厚みのある The Ultimate版ペーパーバックスを久しぶりにパラパラめくっただけでも "Sub-Etha Sens-O-Matic" を筆頭に、"KIll-O-Zap gun"、"Titan-O-Hold door"、"Dine-O-Charge credit card" などその種の造語がぽろぽろ目に止まる。同作家のビデオゲーム Starship Titahic には "Succ-U-Bus" というバキューム式輸送装置が出てきたのも思い出す。Succ-U-Bus吸い込み口の「声」は Douglas Adams 本人が演っていた。

下準備

EPELの EL6用 Yum Repo定義ファイルをインストールする。例えば、

root# rpm -ivh \
 http://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm

X11RDP-RH-Matic は一般ユーザ(ここでは hoge だとして話を進める) で行うことにするが、Matic は必要に応じて sudo を介してroot権限を取得してコマンドを発行する。途中でパスワードを入力しなくて済むように sudoers を設定しておく。sudoに関しては別ページで詳しく書いた。最低限必要な定義だけ挙げると、

User_Alias  ADMINS   = hoge
Defaults:ADMINS    !requiretty, !env_reset, setenv, !noexec
ADMINS     ALL = (ALL)    NOPASSWD: ALL

それから、やってもやらなくてもよいが、rpmdev-setuptree コマンドを使ってビルドツリーが作られる時に、思い通りのパスで作られるように、ホームディレクトリ直下に .rpmmacros ファイルを予め作っておくとよい。内容はこんな具合。

%packager	Hoge Net
%_topdir	%(echo $HOME)/rpmbuild
%_rpmdir	%{_topdir}/RPMS
%_srcrpmdir	%{_topdir}/SRPMS
%_specdir	%{_topdir}/SPECS
%_sourcedir	%{_topdir}/SOURCES
%_builddir	%{_topdir}/BUILD

X11RDP-RH-Matic の実行

まず、GitHub から X11RDP-RH-Matic レポジトリをクローンする。あらかじめ、git (標準パッケージあり) がインストールしてある必要がある。

hoge$ cd ~
hoge$ mkdir git && cd git
hoge$ git clone --depth 1 -b master https://github.com/metalefty/X11RDP-RH-Matic.git

X11RDP-RH-Matic を実行する。 好みの問題だが、どのパッケージをインストールするかは掌握しておきたいので、Matic はビルド止まりとしておき、インストールは別途行う。xrdp のバックエンドには Xvnc を使用する前提なので、xrdp独自のバックエンドはコンパイルしない。専用バックエンドをコンパイルすると10数分余計な時間が掛かる。そうでなければコンパイルは数分で終わる。オプションの意味は `X11RDP-RH-Matic --help' で分かる。

hoge$ cd X11RDP-RH-Matic
hoge$ ./X11RDP-RH-Matic.sh --noinstall --with-xorgxrdp --nox11rdp --cleanup 

インストールする。rpm コマンドを直接使ってもいいが、必要な依存パッケージがあれば牽いてこれるように念のため `yum localinstall' を利用する。xorgドライバは Xvncバックエンドで使う限り不要だが、数kb なのでインストールする。

hoge$ su -
root# cd ~hoge/rpmbuild/RPM/x86_64
root# yum localinstall xrdp-0.9.*.rpm xorg-x11-drv-xrdp-0.9.*.rpm

なお、他のマシンにもインストールする場合、ビルドしたのと同じOSリリースなら、ここで作った rpm パッケージを持って行ってインストールするだけでいい。

調整

EL7 の時と同様に、RedHat系のLANG変数取得ルーティンを startwm.sh に加えてやる。 /etc/xrdp にない場合は /usr/libexec/xrdp をあたってみよう。

root# patch -d /etc/xrdp < startwm.sh.diff

Xvncsesman への delay 追加と、接続時にいちいちドロップダウンからセッションタイプを選ばなくていいようにセッションタイプ表示順を変更。

root# patch -d /etc/xrdp < xrdp.ini.diff

接続時、sesman がログオン対象ユーザの ~/.vnc/ ディレクトリに一時的な VNCパスワードファイルを作るので、ディレクトリ構造を作るために一度、目的のユーザで Xvnc を一度開始してすぐ終了させてやる。その際に VNCパスワードも入力させられるが、xrdp では .vnc/passwd ファイルは使われないので、気になるなら後で削除してもいい。

hoge$ vncserver :51
hoge$ vncserver -kill :51

そして、お決まりの

root# chkconfig xrdp on

xorgドライバが X にロードされるよう、リブートが許される状況なら念のためマシンをリブートする。Xvncバックエンドの場合、実際はドライバは使用されないので、リブートせずにそのまま利用を始めても構わない。

接続

リモートデスクトップ (mstsc.exe) でサーバへ接続する際に、まず 画面 オプションの 画面の色 を 24ビット以下にしなければならない。xrdpのログイングリーターが出たら、session ドロップダウンから sesman-Xvnc を選択して接続する。上記で設定ファイルをいじったのでデフォルトで選択されている。/etc/xrdp/sesman.ini[Xvnc] ブロックの定義に従い、xrdpセッションマネージャによって Xvnc プロセスがバックグラウンドで起動される。Session manager でも接続可能だが、ローカル(仮想マシンならVMコンソール) で既にログインしている時しかつながらないのであまり利用する機会はない。ユーザ/パスワードは、基本的には PAM(pam.d/xrdp-sesman) を介して制御されている。

rootでのログインを禁止する

本来、X のデスクトップ環境は root でログインするようには作られていない。一部のグラフィカルアプリケーションは誤動作を起こすこともある。自分だけの使うマシンならまだいいが、rootでログインしたままログアウトもせずに放置するグウタラはどこにでもいるわけで、許しておくとろくなことにはならない。ローカルでの GNOME ログインや VNC についてのやり方は よろづ環境設定 に書いたが、xrdpgdm を通らないのでそのままやっても通用しない。代わって /etc/pam.d/xrdp-sesman ファイルをいじる。既定の "auth include password-auth" (xrdpのバージョンやビルドによっては system-auth) という行の手前に pam_succeed_if.so モジュールを入れる。こんな感じだ。変更は即反映され、xrdpサービスのリスタートも不要だ。

auth       required     pam_succeed_if.so user != root quiet
auth       include      password-auth
account    include      password-auth
password   include      password-auth
session    include      password-auth

SSL証明書の整備

VPNも通さずにインターネット越しにリモートデスクトップを使う人などおるまい。RDPトラフィックを暗号化する意義がどこにあるのか筆者はかねがね疑問に思っている。よって、当工程は趣味とこだわりだけの仕業であって、やらなくても困ることはない。ただ、接続時の警告が気持ち悪いという几帳面な人は、やっておくと気分が晴れるだろう。ユーザ会のサイトにも一通りはやり方が載っている。

xrdpサーバの秘密鍵と自己署名済み公開鍵を作る。一般ユーザ(ここでは例によって"hoge") で任意の作業ディレクトリ (仮に ~/ssl-work とする) を作り、openssl_xrdp.cnf ファイルを置く。CentOS 7 の openssl.cnf を元にしているが、RHEL/CentOS 6 でも共通して使える。どこをいじったか分かるように diff も採っておいた。openssl_xrdp.cnf の冒頭にコメントしたように [req_distinguished_name] セクションの情報を自分の環境に合わせて書き換えてから、ユーザ hoge で、

$ cd ~/ssl-work
$ openssl req -config openssl_xrdp.cnf -x509 -newkey rsa -keyout key.pem \
 -out cert.pem -days 3650

自己署名済みパブリックキー cert.pem の内容を確かめたければ、

$ openssl x509 -text -noout -in cert.pem

xrdpの設定ディレクトリに証明書をコピーする。

# cp cert.pem key.pem /etc/xrdp
# cd /etc/xrdp
# chmod 600 key.pem
# chmod 644 cert.pem

xrdp.ini の以下の箇所を修正する。

そして `service xrdp restart' でデーモンを再起動。

証明書を投入して初めての接続時は、RDPの接続オプションの 詳細 タブで 警告メッセージを表示する にしておき、「リモートコンピュータのIDを識別できない」警告ダイアログが出たところで待ってましたとばかりに 証明書を表示 を押し、証明書を 信頼された証明機関ローカルコンピュータ 物理ストアにインポートする。これで以後、警告は正式にストップする。コネクションがきちんと暗号化されているかどうかは、クライアントのレジストリキー HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\ にある REG_DWORD値 EventLogging (既定値 0x0) を 0x7 に変更してからリモートデスクトップ接続をしなおせば、イベントログのシステムログにソース Schannel のイベントとして記録される。暗号化が成立していれば、

SSL クライアント ハンドシェイクが完了しました。ネゴシエーション暗号化パラメータ:
 
   プロトコル: TLS (SSL 3.1)
   CipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA
   Exchange の強度: 2048

といったようなログが記録されるはずだ。確認が済んだら EventLogging 値を元に戻しておくのを忘れずに。