ちょっと話題の記事

Linux踏み台を使わずにWindowsインスタンスへのリモートデスクトップ接続をSSHトンネル化する

Linux踏み台ホストを使わずにWindowsインスタンスへのリモートデスクトップ接続をSSHトンネル化する方法について調べました。
2019.07.31

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

みなさん、こんにちは!
AWS事業本部の青柳@福岡オフィスです。

今回は、Windows の「リモートデスクトップ接続」に関して調べてみました。

はじめに

リモートデスクトップ接続の SSH トンネリングとは?

Windows をリモートで操作する場合に標準的に使われる「リモートデスクトップ接続」ですが、リモートデスクトップ接続で使用する RDP プロトコル (TCP/3389) ではなく SSH プロトコルを使って接続を行いたい場合があります。

例えば、以下のような要件・背景が考えられます:

  • サーバ側あるいはクライアント側で、ファイアウォール等によって通信可能なポートが SSH (TCP/22) のみに制限されている
  • セキュリティ強化のためパスワード認証ではなく鍵認証を使いたい (リモートデスクトップ接続は単体では鍵認証に対応していない)

このような時によく使われる手法が、Linux 踏み台サーバーと SSH ポート転送を組み合わせて実現する「リモートデスクトップ接続の SSH トンネリング」です。 *1

Linux 踏み台サーバーを利用したリモートデスクトップ接続の SSH トンネリングの例として、例えば下記のような記事があります。

踏み台サーバ経由でリモートデスクトップ接続してみた | DevelopersIO

Linux 踏み台サーバーを使わずに実現する、リモートデスクトップ接続の SSH トンネリング

このように、これまでは Linux 踏み台サーバーを使って行うパターンがよく見られましたが、「Windows Server 2019」では OS 自体に「OpenSSH Server」が標準搭載されるようになったため、以下のような構成をとることが可能となりました。

もちろん、Windows Server 2016 以前でも SSH サーバーソフトウェアを個別にインストールすれば上記の構成をとることは可能でした。
しかし、OS に標準搭載されたことによって、例えばソフトウェア導入の社内ポリシーがある場合などにおいて、導入のハードルが下がるという状況もあるのではないでしょうか。

設定を行う

それでは、実際に設定を行っていきましょう。

1. 対象 Windows サーバーで OpenSSH Server の設定を行う

対象サーバーへリモートデスクトップ接続

まず、対象となる Windows サーバーへ、通常の方法でリモートデスクトップ接続を行います。

OpenSSH Server 機能を有効化

「Settings」(設定) 画面を開き、「Apps」(アプリ) をクリックします。

「Apps & features」(アプリと機能) を選択し、「Manage optional features」(オプション機能の管理) をクリックします。

「Add a feature」(機能の追加) をクリックします。

一覧から「OpenSSH Server」を選択し、「Install」(インストール) をクリックします。

オプション機能の管理画面に戻り、「OpenSSH Server」のインストールが完了するのを待ちます。

OpenSSH Server サービスの自動起動設定

「Server Manager」(サーバーマネージャー) から「Services」(サービス) を起動します。
サービス一覧から「OpenSSH SSH Server」を右クリックして「Properties」(プロパティ) を選択します。

「Startup type」(スタートアップの種類) から「Automatic」(自動) を選択し、「OK」をクリックします。

サービス一覧から「OpenSSH SSH Server」を右クリックして「Start」(開始) を選択します。
※ ここで一旦サービスを開始しなければ、後述する「ssh」フォルダや設定ファイル群が作成されないため、必ず開始しておきます。

OpenSSH Server の config 設定

エクスプローラーで C:\ProgramData\ssh を開き、フォルダ内の sshd_config ファイルをメモ帳で開きます。

sshd_config ファイルの初期内容は以下のようになっています。

sshd_config

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

#HostKey __PROGRAMDATA__/ssh/ssh_host_rsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_dsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_ecdsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_ed25519_key

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
#PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#PubkeyAuthentication yes

# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile	.ssh/authorized_keys

#AuthorizedPrincipalsFile none

# For this to work you will also need host keys in %programData%/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#PermitTTY yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#PermitUserEnvironment no
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# no default banner path
#Banner none

