🍅

AzureVMのWindows11にPHPからSSH接続するメモ

2024/08/09に公開

環境

  • nginx-1.26.1
  • php-8.2.21
  • OpenSSH_for_Windows_8.6p1, LibreSSL 3.4.3

AzureCLIはインストール済みとします。↓インストール方法
https://learn.microsoft.com/ja-jp/cli/azure/install-azure-cli-windows?tabs=azure-cli
今回はすでにAzure上にWindows11VMがある状態での方法です。

1. クライアントPCでOpenSSHサーバをインストールする

通常は、こちらのように、設定アプリからシステム>オプション機能OpenSSHサーバーをインストールできるみたいなのですが、私の場合はエラーでうまくいかなかったため、こちらの最後の方法(GitHubからインストールする方法)でやると、インストールできました。

2. ホスト キーの生成

この辺りはあいまいで申し訳ないです。
クライアント側のPCのWindows PowerShellを起動して、以下を入力します。

Windows PowerShell
# Set the sshd service to be started automatically
Get-Service -Name sshd | Set-Service -StartupType Automatic

# Now start the sshd service
Start-Service sshd

これで、c://prodramdata/sshフォルダに鍵が生成されると思います。今回はとりあえず、生成された公開鍵(ssh_host_rsa_key.pub)と秘密鍵(ssh_host_rsa_key)を使います。

3. サーバー側(VM)のSSHを有効にする

クライアント側で、以下を入力する。$myResourceGroup(リソースグループ名)と$myVM(VM名)はAzureで作成したものを代入してください。

Azure CLI(Windows PowerShell)
az vm extension set --resource-group $myResourceGroup --vm-name $myVM --name WindowsOpenSSH --publisher Microsoft.Azure.OpenSSH --version 3.0

4. サーバー側(VM)のTCPポートを開く

クライアント側で、以下を入力する。$myResourceGroup(リソースグループ名)と$myNSG(ネットワークグループ名)はAzureで作成したものを代入してください。〇.〇.〇.〇/32の部分は、私の場合は、クライアントPCのグローバルIPにしました。

Azure CLI(Windows PowerShell)
az network nsg rule create -g $myResourceGroup --nsg-name $myNSG -n allow-SSH --priority 1000 --source-address-prefixes 〇.〇.〇.〇/32 --destination-port-ranges 22 --protocol TCP

5. クライアント側で作成した公開鍵を、サーバー側(VM)にコピーする

これは、スクリプトでできるみたいですが、難しかったのでテキストエディタから公開鍵(クライアント側の"C:\ProgramData\ssh\ssh_host_rsa_key.pub")直接開いて、中身をコピーして、サーバー側のauthorized_keys("C:\ProgramData\ssh\authorized_keys")にコピーしました。authorized_keysがなかったら作成してください。

6. サーバー側のOpenSSHサーバの設定を変更する

サーバー側の"C:\ProgramData\ssh\sshd_config"の中身を編集します。今回はパスワードではなく、公開鍵による認証を行うので、パスワードを無効にして、公開鍵を有効にします。また、鍵のパスを修正します。あと、administrators_authorized_keysを参照するのも無効にします。

sshd_config
- #PubkeyAuthentication yes
+ PubkeyAuthentication yes

- AuthorizedKeysFile	.ssh/authorized_keys
+ AuthorizedKeysFile	__PROGRAMDATA__/ssh/authorized_keys

- #PasswordAuthentication yes
+ PasswordAuthentication no

- Match Group administrators
-       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
+ #Match Group administrators
+ #       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

ここまで来たら、サーバーにSSH接続できるか試してみます。
サーバー側のOpenSSHを起動する。↓参考サイト引用
https://learn.microsoft.com/ja-jp/windows-server/administration/openssh/openssh_install_firstuse?tabs=gui

  1. [サービス] デスクトップ アプリを開きます。 ([スタート] を選択し、検索ボックスに「services.msc」と入力して、[サービス] アプリを選択するか、Enter キーを押します。)
  2. 詳細ウィンドウで、[OpenSSH SSH Server] をダブルクリックします。
  3. サービスを開始するには、[開始] を選択します。

