Apache Guacamole でVNCつないでみたの

2024/05/30 編集して `1.2.0` -> `1.5.5` にしました。

# Guacamoleって何？
https://guacamole.apache.org/
html5を使ってブラウザ経由でvnc、rdpなどを利用できるもののようです。 

vnc(virtual network computing) はデスクトップ環境にネットワーク越しからアクセスする仕組みです。

閉じたネットワークでGUI操作が必要な場合に、踏み台を作っておいて手元の端末からvncで接続すると便利なことがあります。
このとき普通は端末にvncのクライアントを用意すればよいですが、だいたいの場合はブラウザの方が手軽です。

今回は仮想マシン上で動作するvncサーバにブラウザからアクセスできるようにしてみます。

# 環境
- Fedora 40 (Server Edition)
- tomcat 9.0.83
- guacamole-server-1.5.5
- guacamole-client-1.5.5

また、この仮想マシンとは別にVNCで接続できるものを用意しておきます。

# 手順
公式の通り https://guacamole.apache.org/doc/gug/installing-guacamole.html

```shell:guacamole-server(guacd)
# 依存パッケージ。
sudo dnf install cairo-devel libjpeg-turbo-devel libpng-devel libuuid-devel libtool
# VNC
sudo dnf install libvncserver-devel pulseaudio-libs-devel 
# SSH
sudo dnf install libssh2-devel openssl-devel
sudo dnf install pango-devel
# RDP。1.5.5はfreerdp3.0に対応していないため2。
sudo dnf install freerdp2-devel
# 録画
sudo dnf install ffmpeg-free-devel

# 公式からダウンロード。
wget 'https://apache.org/dyn/closer.lua/guacamole/1.5.5/source/guacamole-server-1.5.5.tar.gz?action=download' -O guacamole-server.tar.gz
tar -xvf guacamole-server.tar.gz
cd guacamole-server-1.5.5/

# このオプションでsystemdの設定を作ってくれる。
./configure --with-systemd-dir=/usr/lib/systemd/system
make
sudo make install

# 今回は実施していない。後述。
# sudo ldconfig

sudo systemctl start guacd
sudo systemctl enable guacd
```

```shell:guacamole-client
sudo dnf install tomcat

# 今のバージョンではbuildに失敗する。
# sudo dnf install maven
# 
# wget 'https://apache.org/dyn/closer.lua/guacamole/1.5.5/source/guacamole-client-1.5.5.tar.gz?action=download' -O guacamole-client.tar.gz
# tar -xzf guacamole-client.tar.gz
# cd guacamole-client-1.5.5/
# 
# mvn package
# sudo cp guacamole/target/guacamole-1.5.5.war /var/lib/tomcat/webapps

wget 'https://apache.org/dyn/closer.lua/guacamole/1.5.5/binary/guacamole-1.5.5.war?action=download' -O guacamole-1.5.5.war
sudo cp guacamole-1.5.5.war /var/lib/tomcat/webapps

sudo systemctl restart tomcat
sudo systemctl enable tomcat

# firewallを設定。
sudo firewall-cmd --add-port 8080/tcp --permanent
sudo firewall-cmd --reload

# 次の手順のために作っておく。
sudo mkdir /etc/guacamole
```

この時点で `http://<hostname>:8080/guacamole-1.5.5` にアクセスするとログイン画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547524/2fe57105-a143-423a-1461-8c1a9625f307.png)

# ちょっと追加（2024/05）
以前は上の内容で問題なかったのですが、OSやライブラリが新しくなったからかうまく動かないところがあるので対応します。

### 待ち受けるアドレスをIPv4に変更
IPv6で待ち受けるとguacdにクライアントが接続できません。

```shell:IPv6での待ち受け 例
$ sudo lsof -i:4822 -Pn
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
guacd   47812 daemon    4u  IPv6 103440      0t0  TCP [::1]:4822 (LISTEN)
```
IPv4のループバックアドレスを指定します。

```shell:待ち受けるアドレスをIPv4に変更
sudo vi /etc/guacamole/guacd.conf

# 以下を入力して保存。
[server]
bind_host = 127.0.0.1
```
### ライブラリパスの追加
上の手順ではライブラリファイルが/usr/local/libに作られますが、現在のFedoraはldconfigでここを使わないため、ライブラリを見つけることができずホストへの接続が失敗します。
（確認できていませんが、昔は/usr/local/libも使っていたのかも。）

```shell:接続失敗時のログ 例
Support for protocol "vnc" is not installed
```

