zaki work log

作業ログやら生活ログやらなんやら

Apache Guacamoleを使ってwebブラウザでSSH接続をお試し (Docker版)

ネットワークの制限でwebアクセス(HTTP/HTTPS)しか許可されておらず、SSHアクセスが使えないような環境でリモートのLinuxサーバーのシェルへアクセスしたい場合、Apache Guacamoleを使うことでwebブラウザの画面でSSHログインを行う。(webページ内にSSHアクセスしたリモートサーバーのシェルが画面表示される)

接続イメージは以下の通り。

本エントリではとりあえずSSH接続のみ。
ただしGuacamoleはSSH以外にもVNCやRDPなどいくつかのリモート接続用のプロトコルに対応している。
Kubernetesもあるのが気になる。

Guacamoleのデプロイ

サーバーへ直接インストールする方式と、Docker Hubで公開されているDockerコンテナ版のGuacamoleを使う方法がある。 本エントリではDockerイメージを使うパターンで構築。

guacamole.apache.org

Guacamoleは、以下の3つのコンポーネント(説明は意訳)で動作し、それぞれコンテナを実行する。(DBだけ外部とかできるけど、とりあえず全部Dockerで)

ちなみにGuacamoleのコンテナイメージは、latestタグはデイリーで更新されているため、最新安定版のバージョンのタグを指定した方が良さそう(おそらくCIで自動ビルドされてるっぽい)。
現時点で1.4.0が最新。

docker networkの作成

公式ドキュメントだと--link使ってコンテナ間通信する手順になってるけどさすがにもうこのオプションを使うのも微妙なので、コンテナ間通信を行うためのDocekr Networkを作成。

docker network create guacamole-network

以降のコンテナデプロイは、このDocker Networkを--networkで指定。

guacdの起動

docker run --name guacd -d --network guacamole-network guacamole/guacd:1.4.0

MySQL

MySQLPostgreSQLが使用できるが、今回はMySQLを使用。

初期化ファイル作成

まずは事前にguacamole/guacamoleコンテナ内のスクリプトを使って、DBの初期化スクリプトを作成。

docker run --rm guacamole/guacamole:1.4.0 /opt/guacamole/bin/initdb.sh --mysql > initdb.sql

DBの起動

MySQLコンテナは、起動時に/docker-entrypoint-initdb.dディレクトリ以下の*.sqlファイルでDBを初期化するので、↑で作成した初期化スクリプトをバインドマウントして起動する。
また、DBのデータ(/var/lib/mysql)をボリュームマウントする。

docker run --name guacamole_db \
  -d \
  -e MYSQL_DATABASE=guacamole_db \
  -e MYSQL_USER=guacamole_user \
  -e MYSQL_PASSWORD=guacamole_passwd \
  -e MYSQL_RANDOM_ROOT_PASSWORD=yes \
  -v $PWD:/docker-entrypoint-initdb.d \
  -v guacamole_db:/var/lib/mysql \
  --network guacamole-network \
  mysql

guacamole

アプリケーションサーバーを起動する。
GUACD_HOSTNAMEにguacdコンテナのコンテナ名、MYSQL_HOSTNAMEmysqlコンテナのコンテナ名を指定する。
DBの接続情報はmysql起動時に指定したものと同じものを指定する。

また、このコンテナにwebブラウザでアクセスするので、ポート番号をpublishする。

docker run --name guacamole \
  -d \
  -e GUACD_HOSTNAME=guacd \
  -e MYSQL_HOSTNAME=guacamole_db \
  -e MYSQL_DATABASE=guacamole_db \
  -e MYSQL_USER=guacamole_user \
  -e MYSQL_PASSWORD=guacamole_passwd \
  --network guacamole-network \
  -p 8080:8080 \
  guacamole/guacamole:1.4.0

デプロイはこれで完了。

webアクセスと接続設定

http://<docker host>:8080/guacamole にアクセス。(ドキュメントルートでなくパス指定があるので注意)

認証

初期値としてユーザー名・パスワードともにguacadminがセットされている(たぶんDBの初期化ファイル作成の時点にこれになってる)のでこれでログイン。

Verifying the Guacamole install

adminのパスワードを変更するには、ログインして右上にあるメニューから「設定」を選択。

ユーザ設定メニューにパスワード変更のフィールドがあるので現在のパスワードと新しいパスワードを入力する。

接続先設定

接続先の設定は、メニューの「接続」→「接続の追加」でサーバー設定を行う。 SSH接続のために最低限必要なのは以下の通り。

  • 接続の編集
    • 名前: 設定の名前。わかりやすいのを入力しておく
    • プロトコル: SSH
  • パラメータ
    • ネットワーク
      • ホスト名: 接続先SSHサーバーのアドレス

これだけ入力して「保存」、ホームに戻ると接続情報に設定が追加されるのでマウスクリックすれば、ユーザー名とパスワードを聞かれてパスワード認証でSSH接続できる。

認証パラメータの「ユーザ名」「パスワード」を事前に入力しておけば、接続時の認証も省略できる。

公開鍵認証設定

公開鍵認証の設定は、パラメータセクションに最低限以下を入力すればOK。

ただし、秘密鍵の登録はOpenSSH形式とドキュメントに記載があるが、実際にはPEM形式である必要がある。

The private key must be in OpenSSH format, as would be generated by the OpenSSH ssh-keygen utility.

https://guacamole.apache.org/doc/gug/configuring-guacamole.html#ssh-authentication

現バージョンのOpenSSHのssh-keygenでキーペア作成すると、デフォルトではOpenSSH形式(ファイル先頭が「-----BEGIN OPENSSH PRIVATE KEY-----」で始まる)になっているが、この形式だと公開鍵認証が上手くいかない。
PEM形式(ファイル先頭が「-----BEGIN RSA PRIVATE KEY-----」で始まる)のキーペアを作成するには、ssh-keygen-mオプションで形式を指定する。

$ ssh-keygen -m PEM ...

既存のOpenSSH形式の鍵をPEM形式に変換するには以下。この場合元のファイルが更新されるので、必要があれば事前にコピーしておく。

$ ssh-keygen -p -m PEM -f ~/.ssh/id_rsa

秘密鍵の入力フィールドに、秘密鍵ファイルの中身を全て貼り付けて保存する。

これでホームに戻り、接続先を選択すれば、公開鍵認証でSSH接続できる。

環境

  • ホストOS: Fedora 35
  • Docker: 20.10
  • Guacamole: 1.4.0

補足

Guacamoleのイメージはamd64版しかないので、arm64ではそのままでは動かせない。

デフォルトだと日本語入出力できないので要調査。
多分コンテナ内のロケールがどうとか、、、と思う。
ロケールの追加と設定は関係なく(ja_JP.UTF-8とか入れても変化無し)、原因は日本語フォントでした。あとで別途まとめる。

まとめました。

zaki-hmkc.hatenablog.com

あと今回はSSHサーバーとGuacamoleを立てたDockerホストを別にしてるが、ここは同じホストでも疎通があるなら問題ない。はず。