Apache Guacamoleを使ってWindowsServerにセキュアにログイン


f:id:cloudfish:20200417102427p:plain:w200
 諸事情により社内で複数担当者が共通ユーザーでWindowsServerにアクセスして実施している業務がありました。こうした運用はよくあるのではないでしょうか。当然ながら共通ユーザーでアクセスすることに問題があることは認識していますが、アクセスについては社内からのみとアクセス制限を行っていたため現状では特に対応を行っていませんでした。
 しかしながら、昨今の急激なリモートワークへの移行に伴って、自宅からの接続も許可する必要が出てきましたが、現状オフィスへのVPN接続環境はないため、このままだと対象のWindowsマシンのセキュリティグループ設定でRDP接続の接続元をフル解放するか都度作業者のIPを許可する必要に迫られました。とはいえどちらの方法もあまり現実的ではないので、別な手段を探していたところ、GuacamoleというブラウザからRDP接続ができるツールを見つけたので、これをRDP接続するための踏み台サーバとして利用することで共通ユーザー問題を解決できると考え導入を進めています。今回はこれについて紹介したいと思います。

Apache Guacamoleとは

Guacamole(ワカモレもしくはガカモレと読むそうです)とはクライアントレスなリモートデスクトップゲートウェイです。また、接続クライアントに特別なプラグインやソフトウェアなどをインストールせずに、ブラウザからVNC、RDP、SSH接続などが可能となっています。

Guacamoleの主な機能

主に以下のような機能が提供されており、作業端末やサーバーへのアクセスにおいて、セキュリティの強化や問題が発生した際のトレースが行いやすくなっています。また、今回Guacamoleを使う大きな理由の一つとして、管理者側で接続可能な端末を登録して誰に接続させるかをコントロールできる機能があります。そのため利用者側は接続情報(ユーザー、パスワード)を意識する必要がありません。言い換えると利用者側はユーザー、パスワードを知ることができないことになります。

  • ブラウザからVNC、RDP、SSH、SFTP、TELNET接続が可能
  • DBでの認証、LDAPOpenIDなどで認証やMFA(多要素認証)が利用可能
  • 端末へのアクセスログが保存されているため、いつ誰がどの端末へアクセスしたのかトレースが可能
  • 管理者と一般ユーザーの権限分離が可能
  • 画面操作内容の録画

Gucamoleの構成

詳細は公式ドキュメントを確認してもらうとして、主に二つのコンポーネントで構成されています。

guacamole

ユーザーからのアクセスを受け付けるWebアプリケーション

guacd

RDP、VNCSSH接続などを行うコンポーネント
guacamole.apache.org

現状の課題と解決策

本来であればWindowsをAD運用することが一番いいのですが、現状すぐにはその対応はできないというのが前提にあります。

1.ユーザー管理

現状では、ユーザー管理ができていないため、SimpleADを使ってGucamoleのユーザー管理を行います。もい担当者が異動や退職となって業務を外れた場合は、対象ユーザーを削除します。削除されたユーザーはGucamoleにログインできないため、業務用のWindowsServerへもログインでき無くなります。

2.WindowsServerへ共通ユーザーでログイン

WindowsServerへの接続情報はGucamoleだけが保持する事になるので、利用者が知ることはできません。そのため、担当者の退職などによりパスワードの再設定、再配布などの対応が不要になります。

3.いつ誰がアクセスしたか分からない

Gucamole側でいつ誰がどの端末にアクセスしたかログを保持しているため、Windows側は共通ユーザーでログインされていたとしてもGucamole側のログを確認することでトレースが可能となります。

4.社外からもアクセスする必要がある(オフィスにVPN環境がないためIP制限できない)

WindowsへのアクセスはGucamoleサーバからのみアクセス可能として、Gucamoleサーバーに対してはどこからでもログイン可能とする。認証方法をSImpleAD+MFAとすることでログイン時のセキュリティ向上を行います。

構成

実際の構成はVPCが別れていたりするのでもう少し複雑にはなるのですが、ここではシンプルな構成とします。以下のようにGucamoleサーバーを踏み台として配置することでWindowsServerをPrivateSubnetに配置することが可能になります。
f:id:cloudfish:20200420152133p:plain:w300

構築手順

Gucamoleのインストール方法については、サーバーにwarファイルを展開して直接インストールする方法もありますが、Dockerでインストールする方が簡単なので今回はこちらの方法で構築を行います。また、有償にはなりますがMarketPlaceでイメージ(Guacamole Bastion Host)が公開されているものもありますので興味のある方はそちらもご覧ください。

SimpleADの構築

