企業内システムでは、セキュリティ向上を目的として、システム開発者が開発サーバ等にアクセスするために踏み台サーバを経由しなければいけない場合がよくあります。これが様々な事情で多段構成になっていることがあり、接続するだけで非常に面倒なので、できるだけ簡単に多段の踏み台サーバを超える方法について検証してみたいと思いました。
システム構成
下図のシステム環境で検証します。
ローカル端末からLinux踏み台サーバを10台(hop01, hop02, ..., hop10
)を経由して、最終接続先のWindowsサーバ(target
)にアクセスします。この検証環境のサーバ設定は、下表の通りです。
- 検証環境のサーバ設定
サーバ名 | IPアドレス | OSユーザ名 | SSH認証方式 | 秘密鍵ファイル |
---|---|---|---|---|
hop01 | 10.0.1.10/24 | centos | 鍵認証 | hop01.pem |
hop02 | 10.0.2.10/24 | centos | 鍵認証 | hop02.pem |
hop03 | 10.0.3.10/24 | centos | 鍵認証 | hop03.pem |
hop04 | 10.0.4.10/24 | centos | 鍵認証 | hop04.pem |
hop05 | 10.0.5.10/24 | centos | 鍵認証 | hop05.pem |
hop06 | 10.0.6.10/24 | centos | 鍵認証 | hop06.pem |
hop07 | 10.0.7.10/24 | centos | 鍵認証 | hop07.pem |
hop08 | 10.0.8.10/24 | centos | 鍵認証 | hop08.pem |
hop09 | 10.0.9.10/24 | centos | 鍵認証 | hop09.pem |
hop10 | 10.0.10.10/24 | centos | 鍵認証 | hop10.pem |
target | 10.0.100.10/24 | Administrator | パスワード認証 | なし |
今回は、AWSで検証環境を構築しました。踏み台サーバのユーザ認証には鍵認証方式を利用します。各サーバは、その一つ前のサーバが所属するサブネットからのSSH接続のみを受け付けるように、各サーバに割り当てたセキュリティグループで制限しています。
- 目標
ローカル端末のコンソール上でssh target_rdp
とコマンドを叩くと、10台の踏み台サーバを経由したトンネル接続が確立され、ローカル端末(ポート番号:13389
)から最終接続先(ポート番号:3389
)へのリモートデスクトップ通信を可能にすることを目標にします。
環境設定
多段SSHポートフォワーディングを行う方法は、コマンドラインやGUIなど複数あると思いますが、今回は、SSH_CONFIGを利用して接続します。SSH_CONFIGを利用すると、SSHコマンドのパラメータ管理が非常に楽になります。
ローカル端末の設定
今回はローカル端末のユーザ名は「USER」で統一しています。
- configファイルの設定
まず、新規ファイルを作成してSSH_CONFIGの設定内容を記述します。設定ファイルは、ファイル名をconfig
として保存します。下記の設定では、最下部に定義している接続名(Host)のtarget-rdp
を実行すると、多段SSHポートフォワーディングのトンネル接続が確立するように記載しています。
Host hop01-rdp
HostName 10.0.1.10
User centos
IdentityFile ~/.ssh/hop01.pem
LocalForward 13389 localhost:13389
Port 22
Host hop02-rdp
HostName 10.0.2.10
User centos
IdentityFile ~/.ssh/hop02.pem
ProxyJump hop01-rdp
LocalForward 13389 localhost:13389
Host hop03-rdp
HostName 10.0.3.10
User centos
IdentityFile ~/.ssh/hop03.pem
ProxyJump hop02-rdp
LocalForward 13389 localhost:13389
Host hop04-rdp
HostName 10.0.4.10
User centos
IdentityFile ~/.ssh/hop04.pem
ProxyJump hop03-rdp
LocalForward 13389 localhost:13389
Host hop05-rdp
HostName 10.0.5.10
User centos
IdentityFile ~/.ssh/hop05.pem
ProxyJump hop04-rdp
LocalForward 13389 localhost:13389
Host hop06-rdp
HostName 10.0.6.10
User centos
IdentityFile ~/.ssh/hop06.pem
ProxyJump hop05-rdp
LocalForward 13389 localhost:13389
Host hop07-rdp
HostName 10.0.7.10
User centos
IdentityFile ~/.ssh/hop07.pem
ProxyJump hop06-rdp
LocalForward 13389 localhost:13389
Host hop08-rdp
HostName 10.0.8.10
User centos
IdentityFile ~/.ssh/hop08.pem
ProxyJump hop07-rdp
LocalForward 13389 localhost:13389
Host hop09-rdp
HostName 10.0.9.10
User centos
IdentityFile ~/.ssh/hop09.pem
ProxyJump hop08-rdp
LocalForward 13389 localhost:13389
Host target-rdp
HostName 10.0.10.10
IdentityFile ~/.ssh/hop10.pem
user centos
ProxyJump hop09-rdp
LocalForward 13389 10.0.100.10:3389
- configファイルの配置
作成したconfigファイルを、ローカル端末のC:\Users\USER\.ssh
に配置します。Windows 10は最初は.ssh
フォルダは存在していないと思うので、新規に作成します。
- 秘密鍵ファイルの配置
踏み台サーバの接続に必要な秘密鍵ファイルを、任意の場所に配置します。このconfigファイルでは、秘密鍵ファイルのパスを設定するIdentityFile
パラメータで~/.ssh/
を指定しているので、秘密鍵ファイル(hop01.pem, hop02.pem, ..., hop10.pem
)をC:\Users\USER\.ssh\
下に配置しておきます。
実行結果
- トンネル接続の確立
あとは、コマンドプロンプトを起動して、target-rdp
を指定してsshコマンドを実行するだけです。
C:\Users\USER>ssh target-rdp
CreateProcessW failed error:2
posix_spawn: No such file or directory
これd...、あれ、エラーが出る…。
- エラーの原因
エラーの原因を調べてみたところ、OpenSSH for Windowsのバージョンの問題のようです。OpenSSH for Windows 7.9(2019/1/11リリース)未満では、このIssueに該当してこのエラーが出るそうなので、クライアント端末のOpenSSHのバージョンを確認してみます。
C:\Users\USER>ssh -V
OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5
ローカル端末のSSHのバージョンが古いままでした。残念ながら、Windows 10標準搭載のOpenSSH for Windowsクライアントは、2019年11月現在ではこれが最新版のようでした。
エラー回避方法
OpenSSHのエラー回避方法として、以下が考えられると思います。
- OpenSSHクライアント(Windows 10標準)を利用する [未検証]
- Windows 10標準のOpen SSHクライアントがバージョン7.9以降にアップデートされるまで待つ。
- OpenSSHクライアント(PowerShell Githubリポジトリ)を利用する [未検証]
- Windows 10標準のOpen SSHクライアントをアンインストールする
- PowerShell Githubリポジトリから最新バージョンのバイナリをダウンロードし、Windows 10に別途インストールする。
- OpenSSHクライアント(Ubuntu on Windows)を利用する
- Windows 10にUbuntu on Windowsをインストールして、Ubuntu上からLinux版Open SSHを利用する。
今回は、3のUbuntu on Windowsを利用する方法で確認してみます。
再環境設定
ローカル端末の設定
- Ubuntu on Windowsのインストール
幸運なことに、Windows 10ではLinux環境を無償で準備できます。Windows 10のLinux環境のインストール方法については、こちらのリンク等を参考にさせていただきました。早速、ローカル端末上にLinux環境をインストールします。
- OpenSSHクライアントのバージョン確認
Linux環境のインストール後に、Ubuntu on WindowsのコンソールからSSHコマンドのバージョンを確認してみます。
root@USER:~# ssh -V
OpenSSH_7.6p1 Ubuntu-4ubuntu0.3, OpenSSL 1.0.2n 7 Dec 2017
OpenSSH_for_Windowsでなくなったので、これでOKです。
- configファイルの設定
Windows環境で作成したconfigファイルを、そのまま流用します。
- configファイルの配置
Windows環境のconfigファイルを、ユーザディレクトリ直下の.sshディレクトリ(ここでは/root/.ssh/
)にコピーして配置します。最初は.sshディレクトリが存在しないため、始めにmkdir
コマンドでディレクトリを作成します。
root@USER cd ~
root@USER mkdir .ssh
root@USER cp /mnt/c/Users/USER/.ssh/config .ssh/config
- 秘密鍵ファイルの配置
Windows環境の秘密鍵ファイルも、同様にLinux環境にコピーして配置します。最後のコマンドの権限設定を忘れると、sshコマンド実行時にBad owner or permissions
のエラーが出ます。
root@USER:~/.ssh# cd /mnt/c/Users/USER/.ssh/
root@USER:/mnt/c/Users/USER/.ssh# cp hop01.pem hop02.pem hop03.pem hop04.pem hop05.pem hop06.pem hop07.pem hop08.pem hop09.pem hop10.pem /root/.ssh/
root@USER chmod 600 .ssh/*
実行結果
準備が完了したので、再度SSHコマンドを実行してみます。
- トンネル接続の確立
root@USER:~# ssh target-rdp
Last login: Fri Nov 30 00:00:00 2019 from ip-10-0-9-10.ap-northeast-1.compute.internal
[centos@ip-10-0-10-10 ~]$
これで、ローカル端末から接続先サーバへのトンネル接続が確立しました。
- Windows Remote Desktopの実行
ローカル端末から、13389番ポートでリモートデスクトップ接続します。
成功しました!リモートデスクトップの通信性能としては、操作時に微妙にネットワーク遅延のようなものを感じなくはない(ミリ秒以下レベル?)ですが、まあ十分利用できるくらいの使用感でした。
- 結論
SSH_CONFIGは便利。
参考リンク
多段SSHポートフォワーディングについて、参考にさせていただきました。
https://qiita.com/yuuki4891/items/bfe5c1d201524c6d1827
https://swfz.hatenablog.com/entry/2017/09/08/020137