図解で、クラウドのWindowsサーバーにSSH接続する（RDP over SSH）！

# クラウドの Windowsサーバーに直接SSH接続する！
**[Windows Server 2019]からOpenSSHが標準インストールされるようになった**ので、踏み台サーバーのOSをWindowsで用意することを検証した。今回も直観的にわかりやすくするため図解付きにて。
## シナリオ（利用シーン）
パブリッククラウドでアプリケーションを実行する。アプリケーションのOS要件がWindows Serverであり、リモートデスクトップ接続（以降RDP接続と略す）が必要。保守対象のWindowsサーバーが複数あるので、Windowsの踏み台サーバーを経由してRDP接続する。今までなら踏み台サーバーを２台用意して、Linuxの踏み台サーバーでSSH接続した後、Windowsの踏み台サーバーへRDPをポートフォワードしてリモートデスクトップ接続していた。

***今まで***
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/bced8a0e-e68c-717c-1c22-15ed5a9b134f.png)

***これから***
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/04ccc36c-6b49-2215-6ddc-31ed57baf917.png)

### 手順１．踏み台サーバー(Windows)のOpenSSHを設定する
最初の設定だけはインターネットから直接RDP接続するため、最初のセキュリティグループ設定はあらゆるコンピュータからアクセス可能な「TCP3389 ソース(アクセス元)0.0.0.0/0」でありリスクあるので手早く設定する。まず、AWSやIBMCloudで[Windows Server 2019]をデプロイした後、AdministratorでログインしてPowerShellを使ってOpenSSH機能を有効にする。

    Windows PowerShell
    Copyright (C) Microsoft Corporation. All rights reserved.
    
    ▼インストール済みプログラムを確認。SSHサーバーがインストールされていない。
    PS C:\Users\Administrator>  Get-WindowsCapability -Online | ? Name -like 'OpenSSH*'
    
    Name  : OpenSSH.Client~~~~0.0.1.0
    State : Installed
    
    Name  : OpenSSH.Server~~~~0.0.1.0
    State : NotPresent　　　　　　　　　　　←インストールされていない
    
    ▼OpenSSHサーバーをインストールする。
    PS C:\Users\Administrator>  Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
    
    Path          :
    Online        : True
    RestartNeeded : False
    
    ▼再確認（今度はSSHサーバーがインストールされた）。
    PS C:\Users\Administrator>  Get-WindowsCapability -Online | ? Name -like 'OpenSSH*'
    
    Name  : OpenSSH.Client~~~~0.0.1.0
    State : Installed
    
    Name  : OpenSSH.Server~~~~0.0.1.0
    State : Installed
    
    ▼ sshdサービス起動
    PS C:\Users\Administrator> Start-Service -Name "sshd" 
    
    ▼ スタートアップを [自動] に設定
    PS C:\Users\Administrator> Set-Service -Name "sshd" -StartupType Automatic 
    
    ▼ 再起動時にSSHがスタートすることを確認
    PS C:\Users\Administrator> Get-Service -Name "sshd" | Select-Object * 
    
    Name                : sshd
    RequiredServices    : {}
    CanPauseAndContinue : False
    CanShutdown         : False
    CanStop             : True
    DisplayName         : OpenSSH SSH Server
    DependentServices   : {}
    MachineName         : .
    ServiceName         : sshd
    ServicesDependedOn  : {}
    ServiceHandle       : SafeServiceHandle
    Status              : Running
    ServiceType         : Win32OwnProcess
    StartType           : Automatic　　　　　　　←自動スタートになってること
    Site                :
    Container           :

### 手順２．Windows踏み台サーバーにSSH公開鍵を登録する
Windowsにログインする保守ユーザアカウントを設定して保守ユーザでログインする（この例ではwinuserが保守ユーザID）。

    ▼PowerShellを起動してユーザディレクトリに".ssh"ディレクトリを作る。
    PS C:\Users\winuser\ mkdir .ssh
    PS C:\Users\winuser\ cd .ssh
    
    ▼メモ帳を起動してOpenSSH形式の公開鍵(ssh-rsaで始まる鍵)を保存する。
    PS C:\Users\winuser\ notepad authorized_keys
    
    　…メモ帳で作業（割愛）…
    
    ▼検査
    PS C:\Users\winuser\ type authorized_keys
    ssh-rsa AAAAB3**************KkqqQ== rsakey

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/e621be19-c611-9c4a-4ba4-7b07efe40995.png)