いくつか方法は考えられますが、今回はsystemdのユニットファイルに環境変数を追加してみます。
```shell:ライブラリパスの追加
sudo systemctl edit --full guacd.service

# エディタが起動するので、Environmentを[Service]に追記。
[Service]
User=daemon
ExecStart=/usr/local/sbin/guacd -f
Restart=on-abnormal
Environment=LD_LIBRARY_PATH=/usr/local/lib
```
### 実行ユーザの変更、ホームディレクトリの設定
FreeRDPの2.0.0以降はユーザのホームディレクトリに書き込みを行うようです。インストール時に作成されたsystemdのユニットではdaemonユーザで実行するためホームディレクトリに書き込みができず、どうやらこれが原因でRDPの接続に失敗します（https://issues.apache.org/jira/browse/GUACAMOLE-927）。

```shell:connection選択時のログ 例
FreeRDP initialization may fail: The current user's home directory ("/sbin") is not writable, but FreeRDP generally requires a writable home directory for storage of configuration files and certificates.
```

今回はユーザguacdを作り、ホームを/var/local/guacamoleにします。
```shell:実行ユーザの変更、ホームディレクトリの設定
sudo useradd -r -s /sbin/nologin -d /var/local/guacamole guacd
sudo mkdir -m 700 /var/local/guacamole
sudo chown guacd:guacd /var/local/guacamole

sudo systemctl edit --full guacd
# エディタが起動するので、[Service]のUserを書き換え。
[Service]
User=guacd
ExecStart=/usr/local/sbin/guacd -f
Restart=on-abnormal
Environment=LD_LIBRARY_PATH=/usr/local/lib
```

guacdサービスは再起動しておきます。

```
sudo systemctl restart guacd
```

# ユーザを作る。
ユーザは `/etc/guacamole/user-mapping.xml` に書きます。

```xml:user-mapping.xml
<user-mapping>
  <!-- login 画面で打つ。 -->
  <authorize username="test" password="password">
    <connection name="hostX">
      <protocol>vnc</protocol>
      <!-- 本当の host, port, password にする -->
      <param name="hostname">192.168.0.1</param>
      <param name="port">5901</param>
      <param name="password">password</param>
      <!-- 画面キャプチャ用に入れておく -->
      <param name="recording-path">/tmp/hostX</param>
      <param name="create-recording-path">true</param>
    </connection>
  </authorize>
</user-mapping>
```

# 接続する。
ユーザ名とパスワードを入力すると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547524/7acfb447-4a83-d02f-8d59-708ffc632c15.png)


クリップボードは `Ctrl+Shift+Alt` で出てくるメニューの、フォームと同期しているようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547524/b849d53b-1289-2c88-da10-04f616addefe.png)

## RDP
RDPも設定してみます。
```xml:user-mapping.xml 追記
  <authorize username="test" password="password">
    <!-- authorizeの中に追記 -->
    <connection name="hostY">
      <protocol>rdp</protocol>
      <!-- 本当の host, portにする -->
      <param name="hostname">192.168.0.1</param>
      <param name="port">3389</param>
      <param name="ignore-cert">true</param>
    </connection>
  </authorize>
```
二つ目のConnectionを追加すると、ログイン後にConnectionを選べるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547524/f8be433f-8669-af72-43a2-4ef1f7731634.png)

ただ、RDPについては **残念ながらここまで** にします。今回RDPの接続先にGNOME Remote Desktopを使うつもりだったのですが、どうやらGuacamole 1.5.5では接続できないようです（1.6.0で対応するらしい…？ https://issues.apache.org/jira/browse/GUACAMOLE-377 ）。

## SSH
SSHも設定してみます。
```xml:user-mapping.xml 追記
  <authorize username="test" password="password">
    <!-- authorizeの中に追記 -->
    <connection name="hostZ">
      <protocol>ssh</protocol>
      <!-- 本当の host, portにする -->
      <param name="hostname">192.168.0.1</param>
      <param name="port">22</param>
    </connection>
  </authorize>
```
usernameとpasswordを省略しているので、connectionを選択するとuserとpasswordを入力したのちログインできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547524/5f135472-20d6-96fd-a7b8-d506eada3bbb.png)


## 録画
user-mappingに書いたので、画面のレコードも可能です。

```shell
$ sudo guacenc /tmp/hostX/recording
guacenc: INFO: Guacamole video encoder (guacenc) version 1.5.5
guacenc: INFO: 1 input file(s) provided.
guacenc: INFO: Video will be encoded at 640x480 and 2000000 bps.
guacenc: INFO: Encoding "/tmp/hostX/recording" to "/tmp/hostX/recording.m4v" ...
guacenc: INFO: All files encoded successfully.

$ sudo file /tmp/hostX/recording.m4v
/tmp/hostX/recording.m4v: ISO Media, Apple iTunes Video (.M4V) Video
```
楽しいです。

# その他
- 1.0.0の時はWindows RDPで苦労してました。https://qiita.com/sandopan65/items/1194078666bbd09eb2fe
- 最初に書いたときはソースからインストールしたかったのですが、今なら素直にパッケージで入れた方が良いなと思います（2024/05）。