【更新:11/9】Azure Bastion で踏み台を無くせるか?追加:ログ設定と内容
2019-11-13
azblob://2022/11/11/eyecatch/2019-06-20-Azure-Bastion-000.jpg

UPDate. 2019/11/9
2019/11 に開催された Microsoft ignite にてGAされたので記事をアップデートしました。
診断ログで何が確認できるようになったのかを確認しているのが中心です。
更新したのは、以下の通りです。

  • ステータスの状況
  • 利用料金
  • プレビューポータルの記述を削除
  • ログ設定と内容(診断ログ)

Azure Bastion とは

ブラウザでAzure Portal から、仮想ネットワークのプライベートIPで仮想マシンに RDPやSSHでアクセスすることができます。仮想マシンにパブリックIPを設定する必要がありません。
ソフトウェアとしては、Apache Guacamole が近いでしょうか。

RDP and SSH directly in Azure portal: You can directly get to the RDP and SSH session directly in the Azure portal using a single click seamless experience.

Azure Bastion - RDP and SSH over SSL - now available for Preview

記事の概要

  • Bastion の概要を把握する(リージョン・料金)
  • Bastion の設定方法
  • Bastion の利用方法(windows: password /Linux: ssh-key)
  • Network Security Group による接続制限をしてみる
  • 接続状況をポータルで確認する
  • 診断ログの設定と内容
  • 制限事項の確認・今後、どうなっていてほしいかの整理

はじめる前に

ステータスと利用できるリージョン

  • ステータス: General Availability ( 一般公開 )
  • リージョン: 
    • West US / East US / South Central US / West Europe
    • West Europe / Australia East / Japan East

料金

評価構成

  • 同一仮想ネットワーク内に、bastion を設置するサブネット[AzureBastionSubnet] と ターゲット仮想マシンを配置するサブネットを作成する
  • 仮想マシンは、Windows Server 2019 / Ubuntu を配置( id/passのログインとkeyによるログインを試したいため)
  • ネットワークセキュリティグループで接続制限を構成

https://docs.microsoft.com/en-us/azure/bastion/bastion-nsg

Bastion を構築する

Azure Portal にログイン

ネットワークの構成

仮想ネットワークを作成するときに注意が必要です。
Bastion 用のサブネット名は固定で AzureBastionSubnet で、セグメントは/27以上である必要があります。
今回は、以下の通り構成
・仮想ネットワーク: vNet-Secure 10.0.0.0/16
・ターゲット仮想マシンの配置用サブネット: vm 10.0.1.0/24
・Bastion 配置用サブネット: AzureBastionSubnet 10.0.2.0/27

Bastion の構成

設定する項目は、リソースグループ、インスタンスの名前・リージョン、仮想ネットワーク、サブネット、パブリックIPアドレス

Bastion の設定画面

実際に構成した後に出来上がるもの

仮想マシンスケールセットの仮想マシン2台。
実際にこちらのインスタンスに対してログインや操作は禁止されているため見えるのはここまで。

仮想マシンスケールセットの仮想マシン2台

ログイン先になるサーバの構成(Windows Server / Ubuntu )

  • 特に特別な設定は不要です
  • Windows Server 2019 と Ubuntu 18.04 LTS を、 VM 用サブネットに配置。グローバルIPは持たせない。Windows Server 2019 は管理者の ID/PASS を Ubuntu は SSH のキーを設定

Bastion 経由でサーバにログインする

共通で注意しておきたいこと

別ブラウザかタブで開くので、ブラウザのポップアップブロックに引っ掛かりました。動かないと思った時はポップアップブロックを疑ってください。

Windows Server に RDP で接続する

  • VM のリソースにアクセスする
  • メニューの、 Bastion を選択
  • Windows Server の Username と Password を入力してログイン
Windows ServerにRDPで接続する

ログインした状態。ブラウザでそのまま RDP 接続ができる。

Ubuntu へキーペアーで SSH アクセスする

  • VM のリソースにアクセスする
  • ブレードのメニューの、Bastion を選択する
  • ログインは、パスワード、 SSH Private Key を書く、 LocalFile の SSH Key ファイルを参照する(結局はブラウザ上に取り込まれます)
  • 注意:証明書のパスワードも入力できますが、シークレットになっていないため表示される。これはこんなものか。
ubuntu  Basion

ログインした状態。ブラウザで SSH 接続。

Network Security Group による接続制限

接続制限の設定方法

  • Bastion はポータル経由でログインしますが、グローバル IP を持つ
  • セキュリティを懸念される方は、Network Security Group でインバウンドで443のみに制限することができる

実際の設定

NSG と許可ルールの追加

Subnet との紐づけ

注意事項

どこでまだ何の通信が発生しているかは未確認なので、上記を実施するときはしっかり確認の上実施してください。どこまで絞れるのだろうか。
以下に情報があるがわかりにくい。
https://docs.microsoft.com/en-us/azure/bastion/bastion-nsg

接続状況をポータルで確認する