SSHコンフィグファイルを修正する。ファイル名は[c:\programdata\ssh\sshd_config]。

    PS C:\Users\winuser\ notepad c:\programdata\ssh\sshd_config

公開鍵での認証をyesとする。パスワード認証はnoとする。ユーザ毎の鍵設定をしたいのでアドミニストレータの鍵保存場所を検査しないようにする。

    #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	c:\Users\winuser\.ssh\authorized_keys c:\Users\winuser2\.ssh\authorized_keys
    AuthorizedKeysFile	c:\Users\winuser\.ssh\authorized_keys
    
    #PasswordAuthentication yes       ← # を外して、noに変更する。
    PasswordAuthentication no　　　　　← noにするとパスワード認証が無効になり、公開鍵認証になる。
    
    #Match Group administrators       ← # を付けて無効にする
    #       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys     ← # を付けて無効にする

SSHDサービスを再起動する。

    PS C:\Users\winuser\ Restart-Service sshd

### 手順３．保守用PCでsshクライアントのPuttyを設定する。
Puttyに新しい接続セッションとして(1)と(2)の２つを追加する。意味は、最初に保守用PCからLinux踏み台サーバーへのSSH接続ルート(1)を確立して、次に保守用PCからSSH接続ルート(1)を経由してWindows踏み台サーバーへのSSH接続ルート(2)を確立するもの。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/19d60eb3-a524-5610-835e-c2b7123bf1b8.png)

▼下図を参考にPuttyを２つ設定する。
・[セッション]-[ホスト名]には、"OSユーザ名@IPアドレス"を入力。両方ともポートはSSHの[22]。
・[セッション]-[セッション一覧]の、接続ルート(1)のセッション名は、接続ルート(2)で使います。
・[接続]-[プロキシ]は、接続ルート(1)はデフォルトのまま、接続ルート(2)は、"plink -load <セッション(1)名> nc %host %port"を入力する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/676777fc-dc74-8b0e-a147-b3ca2e6c86da.png)

▼接続ルート(2)が正しく動作することを検査する。
接続ルート(2)のセッション名を選んで［開く］ボタンを押して、Windows踏み台サーバーにログインできたら成功。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/fecd8ec6-0a16-8251-4720-0b314bbdc426.png)
SSHで接続しているがコマンドシェルはDOSになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/6fb9050b-8039-9e96-bc5e-3baef477bab9.png)


#### 手順４．Puttyのポートフォワードを設定する。
続いて、RDP接続をSSH接続トンネルで転送するためのポートフォワーディングを設定する。SSH接続ルート(2)をトンネルとして使うので、設定するのは(2)側のみ。
・[接続]-[SSH]-[トンネル]の、[源ポート]は自由なポート番号（例えば43389）を記入、[送り先]にはWindows踏み台サーバーのパブリックIPアドレスとRDPポート番号（例えば3.3.3.3:3389）を記入して［追加］ボタンを押す。源ポート番号に下図では33389を設定しているが、RDPの3389と重ならないポート番号なら何でもよい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/d58c1909-c713-6580-250a-65548c82d12b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/75209067-0257-173b-966b-c3b055205ab0.png)

### 手順５．Windows踏み台サーバーにリモートデスクトップ接続する。
保守用PCのリモートデスクトップを起動したらコンピュータ名には自分のPCを意味する"localhost"を指定する（この例ではlocalhost:43389）。ユーザ名にはWindows踏み台サーバーの保守用ユーザIDを指定する。リモートデスクトップ接続を実行する際、自分のPCに43389ポートでRDP接続しようとしたらPuttyがWindows踏み台サーバーの3.3.3.3:3389へ転送してくれる。パスワードを聞いてきたら成功。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/69395058-ef39-4692-7058-7fe282a85973.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/6ac9b765-9f8d-13fa-4978-0b92eae17d2f.png)

