Azure Bastion にネイティブクライアントで接続する (ファイル転送、AAD 認証)

:::note info
2024/06/27 デスクトップのサイズ変更の方法、マルチディスプレイの無効化を追記 
:::

Azure Bastion の Standard SKU にて Windows の RDP, SSH クライアントよる接続が~~パブリックプレビューで~~利用できるようになりました。<font color="Red">(2022/03/28 GA しました)</front>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/af46cae3-1347-fba1-7ce9-3f978be81199.png)

この機能を利用することで今まで Bastion 利用時の一つの課題であったファイル転送が実現できるようになっています。また、AAD 参加済みの VM に対して AAD の資格情報を利用してログインもできるようになりました。

https://docs.microsoft.com/ja-jp/azure/bastion/connect-native-client-windows

https://docs.microsoft.com/en-us/azure/bastion/vm-upload-download-native

ネイティブクライアントの機能を利用することで以下のようなメリットがあります。

- RDP 接続によりファイルのコピー＆ペーストができるようになる (Linux でもデスクトップ環境を構成し、RDP で接続すれば可能)
- SCP を使ってファイルのダウンロード、アップロードが可能になる (Windows/Linux 共に可)
- RDP, SSH でそのまま接続するため、文字列のコピー&ペーストもよりスムーズになる
- AAD の資格情報を利用してログインが可能
- Powershell & Azure CLI だけで接続可能となるため、ブラウザの操作は不要
- パブリック IP アドレスがなく、かつ VPN/ER もないような環境でも従来と同様の操作性で利用できる

構成手順と検証して気づいた留意点や、ネイティブクライアントの動作の詳細を記載していきます。

## 前提条件

- Powershell またはコマンドプロンプトで利用可能な最新版の Azure CLI が導入済みであること
- AAD 認証を利用する場合、Azure VM を AAD 参加済みの VM として構成済みであること
- クライアントに OpenSSH のクライアントが導入済みであること
- Bastion を Standard SKU で構成済みであること
- Windows 10, Ubuntu 18.04 の VM を Bastion と同じ仮想ネットワークに作成済みであること (VNet ピアリングも可)
- NIC, サブネットに NSG が構成されている場合、Bastion サブネットから TCP 22,3389 あての通信が許可されていること (NSG の設定は[こちら](https://jpaztech.github.io/blog/network/bastion-nsg/)を参照)
- Windows / Linux / WSL をクライアントとして利用していること。(az network bastion rdp コマンドが使えるのは Windows のみになります。)
- Cloud Shell で az network bastion tunnel コマンドはサポートされておりません。


Azure CLI のインストールはこちらを参照ください。インストール後に Powershell, コマンドプロンプトを一度閉じる必要があることにご留意ください。

https://docs.microsoft.com/ja-jp/cli/azure/install-azure-cli-windows?tabs=azure-cli#install-or-update

VM を AAD に参加させる手順はこちらを参照ください。原因は分かっておりませんが、Linux 環境は最新の手順 (2022/1 末頃に確認) ですとうまくいきませんでした。

https://docs.microsoft.com/ja-jp/azure/active-directory/devices/howto-vm-sign-in-azure-ad-windows

## 1. Azure VM の準備

こちらの手順に従って Azure VM を用意していきます。

https://qiita.com/Isato-Hiyama/items/cb77897ddbf19d3f1cfb

Windows (SSH), Linux (RDP) が不要である場合、最低限、前提部分の以下が構成されていれば問題ありません。

- Bastion を Standard SKU で構成済みであること
- Windows 10, Ubuntu 18.04 の VM を Bastion と同じ仮想ネットワークに作成済みであること (VNet ピアリングも可)
- NIC, サブネットに NSG が構成されている場合、Bastion サブネットから TCP 22,3389 あての通信が許可されていること (NSG の設定は[こちら](https://jpaztech.github.io/blog/network/bastion-nsg/)を参照)

## 2. Azure Bastion のネイティブクライアントの有効化

Azure Bastion の画面にて "ネイティブ クライアント サポート" にチェックを入れ、"適用" を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/77267a7f-44df-430e-0ea3-0926391bdc73.png)

この作業をやり忘れるとネイティブクライアント利用時に以下のようにトンネリングが無効となっているエラーが出ます。

```
Exception in thread Thread-1:
Traceback (most recent call last):
  File "threading.py", line 932, in _bootstrap_inner
  File "threading.py", line 870, in run
  File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/command_modules/network/custom.py", line 8089, in _start_tunnel
  File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/command_modules/network/tunnel.py", line 182, in start_server
  File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/command_modules/network/tunnel.py", line 117, in _listen
  File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/command_modules/network/tunnel.py", line 104, in _get_auth_token
msrestazure.azure_exceptions.CloudError: Tunneling is disabled
```

## 3. ネイティブクライアントによるログイン

Azure CLI でログインします。

```
az login
```

ログイン後、サブスクリプションを指定します。

```
az account set --subscription <サブスクリプションの ID>
```

Bastion, SSH 用の拡張機能を入れておきます。

```
az extension add --name bastion
az extension add --name ssh
```

### 3-1. RDP による Windows へのログイン

Azure CLI の "az network bastion rdp" コマンドを利用し、Bastion 名、リソースグループ名と VM のリソース ID を指定して接続します。現状、解像度を指定するようなオプションはないようです。

```
az network bastion rdp --name "Bastion" --resource-group "Bastion" --target-resource-id "/subscriptions/<SubID>/resourceGroups/Bastion/providers/Microsoft.Compute/virtualMachines/Windows"
```

RDP による接続が行われ、いつもの RDP の資格情報画面が出ますので、AAD のユーザーまたはローカルユーザーでログインをします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/0f57dc59-3493-b8cf-d2d8-5a204a6ce082.png)

ログインが成功するといつもの RDP の画面と同じように接続されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/22bb288a-fa9b-4e9a-fd16-8550160e5ffc.png)

### 3-2. SSH による Windows へのログイン

対象の Windows VM は SSH サーバーを導入済みなので、SSH による接続も試します。 "az network bastion ssh" コマンドを利用し、Bastion 名、リソースグループ名と VM のリソース ID を指定して接続します。<font color="Red">SSH の場合、auth-type (password/AAD/ssh-key) のどれかの指定が必要となります。</front>

```
az network bastion ssh --name "Bastion" --resource-group "Bastion" --target-resource-id "/subscriptions/<SubID>/resourceGroups/Bastion/providers/Microsoft.Compute/virtualMachines/Windows" --auth-type password --user hiyama

Command group 'network bastion' is in preview and under development. Reference and support levels: https://aka.ms/CLI_refstatus
hiyama@localhost's password:
```

ログインが成功すると以下の様に Windows VM に SSH でログインした状態になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/ff4d91fd-00b9-b74d-255c-ea666eef5559.png)