Sessions のメニューから確認できます。

診断ログ

概要

BastionAuditLogs という診断ログが出力できます。
ログの内容は、基本的にはどういう接続、切断が行われたかという記録になります。
一部ログの内容を紹介すると、処理時刻、処理の名前(connect/disconnect)、接続元情報(resourceId/接続元IP)、接続先情報(targetResourceId/接続先IP/プロトコル(ssh/rdp))、接続に利用したユーザID(接続先サーバのユーザ名)、セッション情報(開始時刻、終了時刻、接続時間(ms))が含まれています。
接続時に何が行われたかという記録は取得できません。

設定方法

診断ログ設定から、ログを出力する先を選択します。
選択肢は、他のサービスと同じで、Blobストレージ、EventHub、Log Analyticsが選択できます。
これらのリソースは事前に作っておいてください。Blobストレージはログ蓄積、EventHubはログをベースとしたイベント処理、Log Analyticsはログの分析とアラートといったところでしょうか。

ログ設定画面

bastion audit logs schema

以下はサンプルログです。SSHとRDPそれぞれの接続時、切断時のログになります。

{
  "time": "2019-11-09T05:00:29.650Z",
  "resourceId": "/SUBSCRIPTIONS/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/RESOURCEGROUPS/DEMO_BASTION/PROVIDERS/MICROSOFT.NETWORK/BASTIONHOSTS/DEMO_BASTION",
  "operationName": "Microsoft.Network/BastionHost/connect",
  "category": "BastionAuditLogs",
  "level": "Informational",
  "location": "japaneast",
  "properties": {
    "userName": "sakurai",
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19018",
    "clientIpAddress": "223.135.xxx.xxx",
    "clientPort": 52298,
    "protocol": "ssh",
    "targetResourceId": "/SUBSCRIPTIONS/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/RESOURCEGROUPS/DEMO_BASTION/PROVIDERS/MICROSOFT.COMPUTE/VIRTUALMACHINES/UBUNTU-BASTION",
    "subscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "message": "Successfully Connected.",
    "resourceType": "VM",
    "targetVMIPAddress": "10.1.1.4",
    "tunnelId": "cc93e94c-8a24-47ee-a25b-ae9cb4907b2a"
  },
  "FluentdIngestTimestamp": "2019-11-09T05:00:29.0000000Z",
  "Region": "japaneast",
  "CustomerSubscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
{
  "time": "2019-11-09T05:00:40.655Z",
  "resourceId": "/SUBSCRIPTIONS/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/RESOURCEGROUPS/DEMO_BASTION/PROVIDERS/MICROSOFT.NETWORK/BASTIONHOSTS/DEMO_BASTION",
  "operationName": "Microsoft.Network/BastionHost/disconnect",
  "category": "BastionAuditLogs",
  "level": "Informational",
  "location": "japaneast",
  "properties": {
    "userName": "sakurai",
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19018",
    "clientIpAddress": "223.135.xxx.xxx",
    "clientPort": 52298,
    "protocol": "ssh",
    "targetResourceId": "/SUBSCRIPTIONS/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/RESOURCEGROUPS/DEMO_BASTION/PROVIDERS/MICROSOFT.COMPUTE/VIRTUALMACHINES/UBUNTU-BASTION",
    "subscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "message": "Successfully Disconnected",
    "resourceType": "VM",
    "targetVMIPAddress": "10.1.1.4",
    "tunnelId": "cc93e94c-8a24-47ee-a25b-ae9cb4907b2a",
    "sessionStartTime": "2019-11-09T05:00:29.632Z",
    "sessionEndTime": "2019-11-09T05:00:40.655Z",
    "duration": 11023
  },
  "FluentdIngestTimestamp": "2019-11-09T05:00:40.0000000Z",
  "Region": "japaneast",
  "CustomerSubscriptionId": "723c35fd-fbf9-4394-b543-2c589939374a"
}
{
  "time": "2019-11-09T05:07:20.697Z",
  "resourceId": "/SUBSCRIPTIONS/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/RESOURCEGROUPS/DEMO_BASTION/PROVIDERS/MICROSOFT.NETWORK/BASTIONHOSTS/DEMO_BASTION",
  "operationName": "Microsoft.Network/BastionHost/connect",
  "category": "BastionAuditLogs",
  "level": "Informational",
  "location": "japaneast",
  "properties": {
    "userName": "sakurai",
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19018",
    "clientIpAddress": "223.135.xxx.xxx",
    "clientPort": 52457,
    "protocol": "rdp",
    "targetResourceId": "/SUBSCRIPTIONS/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/RESOURCEGROUPS/DEMO_BASTION/PROVIDERS/MICROSOFT.COMPUTE/VIRTUALMACHINES/WINSRV-BASTION",
    "subscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "message": "Successfully Connected.",
    "resourceType": "VM",
    "targetVMIPAddress": "10.1.1.5",
    "tunnelId": "bf7bf3d4-8ba6-45bf-8661-a34d2f57c1a2"
  },
  "FluentdIngestTimestamp": "2019-11-09T05:07:20.0000000Z",
  "Region": "japaneast",
  "CustomerSubscriptionId": "723c35fd-fbf9-4394-b543-2c589939374a"
}
{
  "time": "2019-11-09T05:15:51.402Z",
  "resourceId": "/SUBSCRIPTIONS/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/RESOURCEGROUPS/DEMO_BASTION/PROVIDERS/MICROSOFT.NETWORK/BASTIONHOSTS/DEMO_BASTION",
  "operationName": "Microsoft.Network/BastionHost/disconnect",
  "category": "BastionAuditLogs",
  "level": "Informational",
  "location": "japaneast",
  "properties": {
    "userName": "sakurai",
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19018",
    "clientIpAddress": "223.135.xxx.xxx",
    "clientPort": 52457,
    "protocol": "rdp",
    "targetResourceId": "/SUBSCRIPTIONS/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/RESOURCEGROUPS/DEMO_BASTION/PROVIDERS/MICROSOFT.COMPUTE/VIRTUALMACHINES/WINSRV-BASTION",
    "subscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "message": "Successfully Disconnected",
    "resourceType": "VM",
    "targetVMIPAddress": "10.1.1.5",
    "tunnelId": "bf7bf3d4-8ba6-45bf-8661-a34d2f57c1a2",
    "sessionStartTime": "2019-11-09T05:07:20.697Z",
    "sessionEndTime": "2019-11-09T05:15:51.402Z",
    "duration": 510705
  },
  "FluentdIngestTimestamp": "2019-11-09T05:15:51.0000000Z",
  "Region": "japaneast",
  "CustomerSubscriptionId": "723c35fd-fbf9-4394-b543-2c589939374a"
}

Field and property descriptions

ログの想定される編集内容になります。
まだ、オンラインに情報がなかったので出てきたログから推測しています。2019/11/9 時点

Field name Description
time The date and time (UTC).
resourceIdAzure Resource Manager resource ID of bastion host
operationNameThe name of the operation.
The value is "Microsoft.Network/BastionHost/connect"
or "Microsoft.Network/BastionHost/disconnect" .
categoryConstant value 'BastionAuditLogs'
levelConstant value 'Informational'
locationName of the Azure region where the bastion host
that processed the request was located
propertiesProperties of the current session
userNameUser login name for current session
userAgentWeb Browser userAgent for current session
clientIpAddressIP address of client computer for current session
clientPortPort number of client computer for current session
protocol Protocol name for current session.
The value is "ssh" or "rdp"
targetResourceIdAzure Resource Manager resource ID of target host
subscriptionIdSubscription entity identifier for current session
messageThe value is "Successfully Connected."
or "Successfully Disconnected"
resourceTypeType name of target host.
The value is "VM"
targetVMIPAddressIP address of target host for current session
tunnelIdSession identifier for current session
sessionStartTimeStart time for current session. This value only set at disconnect.
sessionEndTimeEnd time for current session. This value only set at disconnect.
durationNumber of milliseconds from the moment received login request
until the moment received logout or cannot login.
FluentdIngestTimestampTime of collect log data
RegionName of the Azure region
CustomerSubscriptionIdSubscription entity identifier for current session

現状の注意事項

  • どういう単位で構成することが必要なのか?
    • Vnet 単位での構成が必要
      • VNetPeering をした、同一リージョン、また、他リージョンの別の VNet にある VM に接続しようとしましたが、 Bastion の作成画面に遷移してできなかった
      • VNet ごとに設定する必要が現時点ではあります
  • ログ
    • Bastion なので監査ログが欲しくなる
      • 例えば、リモートデスクトップの画面の記録
      • 例えば、 SSH で接続したときのコンソールログ
  • 認証(できたらうれしいとふと思ったこと)
    • Azure Poral -> Azure AD -> Azure ADDS -> VM と考えると、 Bastion がきれいにつながったら、セキュアで接続が楽な環境を作れるんじゃないかと思いました。

まとめ

  • RDP と SSH ともに動きは快適でした
  • ログが記録されるようになったので一歩前進です。このログでログイン失敗など拾いたいと思ったのですが直接そのようなことが記録されるわけではないので、検討が必要になります。
    duration の時間が非常に短いというのは、RDPのパスワードでは使えるかなと思いましたが、SSHのキーを誤って登録した場合は、再ログインが促されている状態も duration の時間に含まれるのでちょっと難しいなと思いました。
  • セキュリティの観点では、パブリック IP を持ちますが、 Azure Portal のログインが前提になっているため、Azure AD や Intune のセキュリティ機能がすべて利用できるし、 VPN や Express Route など通信経路を守るのとは別の解決が図られているのでちゃんと設定すれば安心して利用できる
  • 踏み台は、もう少しでなくせる気がしてきた。これがあると cloudshell もなんかうまくつながってくれないかなと

参考リンク