## セキュリティのポイント
WindowsサーバーOSへのログインはユーザIDとパスワード、初期状態ではユーザIDがAdministratorであるため、パスワードだけ見つけられればログイン出来てしまう。実際にパブリッククラウドにデプロイされたWindows仮想サーバーがウィルスに感染させられた事例を見ているので、ポート3389をソース0.0.0.0/0にしたまま保守するのは危険、というか攻撃されるのを待っているようなもの。本書で紹介した方法ならば、(1)ソースIPアドレスを自分のLinux踏み台サーバーに限定し、(2)SSH秘密鍵を持っているユーザをSSH公開鍵で照合し、(3)ユーザIDとパスワードで認証する多段防御が実現する。なお、Windows踏み台サーバーから自分自身のWindows踏み台サーバーへRDP接続する時のセキュリティグループに登録するソースIPアドレスはAWSとAzureで異なるので注意。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/98bc75ce-8ee0-0f5f-3629-a449235b6669.png)

## つまづきポイント
### sshが怪しい
Windows踏み台サーバーの公開鍵やコンフィグを変更したらsshdサービスを再起動する。タスクマネージャーはAdministrator権限で実行する必要あり。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/6a7b2e46-616f-d214-3864-5611be037ad1.png)

### ファイアウォールが怪しい
リモートデスクトップ接続がずーーーっと待ちの時は、ファイアウォールの設定が間違っているのかも。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/7436a3a5-7365-84d0-9dbe-0b6f9b28bf60.png)

#### AWSの場合
AWSの場合、Windows踏み台サーバーに対するセキュリティグループは、外部からのSSH接続はパブリックIPアドレスでソースを指定するが、RDP接続のポートフォワードは自分自身のプライベートIPアドレスで指定するので要注意。
from 1.1.1.1 to 3.3.3.3  OpenSSH(22)
from 2.2.2.2 to 2.2.2.2  RDP(3389)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/4fe6b980-2506-d1fe-9bf3-cfefc1b41943.png)


#### Azureの場合
Azureの場合は、仮想ネットワークインターフェース(ENI)からのRDP接続になるらしく、RDP接続のポートフォワードも自分自身のパブリックIPアドレスで指定するので要注意。
from 1.1.1.1 to 3.3.3.3  OpenSSH(22)
from 3.3.3.3 to 2.2.2.2  RDP(3389)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/7e08d00c-8652-adb9-c9c0-95e1e71f1803.png)

#### IBM Cloudの場合
IBM Cloudの場合は、浮動IP(eth0)にセキュリティグループを割り当てている場合が最もシンプルで、外部からのSSH接続だけでよい（RDPの許可は不要）。
from 1.1.1.1 to 3.3.3.3  OpenSSH(22)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/9462f346-30a2-b40a-1c0e-f22286782ee7.png)




### ポートフォワードされているか怪しい
本当にRDPポートが転送されているのかな～、と不安な時は自分の保守用PCでポート43389や33389がリッスン(待ち状態)になっているか、DOSの[netstat -a]コマンドで検査する。

    C:\Users\Ichiro>netstat -a
    
    アクティブな接続
    
    プロトコル  ローカル アドレス      外部アドレス           状態
    TCP         0.0.0.0:80             Ichiro-PC:0            LISTENING
    TCP         0.0.0.0:135            Ichiro-PC:0            LISTENING
    TCP         [::]:80                Ichiro-PC:0            LISTENING
    TCP         [::]:135               Ichiro-PC:0            LISTENING
    TCP         [::1]:33389            Ichiro-PC:0            LISTENING
    TCP         [::1]:33389            Ichiro-PC:0            LISTENING
    TCP         [::1]:33389            Ichiro-PC:50942        ESTABLISHED
    TCP         [::1]:50942            Ichiro-PC:33389        ESTABLISHED

### Puttyでエラー［SSH2_MSG_UNIMPLEMENTED］の時
PuttyでSSH接続するときの鍵交換アルゴリズムを強固な[Diffie-Hellman group 14]を一番上に変更する[Up]ボタンで入れ替える。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/e163bd08-48fc-8c51-a8e9-218cea046753.png)


### 最後に
インターネット（ソース0.0.0.0/0）からのRDP接続（TCP 3389）を拒否していることを確認すること。

以上。