### 3-3. RDP による Linux へのログイン

対象の Linux VM (Ubuntu) は VM 準備の際にデスクトップ環境を整備済みですので、RDP による接続を試みます。接続コマンドは Windows VM と同様です。

```
az network bastion rdp --name "Bastion" --resource-group "Bastion" --target-resource-id "/subscriptions/<SubID>/resourceGroups/Bastion/providers/Microsoft.Compute/virtualMachines/Ubuntu"
```

Linux へ RDP 接続する場合、RDP 接続後にユーザー認証を行います。この方法の場合、ローカルユーザーしか使えないと思われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/61cd1d97-95a5-4bff-6b28-df3d94c4fe78.png)

無事接続できると以下の様にデスクトップ画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/a8bb5e8b-3b84-2a4b-cb3b-1674c6d64dc4.png)

### 3-4. SSH による Linux へのログイン
同様に今度は Linux へ SSH で接続します。

```
az network bastion ssh --name "Bastion" --resource-group "Bastion" --target-resource-id "/subscriptions/<SubID>/resourceGroups/Bastion/providers/Microsoft.Compute/virtualMachines/Ubuntu" --auth-type password --user hiyama

Command group 'network bastion' is in preview and under development. Reference and support levels: https://aka.ms/CLI_refstatus
Password:
```

接続が成功すると以下の様に Ubuntu に SSH で接続した状態になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/158c9b96-19ab-dd85-0fd6-b1199a811404.png)

## 4. ファイル転送を試してみる
Windows, Linux VM へ Bastion 経由でファイル転送を試してみます。

以下の 4 つのパターンでの転送を試します。

- Windows への RDP
- Windows への SCP
- Linux への RDP
- Linux への SCP

### 4-1. Windows VM へのファイル転送 (RDP)

以下のようなテキストファイルを用意して、Bastion & RDP ネイティブクライアントで接続した Windows VM へコピー&ペーストします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/1a8b2636-3f00-9f2f-8805-564345723783.png)