# override default of no subsystems
Subsystem	sftp	sftp-server.exe

# Example of overriding settings on a per-user basis
#Match User anoncvs
#	AllowTcpForwarding no
#	PermitTTY no
#	ForceCommand cvs server

Match Group administrators
       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

変更箇所 その1:
PubkeyAuthentication yes のコメントアウトを解除します。
(公開鍵による認証を有効にします)

変更前

#PubkeyAuthentication yes

変更後

PubkeyAuthentication yes

変更箇所 その2:
PasswordAuthentication yes のコメントアウトを解除し、設定値を no に変更します。
(パスワードによる認証を無効にします)

変更前

#PasswordAuthentication yes

変更後

PasswordAuthentication no

変更箇所 その3:
Match Group administrators および AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys をコメントアウトします。
(公開鍵ファイルの場所を指定する記述ですが、この設定が有効な状態だと鍵ファイルを上手く認識してくれないため、無効にします)

変更前

Match Group administrators
       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

変更後

#Match Group administrators
#       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

公開鍵ファイルの配置

OpenSSH の公開鍵認証に使う「鍵」を準備します。

オンプレミスなどの場合であれば ssh-keygen コマンドなどを使って鍵を生成することが多いですが、今回は AWS 環境ですのでインスタンス作成時にキーペアを指定していると思います。それを使うことにしましょう。(AWS キーペアを使うことで、生成したキーファイルのセキュアな転送に関わる懸案なども考慮する必要がなくなります)

サーバー側に配置されるべき「公開鍵」ですが、Linux インスタンスの場合は /home/ec2-user/.ssh/authorized_keys に保管されています。
では、Windows インスタンスの場合はどこに保管されているのでしょうか?

答はこちらに書かれていました。

Amazon EC2 のキーペアと Windows インスタンス -> インスタンスからキーペアのパブリックキーを取得する

EC2 インスタンス内から http://169.254.169.254/latest/meta-data/ へアクセスすることで参照できる「インスタンスメタデータ」に含まれる情報の一つとして、公開鍵のデータを取得することができます。

取得した公開鍵ファイルは、Administrator ユーザープロファイルのフォルダ C:\Users\Administrator\.ssh フォルダを作成し、このフォルダ直下にファイル名 authorized_keys で保存する必要があります。

PowerShell コンソールを起動し、以下のコマンドラインを実行します。

PS> mkdir C:\Users\Administrator\.ssh
PS> Invoke-WebRequest -Uri http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key -OutFile C:\Users\Administrator\.ssh\authorized_keys

C:\Users\Administrator\.ssh\ フォルダ直下にファイル authorized_keys が保存されました。

OpenSSH Server サービスを再起動して設定を反映

これで OpenSSH Server の必要な設定は終わりました。
設定を反映させるために、OpenSSH Server サービスの再起動を行います。

「Server Manager」(サーバーマネージャー) から「Services」(サービス) を起動します。
サービス一覧から「OpenSSH SSH Server」を右クリックして「Restart」(再起動) を選択します。

2019/8/5 追記:
「1. 対象 Windows サーバーで OpenSSH Server の設定を行う」の設定内容を UserData を用いて設定自動化する方法について、記事を投稿しました。併せてご参照ください。
「Linux踏み台を使わずにWindowsインスタンスへのリモートデスクトップ接続をSSHトンネル化する」のをUserDataを用いて設定自動化してみた | DevelopersIO

2. セキュリティグループの設定を変更する

現時点で、対象の Windows サーバーに割り当てられているセキュリティグループは、接続元 IP アドレスから「TCP/3389」ポートのみ接続を許可する設定になっていると思います。

「リモートデスクトップ接続の SSH トンネリング」を行うにあたり、接続元 IP アドレスから「TCP/22」ポートの接続を許可するように、セキュリティグループのルールを追加設定する必要があります。

「リモートデスクトップ接続の SSH トンネリング」の接続確認がとれるまでは、「TCP/3389」許可のルールは残しておいてもよいかと思います。

ただし、「リモートデスクトップ接続の SSH トンネリング」を運用開始した時点で「TCP/3389」許可のルールは削除するようにしてください。
(せっかく SSH トンネリングで接続するようにしたのに、RDP プロトコルでも接続できるようになっていると意味がありませんので)