クライアントPCのWindows PowerShellをを管理者権限で開きます。
以下のコマンドを入力して接続する。$usernameはVMのユーザー名、$domainnameは私の場合VMの静的IPアドレスにしました。

Windows PowerShell
ssh -i "C:\ProgramData\ssh\ssh_host_rsa_key" $username@$domainname

無事以下のように中に入れたら成功です。
Windows PowerShell
切断するにはexitを入力します。

(番外)Azure CLIのazコマンドでssh接続するだけであれば、以下のコマンドで接続できるみたいです。↓詳しくはこちら
https://learn.microsoft.com/ja-jp/azure/virtual-machines/windows/connect-ssh?tabs=azurecli#connect-using-az-cli

Azure CLI
az vm run-command invoke -g $myResourceGroup -n $myVM --command-id RunPowerShellScript --scripts "MYPUBLICKEY | Add-Content 'C:\ProgramData\ssh\administrators_authorized_keys' -Encoding UTF8;icacls.exe 'C:\ProgramData\ssh\administrators_authorized_keys' /inheritance:r /grant 'Administrators:F' /grant 'SYSTEM:F'"

7. phpでssh(ssh2)を使えるようにする

私の環境はnginxphp-fpmを使用する環境なのですが、そのままではssh2_connect()関数が使えません。phpの拡張機能をインストールする必要があります。
インストールの方法はいくつかあるみたいですが、私はdllファイルを直接ダウンロードしました。
1. PECLのサイトから「ssh2」を検索する
2. DownloadsのDLLをクリックする。今回はVersion1.4.1にした。
3. DLLをダウンロードする。私はWindows64bitPHP8.2なので、8.2 Non Thread Safe (NTS) x64をダウンロードしました。
4. ダウンロードしたファイルを解凍し、中にあるphp_ssh2.dllをphpフォルダのextフォルダにコピーする。
5. php.iniにextension=ssh2を追記する
6. phpを再起動する

8. phpでOpenSSL接続する

サーバーに2.で作成した公開鍵と秘密鍵を配置して、以下のように接続します。

index.php
// ユーザー名(VMのユーザー名を入力)
$username='testuser';
// ホスト名(VMの静的IP)
$host = '〇.〇.〇.〇'
// 秘密鍵のパス
$secretKey = __DIR__ . "/env/ssh_host_rsa_key";
// 公開鍵のパス
$publicKey = __DIR__ . "/env/ssh_host_rsa_key.pub";
// 接続する
$connection = ssh2_connect($host, 22, array('hostkey' => 'ssh-rsa'));
// 公開鍵を使用した認証を行う
if (ssh2_auth_pubkey_file($connection,$username,$publicKey,$secretKey,))
{
// 成功時
  echo "Public Key Authentication Successful\n";
}
else
{
// 失敗時
  die('Public Key Authentication Failed');
}
// 接続を解除する
ssh2_exec($connection, "exit");
unset($conn);

まとめ

駆け足でメモしましたが、無事接続できました。
今回は鍵の生成は端折りましたが、本来はpassphraseなどを使って適切な鍵を作成する必要があると思います。

参考サイト

  • OpenSSH関係

https://learn.microsoft.com/ja-jp/azure/virtual-machines/windows/connect-ssh?tabs=azurecli
https://learn.microsoft.com/ja-jp/azure/virtual-machines/linux/ssh-from-windows
https://learn.microsoft.com/ja-jp/windows-server/administration/openssh/openssh_keymanagement
https://learn.microsoft.com/ja-jp/windows-server/administration/openssh/openssh_install_firstuse?tabs=gui
https://blog.jbs.co.jp/entry/2023/12/04/091703
https://qiita.com/nujust/items/6d5ccea95e635467c96a
https://nonfleon-it.com/2024/02/08/blog-10030/

  • php関係

https://column.prime-strategy.co.jp/archives/column_2191
https://qiita.com/taiba/items/6a1cfd53f0fdcfce14bf
https://www.php.net/manual/ja/function.ssh2-auth-pubkey-file.php

Discussion