ユーザー管理用のSimpleADを構築します。SimpleADの構築方法については以下のブログを参照してください。
以下の設定で構築してください。ドメイン名は適当な名称を設定してください。

DirectoryType small
ドメイン guacamole.local
VPC Gucamoleを構築するVPC
Subnet 上記のVPCのPrivateSubnet

ユーザーの作成については、WorkSpacesの設定から追加が可能なのでGucamoleのログイン用ユーザーを作成しておいてください。こちらも以下のブログに追加方法がありますので参照してください。間違ってWorkspacesの立ち上げまではしないようにしてください。
Simple ADを利用したWorkSpaces構築手順 – サーバーワークスエンジニアブログ

ELBの準備

ELBはApplicationLoadBalancerを利用します。こちらも詳細は他のブログを参照してください。また、カスタムドメインを使用する場合は、必要に応じてACMなり自己証明書なりを準備しておいてください。

TargeteGroupの設定
ターゲットグループ名 任意
ターゲットの種類 インスタンス
プロトコル HTTP
ポート 8080
VPC Gucamoleを構築するVPC

■ヘルスチェック

プロトコル HTTP
パス /gucamole
ALBの設定
ELBのタイプ Application Load Balancer
VPC Gucamoleを構築するVPCを設定
Subnet 上記のVPCのPublicSubnet

■リスナー設定

Protocol Port 転送先TG
HTTPS 443 上記ターゲーットグループ
HTTP 8080 上記ターゲーットグループ

※証明書を準備していない場合はHTTPのみ設定してください。

Amazon Linuxの準備

起動

Gucamole用のEC2を作成します。Amazon Linuxで構築します。

AMI: 最新のAmazonLinux2
インスタンスタイプ: t3.micro
VPC: Gucamoleを構築するVPCを設定
Subnet: 上記のVPCのPublicSubnet
SecurityGroup: 8080がALBから疎通可能となるよう設定

起動が完了したら作成したターゲットグループにアタッチしてください。なお、この時点ではhealthyになりません。

Dockerインストール

次にDockerをインストールします。
以下のコマンドを実行してdockerとdocker-composeをインストールします。

dockerのインストール

sudo yum install -y docker
sudo service docker start
sudo usermod -a -G docker ec2-user
sudo systemctl enable docker

docker-composeのインストール

sudo curl -L https://github.com/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

gucamoleのイメージ構築

guacamole(gucamole-client)のイメージは公式からDocker Hubでバージョン1.1.0提供されていますが、1.1.0にはMFAの設定が組み込まれていません。そのため、githubから最新のコードをチェックアウトして自分でイメージのビルドを行います。

以下のコマンドを実行してイメージを作成します。
ビルドにはかなりの時間がかかりました。

git clone https://github.com/apache/guacamole-client.git
cd guacamole-client
docker build -t guacamole_120 .

docker-composeの作成

Dockerで構築する場合、以下の3つのコンテナが必要となります。

  • guacamole
  • guacd
  • mysql(or postresql)

以下の内容でdocker-compos.yamlを作成します。
$SIMPLE_AD_IPには作成したSimpleADのIPを設定します。
LDAP_USER_BASE_DN、LDAP_CONFIG_BASE_DNのDCにはSimpleAD作成時に設定したドメインを設定してください。

version: "3"

services:
  guacd:
    image: guacamole/guacd:latest
    expose:
    - "4822"
    environment:
    - GUACD_LOG_LEVEL=debug
  guacamole:
    image: guacamole_120
    links:
      - guacd:guacd
    ports:
    - "8080:8080"
    environment:
    - GUACD_HOSTNAME=guacd
    - LDAP_HOSTNAME=$SIMPLE_AD_IP
    - LDAP_PORT=389
    - LDAP_ENCRYPTION_METHOD=none
    - LDAP_USER_BASE_DN=CN=Users,DC=guacamole,DC=local
    - LDAP_USERNAME_ATTRIBUTE=CN
    - LDAP_CONFIG_BASE_DN=CN=Users,DC=guacamole,DC=local
    - TOTP_ENABLED=true
    - MYSQL_HOSTNAME=mysql
    - MYSQL_DATABASE=guacamole
    - MYSQL_USER=guacamole
    - MYSQL_PASSWORD=guacamole

  mysql:
    image: mysql/mysql-server:5.7
    volumes:
    - "./mysql/data:/var/lib/mysql"
    - "./mysql/init:/docker-entrypoint-initdb.d"
    environment:
    - MYSQL_DATABASE=guacamole
    - MYSQL_USER=guacamole
    - MYSQL_PASSWORD=guacamole

ディレクトリの作成

docker-compose.yamlファイルと同じ階層に以下のディレクトリを作成します。