問題なくファイルを配置して、開くことができました。また、ファイルのダウンロードも可能でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/deb75127-ad00-0e57-49ea-44a08ca60456.png)

### 4-2. Windows VM へのファイル転送 (SCP)

"az network bastion tunnel" コマンドを使用して SSH 接続を行います。

```
az network bastion tunnel --name "Bastion" --resource-group "Bastion" --target-resource-id "/subscriptions/<SUbID>/resourceGroups/Bastion/providers/Microsoft.Compute/virtualMachines/Windows" --resource-port "22" --port "60002"
Command group 'network bastion' is in preview and under development. Reference and support levels: https://aka.ms/CLI_refstatus
Opening tunnel on port: 60002
Tunnel is ready, connect on port 60002
```

もう一つ Powershell のターミナルを開き、上記で指定した 60002 ポートを指定して、ローカルホストに対して SCP 接続を行います。
ローカル認証でファイル転送をすることができます。

```
scp -P 60002 testfile.txt hiyama@127.0.0.1:.
The authenticity of host '[127.0.0.1]:60002 ([127.0.0.1]:60002)' can't be established.
ECDSA key fingerprint is SHA256:ubYT7olpPo7CgkukN6ssXL9bMFxjGxUuzU1UcbnYib0.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Warning: Permanently added '[127.0.0.1]:60002' (ECDSA) to the list of known hosts.

hiyama@127.0.0.1's password:
testfile.txt                                                                          100%   10     0.6KB/s   00:00
```

### 4-3. Linux VM へのファイル転送 (RDP)
クライアント PC の対象ファイルを右クリックして、コピーし、Linux 環境の適当なフォルダに Paste します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/e7c55c57-6cf7-8982-9444-a7912df021bb.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/2a11bea8-ea71-5273-b15d-623c9807f593.png)

無事、対象ファイルを転送することができました。また、ファイルのダウンロードも可能でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/9a786095-99ac-5bdf-cd9a-e4f1617b032d.png)

### 4-4. Linux VM へのファイル転送 (SCP)

"az network bastion tunnel" コマンドを使用して SSH 接続を行います。

```
az network bastion tunnel --name "Bastion" --resource-group "Bastion" --target-resource-id "/subscriptions/<SubID>/resourceGroups/Bastion/providers/Microsoft.Compute/virtualMachines/ubuntu" --resource-port "22" --port "60001"
Command group 'network bastion' is in preview and under development. Reference and support levels: https://aka.ms/CLI_refstatus
Opening tunnel on port: 60001
Tunnel is ready, connect on port 60001
Ctrl + C to close
```

もう一つ Powershell のターミナルを開き、上記で指定した 60001 ポートを指定して、ローカルホストに対して SCP 接続を行います。
ローカル認証でファイル転送をすることができます。
サポート状況は確認できてませんが、WinSCP や Teraterm で localhost:60001 を指定して SSH 接続きますので、その接続を使ってファイルのアップロード、ダウンロードも可能でした。

```
scp -P 60001 testfile.txt hiyama@127.0.0.1:.
The authenticity of host '[127.0.0.1]:60001 ([127.0.0.1]:60001)' can't be established.
ECDSA key fingerprint is SHA256:RJucxs77NuO24Z3Q12On6CWI6oqMn3U3eTElLt0AqjY.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Warning: Permanently added '[127.0.0.1]:60001' (ECDSA) to the list of known hosts.
Password:
testfile.txt                                                                          100%   10     0.7KB/s   00:00                                                                 100%   10     0.6KB/s   00:00
```

### Tips

- Linux 環境は RDP 時の Ctrl + C, Ctrl + V だと感度がイマイチだったので、うまくいかない時はコピー & ペーストは右クリックの方が確実な感じがしました。
- アップロード速度は利用するインターネット回線によっては遅い場合があり、途中で転送が中断されてしまうこともあります。そんなときは以下を見直すとよさそうです。
    - インターネットのアップロード速度が高速な環境かを確認する。数百Kbps しかないような環境では失敗することがあります。
    - Azure の Windows VM から Bastion 経由で同じ手順を試してみる。(同じリージョン内であれば Internet 経由より高速となる可能性が高いです) 