3. SSH トンネル接続を確立する

クライアントから対象 Windows サーバーの OpenSSH Server に対して、SSH トンネル接続を行います。

例として「ssh コマンド」「TeraTerm」を使用した手順を説明します。

ssh コマンドを使用する場合

ssh コマンドのオプションを以下のように指定します。

$ ssh -i <秘密鍵ファイルのパス> -L <転送元ポート>:<転送先アドレス>:<転送先ポート> <SSHログインユーザー>@<SSH接続先アドレス>
項目 設定値
秘密鍵ファイルのパス クライアント上に保存された秘密鍵ファイルの場所を指定します
転送元ポート クライアント上で使用されていないポートであれば何でも構いません
(ここでは 13389 とします)
転送先アドレス OpenSSH Server から見た RDP サーバーのアドレスですが、同一サーバー内ですので 127.0.0.1 となります
転送先ポート RDP サーバーへの接続ポート、すなわち 3389 となります
SSH ログインユーザー OpenSSH Server へのログインユーザーを指定します
(Windows ですので Administrator となります)
SSH 接続先アドレス OpenSSH Server が動作するサーバーの IP アドレス
(つまり、対象 Windows サーバーのパブリック IP アドレスとなります)

具体的な値を入力した例は、以下のようになります。

$ ssh -i ~/.ssh/dev-key.pem -L 13389:127.0.0.1:3389 Administrator@xx.xx.xx.xx

SSH 接続が行われましたら、切断せずにそのままの状態にしておきます。

TeraTerm を使用する場合

TeraTerm を起動し、接続情報を以下のように入力します。

項目 設定値
ホスト OpenSSH Server が動作するサーバーの IP アドレス
(つまり、対象 Windows サーバーのパブリック IP アドレスとなります)
サービス SSH を選択します
TCPポート# 22 を指定します

認証情報を以下のように入力します。

項目 設定値
ユーザ名 OpenSSH Server へのログインユーザーを指定します
(Windows ですので Administrator となります)
パスフレーズ 空欄のままにします (SSH 接続にパスワードは使いません)
認証方式 「RSA/DSA/ECDSA/ED25519鍵を使う」を選択します
秘密鍵 クライアント上に保存された秘密鍵ファイルの場所を指定します

SSH で接続されましたら、「設定」→「SSH 転送」の順に選択します。

「追加」をクリックします。

ポート転送の情報を以下のように入力します。

項目 設定値
ローカルのポート クライアント上で使用されていないポートであれば何でも構いません
(ここでは 13389 とします)
リッスン 空欄のままにします
リモート側ホスト OpenSSH Server から見た RDP サーバーのアドレスですが、同一サーバー内ですので 127.0.0.1 となります
ポート RDP サーバーへの接続ポート、すなわち 3389 となります

ポート転送の設定が追加されたことを確認して、「OK」をクリックします。

TeraTerm の画面は、リモートデスクトップ接続の利用が終わるまで閉じないでおきます。

4. SSH トンネルを通じてリモートデスクトップ接続を行う

「リモートデスクトップ接続」を起動して、接続先に「localhost:13389」を指定します。

「その他」をクリックして、「別のアカウントを使用する」をクリックします。

ユーザー名に「.\Administrator」と入力し、パスワードを入力して、「OK」をクリックします。

リモートデスクトップ接続が正常に行われることを確認します。

おわりに

OS が Windows Server 2019 (以降) であるという条件はありますが、Linux 踏み台を使わずにリモートデスクトップ接続を SSH トンネリングする方法について説明しました。

管理対象の Windows サーバーが多い場合などは Linux 踏み台を使って接続経路を一本化した方が良かったりもしますので、場面によって使い分けるのがよろしいかと思います。

脚注

  1. 勘違いされる場合がありますが、「RDP プロトコルは暗号化されていないため、伝送経路での盗聴を防ぐために SSH トンネリングを行うべき」というのは正しくありません。最初期を除いて RDP プロトコルは暗号化に対応しているため、伝送経路の「秘匿化」を目的に SSH トンネリングを行わなければならないということはありません。