【Azure VM】Windows Serverに公開鍵認証のSSHで接続できるようにするTech TIPS

LinuxとWindowsが混在するシステムをリモートから管理する場合、前者はSSH、後者はリモートデスクトップかWinRMと、使い分けているのではないだろうか。これは意外と面倒だと感じていると思う。実はWindows ServerでもSSHに接続することは可能だ。Azureの仮想マシン(VM)をデプロイする際に、公開鍵認証でSSH接続ができるようにする方法を紹介する。

» 2023年08月30日 05時00分 公開
[島田広道デジタルアドバンテージ]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「Tech TIPS」のインデックス

連載目次

Windows Serverに公開鍵認証のSSHで接続したい(Azure仮想マシン)

対象:Azure Virtual Machine(仮想マシン)、Windows Server 2019/Windows Server 2022、Bicep


Windows ServerもLinuxのようにSSHで接続して管理したい!

 LinuxやWindows Serverをリモートから管理する場合、LinuxにはSSHで、Windows ServerにはリモートデスクトップやWinRMでそれぞれ接続して管理することが多いだろう。

 しかし、Windows ServerとLinuxが混在しているシステム、それもLinuxの方が多い場合は、Windows Serverだけ例外としてSSH以外の方法で管理するのが面倒だと感じないだろうか?

 実は、Windows Server 2019以降のWindows Server OSには、OpenSSHのクライアント/サーバ機能が標準装備されている。ちょっとした作業でOpenSSHサーバをインストールして、リモートからSSHで接続できるのだ。

 そこで本Tech TIPSでは、Windows Server 2019/2022をAzureの仮想マシン(VM)にインストールするという前提で、デプロイ中に自動でOpenSSHサーバをセットアップして、リモートから公開鍵認証を経てSSHで接続できるようにする方法を紹介する。

 管理が主目的なので、SSHで接続できるようにするのは、Azure VMのデプロイ時に生成される管理アカウントとする(管理権限を持たない一般ユーザーは対象外とする)。

■執筆時の各種ツール/APIのバージョン

  • Azure CLI: Ver. 2.51.0
  • Bicep CLI: Ver. 0.20.4
  • Bicepでのデプロイ時のAPIバージョン: 2023-03-01(仮想マシン)、2023-04-01(ネットワーク)

SSH接続に用いる公開鍵/秘密鍵のペアを用意する

 まずは、Windows ServerのVMにSSHで接続するための管理アカウント向け公開鍵/秘密鍵のペアを生成する。後述するVMのデプロイ時に公開鍵が必要なので、事前に用意しておく必要がある。

 公開鍵/秘密鍵は「ssh-keygen」コマンドで生成するのが簡単だ(Windows 10/11の場合、SSHクライアントをインストールすると、ssh-keygenコマンドが使えるようになる)。

ssh-keygen -t ed25519 -f <鍵ファイル名> -C "<コメント>"



 これでed25519署名の秘密鍵が<鍵ファイル名>というファイルに、同様に公開鍵が<鍵ファイル名>.pubにそれぞれ格納される。いずれもOpenSSHでそのまま使える形式で出力される。

秘密鍵/公開鍵のペアを生成する 秘密鍵/公開鍵のペアを生成する

公開鍵認証のSSH接続を有効にしたWindows ServerのVMをデプロイする

 次にWindows ServerのVMを生成しよう。以下、SSHと公開鍵認証に関係する部分に絞って説明していく。その他の部分は適宜補完していただきたい。またデプロイには、AzureリソースマネージャーとBicepを利用している。