私のクライアント環境は無線のためかアップロード速度が遅く (数百Kbps) 、数十MB のファイル転送が失敗することがありました。Azure VM から同じ手順を試したところ、100MB 程度のファイルでも 1 分程度で転送可能でした。

## 5. AAD 認証での接続
ネイティブクライアントを利用することで AAD ユーザーで VM にログインすることができます。従来のブラウザによるログインではできませんのでご留意ください。

ログイン時に AAD ユーザーを指定してログインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/8964d78f-6e0a-9727-8e02-7183fdb8b51e.png)

AAD ユーザーでログインすることができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/75620b2b-fbe2-c145-260a-59f1eb0753c2.png)

うまく入れない場合は RBAC が適切に付与されているか、クライアント端末が同じディレクトリの AAD に参加済みであるか等を確認する必要があります。

https://docs.microsoft.com/ja-jp/azure/active-directory/devices/howto-vm-sign-in-azure-ad-windows#troubleshoot

## 6. 接続情報の確認

~~現状、プレビューのためか、セッション情報にはネイティブクライアントの接続は正しく記録されないようです。診断ログの出力も無いようでした。今後の改善に期待したいと思います。~~ 

セッション情報にも診断ログにも出力されるようになっていました。(20230816追記)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/5f9e807a-7bd3-81e9-62d9-1665c9e50f94.png)


## 7. ネイティブクライアントの動作の詳細を確認
RDP の接続画面を見るとわかりますが、localhost:xxxx となっており、ローカルホストの任意のポートに RDP で接続しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/cae37db2-a60c-dad5-bdc2-4c0462d4527b.png)

以下は接続前後で実施した netstat -anb の結果の差分です。上記の画像 127.0.0.1:59055 に対して RDP (mstsc.exe) で接続していることがわかります。
また python のプロセスが Azure のパブリック IP に https で接続していることがわかります。この https のどれかが Bastion への接続だと思われます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/36ef8cfa-6816-6f84-ab4a-79a4b2c4c4bd.png)

詳細な仕組みは公開されていないため、不明な部分がありますが、動作としてはローカルに RDP で接続し、それを https でカプセル化して転送するような仕組みであると推測できます。

## 8. デスクトップサイズの変更、マルチディスプレイの無効化
複数ディスプレイがある環境だとマルチディスプレイで接続されてしまい困る場合があります。
マルチディスプレイでの接続を無効化したい場合は以下の 2 つの方法で変更可能です。
２つ目の方法はデスクトップのサイズ変更も可能です。

### 8-1. マルチディスプレイの無効化 (RDP ファイルの更新)
以下のようにリモートデスクトップの画面を開き、"リモートデスクトップで すべてのモニターを使用する" のチェックを外します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/2add05a3-98de-b5ef-86b0-b30e553e2383.png)

「全般」の画面で、「接続設定」の「保存」をクリックします。(デフォルトの RDP ファイルが更新されます)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/f0a54269-6dd3-f72e-422e-7a03cdd4bca3.png)

Azure CLI のコマンドに "--disable-gateway true" のオプションを付けて接続します。

```
az network bastion rdp --name "bastion-hub-001" --resource-group "rg-hub-001" --target-resource-id "/subscriptions/<SubscriptionID>/resourceGroups/rg-onpre-001/providers/Microsoft.Compute/virtualMachines/testvm" --disable-gateway true
```

マルチディスプレイが無効化された状態で接続ができます。また、デスクトップのサイズもモニターに合わせて変更されてました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/8f6d17e9-a731-a93d-d93d-442114e856dd.png)

### 8-2. デスクトップのサイズ変更、マルチディスプレイの無効化

Azure CLI のコマンドに "--configure" のオプションを付けて接続します。

```
az network bastion rdp --name "bastion-hub-001" --resource-group "rg-hub-001" --target-resource-id "/subscriptions/<SubscriptionID>/resourceGroups/rg-onpre-001/providers/Microsoft.Compute/virtualMachines/testvm" --configure
```

RDP の接続画面がでますので、画面のタブでサイズを変更し、"リモートデスクトップで すべてのモニターを使用する" のチェックを外します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/5725b691-ce74-ba33-c34d-d011395cfca0.png)

ユーザー名を入力し、接続を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/d3b35fe6-ec72-c4c1-3777-e0b7c8eec30a.png)

マルチディスプレイが無効化され、指定されたサイズで RDP 接続されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/e6a911d9-4d0e-58cf-b091-b23bdbddf23d.png)