mkdir -p mysql/data
mkdir -p mysql/init
tree -d mysql/
mysql/
├── data
└── init

初期データ作成

以下のコマンドで初期化用のスクリプトを作成します。

docker run --rm guacamole_120 /opt/guacamole/bin/initdb.sh --mysql > mysql/init/initdb.sql

起動

docker-compose up -d

Gucamoleの使い方

接続用のWindowsServerについては事前に用意し、Gucamoleサーバーからポート3389で疎通できるようにしておいてください。

ログイン画面にアクセス

カスタムドメインを設定していなければ、以下のいずれかのURLでアクセスしてください。
https://ELB_DNS/guacamole/
http://ELB_DNS:8080/guacamole/
正常に起動されていれば以下のようなログイン画面が表示されます。もし表示されていなければ、ログを確認してみてください。

以下のユーザー、パスワードでログインできます。
ログインユーザー: guacadmin
パスワード: guacadmin
f:id:cloudfish:20200420190016p:plain:w200

MFA設定

MFAが有効になっていますのでGoogle Authenticatorなどで設定してください。
f:id:cloudfish:20200420194326p:plain:w200

初期画面

以下のような初期画面が表示されます。
f:id:cloudfish:20200420200648p:plain

接続設定の追加

右上のユーザー名から「設定」を選択し、「接続」タブを開いて「接続の追加」をクリックします。
以下の通り入力を行い保存します。
f:id:cloudfish:20200421090135p:plain

接続情報の選択

右上のユーザー名からホーム画面に戻ると、先ほど登録した接続設定が表示されていますので、登録した接続情報を選択します。
f:id:cloudfish:20200421091255p:plain

RDP接続

以下のようにリモートデスクトップが開きます。
f:id:cloudfish:20200421092011p:plain

RDPの切断

切断するにはMacの場合は、「Ctrl + Shift + Option」でサイドバーが表示されますので「切断」を選択してください。
f:id:cloudfish:20200421092248p:plain:w300

他のユーザーが利用中の場合

また、別ユーザーが接続中の場合、以下のように利用中であることが分かります。ただし、日本語表記はバグのためが表示されないため、英語表記とする必要があります。日本語だと他にも微妙な動作があったりもしたので基本は英語表記の方がいいかもしれません。
なお、接続設定において最大接続数を1とすると他のユーザーが利用中の場合は接続できないような制限をかけることが可能です。
f:id:cloudfish:20200421094831p:plain

MFAの再設定

多要素認証の機能を利用するので、スマホの故障や紛失による再設定をどのように対応するのか調べてみました。現状では管理者がUIから設定する方法はなさそうです。
そのため、DBを直接いじる必要があるようです。

以下のSQLで対象のユーザーIDを特定し

select 
    gu.user_id 
from 
    guacamole_entity ge inner join guacamole_user gu 
on ge.entity_id = gu.entity_id 
where ge.name='guacadmin'

対象ユーザーの「guac-totp-key-confirmed」属性をfalseに戻すことで、MFAの再設定が可能となります。

update 
    guacamole_user_attribute 
set attribute_value='false' 
where 
    attribute_name='guac-totp-key-confirmed' 
and user_id=${USER_ID}

Workspacesについて

検証しながら気が付いたのですが、この接続の仕組みをWorkSpacesでも利用できることに思い至りました。
WorkSpacesについては、そもそも業務都合上、利用者が自宅でも接続できる必要があるため、IP制限ができず専用のクライアントツールがあればどこからでもユーザー、パスワードでログイン可能となることが悩みとしてありました。
そのため、WorkSpacesについてもGucamole経由でアクセスすることで認証をMFAを使ってセキュアにすることができかつアクセス状況もトレースが可能となります。
設定方法の詳細は割愛させていただきますが、WorkSpacesに割り当てられているENIにアタッチされたセキュリティグループにGucamoleサーバーから3389で疎通可能となるルールを設定することで、RDPで接続が可能となります。さらにIPアクセスコントールでルールなしの状態で設定すると、クライアントツールからは接続ができません。ただし、この方法は実行モードが「AutoStop」モードでは利用できないので注意してください。

まとめ

Apache Gucamoleについては、Windowsマシンへアクセスするための踏み台としてすごく便利だと思いました。特に管理側としてアクセス状況のトレースがしやすいというのは非常にありがたい機能だと思います。今回は、共通ユーザーの問題があったので、Gucamoleにたどり着きましたが、全てのAWS上へのWindowsマシンへのアクセスは基本的にこれを利用する方式にしようかと考えています。もし同じような悩みを抱えている場合は、利用を検討してみてください。