param location string = resourceGroup().location
param vmName string // 仮想マシンの名前
param computerName string // コンピュータ名
param adminUsername string // 管理アカウントのユーザー名
@secure()
param adminPassword string // 管理アカウントのパスワード
param adminPublicKey string = loadTextContent('id_ed25519.pub'
// デフォルトでは「id_ed25519.pub」に記載の公開鍵が用いられる
// loadTextContent()では変数でファイル名を指定できないので注意

// リソース生成: 仮想マシン
resource vm 'Microsoft.Compute/virtualMachines@2023-03-01' = {
  name: vmName
  location: location
  properties: {
    osProfile: {
      computerName: computerName
      adminUsername: adminUsername
      adminPassword: adminPassword
      windowsConfiguration: { /* …… 省略 ……*/ } // Windows OS特有の設定
    }
    hardwareProfile: { /* …… 省略 ……*/ }
    storageProfile: { /* …… 省略 ……*/ }
    networkProfile: { /* …… 省略 ……*/ }
  }
}

// OpenSSHサーバの設定ファイルなどのパス
var winSSHAdminPath = 'C:/ProgramData/ssh'
var winSSHAdminAuthKeys = '${winSSHAdminPath}/administrators_authorized_keys'
var winSSHHostKeys = '${winSSHAdminPath}/ssh_host_*_key.pub'

// 実行するコマンドライン(PowerShell)
var cmdLineSetupSSHServer = 'Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0; while(!(Get-Service sshd -ErrorAction SilentlyContinue)) { Start-Sleep 1; } Start-Service sshd; Set-Service sshd -StartupType Automatic; Write-Output \'${adminPublicKey}\' | Out-File ${winSSHAdminAuthKeys} -Encoding ASCII; icacls.exe ${winSSHAdminAuthKeys} /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"; Get-Content ${winSSHHostKeys}'

// リソース生成: OpenSSHサーバをインストールして公開鍵認証をセットアップする
resource runCmdSetupSSHServer 'Microsoft.Compute/virtualMachines/runCommands@2023-03-01' = {
  parent: vm // コマンドを実行する仮想マシンのリソース
  name: 'SetupSSHServer' // このコマンドに付ける名前
  location: location
  properties: {
    source: {
      script: cmdLineSetupSSHServer // sshdのインストールとセットアップ
    }
    timeoutInSeconds: 1200 // 最長20分まで待つ
  }
}

【Bicep】公開鍵認証のSSH接続が有効なWindows Server VMを生成する
仮想ネットワークやSSHに関係のない設定は省いているので、必要に応じて追加/変更してほしい。
※Microsoftのレファレンス: Microsoft.Compute virtualMachinesMicrosoft.Compute virtualMachines/runCommands

 上記リストの変数「cmdLineSetupSSHServer」に格納しているのが、OpenSSHサーバ(以下、「sshdサービス」)のインストールや公開鍵の設定をするためのコマンドラインである。Windows OSの場合、これはPowerShellで記述する必要がある。各コマンドレットの目的は以下の通りだ。

# 変数
$adminPublicKey = Get-Content "id_ed25519.pub" -Encoding ASCII
$winSSHAdminPath = "C:/ProgramData/ssh"
$winSSHAdminAuthKeys = "${winSSHAdminPath}/administrators_authorized_keys"
$winSSHHostKeys = "${winSSHAdminPath}/ssh_host_*_key.pub"

# Windows Serverの標準機能であるOpenSSHサーバ(sshdサービス)をインストール
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

#サービスとして認識されるまで待つ
while(!(Get-Service sshd -ErrorAction SilentlyContinue)) { Start-Sleep 1; }

# sshdサービスを起動
Start-Service sshd

# sshdサービスが自動的に起動するように設定を変更
Set-Service sshd -StartupType Automatic

# 管理アカウント用の公開鍵を所定のパスに保存
Write-Output ${adminPublicKey} | Out-File ${winSSHAdminAuthKeys} -Encoding ASCII

# 公開鍵ファイルを管理者とシステムアカウントだけがアクセスできるように制限
icacls.exe ${winSSHAdminAuthKeys} /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"

# C:\ProgramData\sshフォルダにあるホストキーを表示
Write-Output "----- SSH Host Keys -----"
Get-Content ${winSSHHostKeys}

【PowerShell】実行するコマンドの詳細
※Microsoftのレファレンス: Add-WindowsCapabilityStart-SleepSet-ServiceStart-Serviceicacls.exe(コマンド)

 VM以外のリソースについても、注意すべき点を簡単に説明しておく。

 ネットワークインタフェース(NIC)に割り当てる「ネットワークセキュリティグループ」については、最低限、SSHの受信を許可するためのセキュリティルール(受信ポートの規則)を追加する必要がある。

// リソース生成: ネットワークセキュリティグループ
resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2023-04-01' = {
  name: 'nsg-${vmName}'
  location: location
  properties: {
    securityRules: [
      {
        name: 'allow-ssh'
        properties: {
          description: 'Allow the SSH Connection'
          protocol: 'TCP'
          sourcePortRange: '*'
          destinationPortRange: '22' // SSHのデフォルトの着信ポート番号
          destinationAddressPrefix: '*'
          access: 'Allow' // 許可
          priority: 1000
          direction: 'Inbound' // 内向き
          sourceAddressPrefixes: [] // 接続を許可するソースIPアドレスを列挙
        }
      }
    ]
  }
}

【Bicep】SSHの受信を許可するためのネットワークセキュリティグループを生成する
※Microsoftのレファレンス: Microsoft.Network networkSecurityGroups

 必要なら、RDPやWinRMについても、許可するセキュリティルールをネットワークセキュリティグループに追記していただきたい。

 インターネット経由でWindows Server VMに接続するなら、パブリックIPアドレスも生成してNICにひも付ける必要がある。

// ↓ホスト名を指定。デフォルトは「<仮想マシン名>-<ユニークな英数字>
param hostName string = toLower('${vmName}-${uniqueString(resourceGroup().id)}')
@allowed([
  'Basic' // 動的IPアドレスが必要ならこちらを選択
  'Standard' // IPアドレスは固定のみ
])
param pipSKU string = 'Basic'
@allowed([
  'Dynamic' // 動的IPアドレス
  'Static' // 固定IPアドレス
])
param pipAllocationMethod string = pipSKU == 'Standard' ? 'Static' : 'Dynamic'
param pipIdleTimeoutInMinutes int // アイドル時のタイムアウト秒数を指定

// リソース生成: パブリックIPアドレス
resource publicIPAddress 'Microsoft.Network/publicIPAddresses@2023-02-01' = {
  name: 'pip-${vmName}'
  location: location
  sku: {
    name: pipSKU
  }
  properties: {
    publicIPAllocationMethod: pipAllocationMethod
    publicIPAddressVersion: 'IPv4'
    dnsSettings: {
      domainNameLabel: hostName // FQDNは「<ホスト名>.<Azureのドメイン>」になる
    }
    idleTimeoutInMinutes: pipIdleTimeoutInMinutes
  }
}

【Bicep】インターネット経由でSSHに接続するためのパブリックIPアドレスを生成する
※Microsoftのレファレンス: Microsoft.Network publicIPAddresses

 デプロイ後に必要となる情報については、以下のような「output」の行を加えて、デプロイ完了時に表示される出力に追加しておくとよい。

// コンピュータ名
output computerName string = vm.properties.osProfile.computerName

// 管理アカウント名
output adminUsername string = vm.properties.osProfile.adminUsername

// SSHクライアントのコマンドライン
output sshCommand string = 'ssh ${adminUsername}@${publicIPAddress.properties.dnsSettings.fqdn} -i id_ed25519'

【Bicep】SSHクライアントのコマンドラインなどを出力(表示)する
※Microsoftのレファレンス: Bicep の出力

デプロイ後に表示されたSSHクライアントのコマンドラインなど デプロイ後に表示されたSSHクライアントのコマンドラインなど

デプロイ時に実行したコマンドの結果を確認/検証する

 デプロイ時に実行したコマンドの標準出力やエラーの有無を確認するには、以下のAzure CLIコマンドを実行する。

az vm run-command show -o jsonc -g <VMのリソースグループ名> --vm-name <VM名> --run-command-name SetupSSHServer --instance-view

【Azure CLI】コマンド実行時の標準出力やエラーの有無を取得する
※Microsoftのレファレンス: az vm run-command show

 コマンドが正しく実行できていたら、以下の画面のように、「instanceView.output」にホストキーなどが出力されているはずだ。一方、エラーが生じた場合は、「instanceView.error」の値で詳細を確認できる(エラーが発生しなかった場合はnullが入る)。

【Azure CLI】コマンドの実行結果 【Azure CLI】コマンドの実行結果

 「instanceView.output」にあるホストキーは、Tech TIPS「【Azure】Linux VMのSSHサーバ(sshd)のホストキー(公開鍵)を安全に確認するには」で説明している手順で、SSHクライアントのknown_hostsに登録しておく。

デプロイしたWindows Server VMにSSHで接続してみる

 VMのデプロイが正しく完了したら、SSHで接続してみよう。それには、前述のOutputで出力したSSHクライアントのコマンドラインをコピーして実行する。

ssh <ユーザー名>@<VMのホスト名(FQDN)> -i <秘密鍵ファイル>

【コマンドライン】デプロイしたWindows VMにSSHで接続する

 秘密鍵に設定したパスフレーズを入力して認証に成功すると、SSH接続が確立し、コマンドプロンプトが表示されるはずだ。

公開鍵認証のSSHでWindows VMに接続したところ 公開鍵認証のSSHでWindows VMに接続したところ

「Tech TIPS」のインデックス

Tech TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。