共用方式為


適用於 Windows 的 OpenSSH 中的金鑰型驗證

Windows 環境中大部分的驗證都是利用使用者名稱-密碼對來完成,這適用於共用通用網域的系統。 當您在不同網域之間工作時,例如在本地和雲端託管系統之間,此類驗證方式會容易受到暴力破解攻擊的影響。

相較之下,Linux 環境通常會使用公開/私鑰組來驅動不需要使用可猜測密碼的驗證。 OpenSSH 包含可協助支援金鑰型驗證的工具,特別是:

  • ssh-keygen 來產生安全密鑰。
  • ssh-agentssh-add 用於安全儲存私鑰。
  • scpsftp,以在初次使用伺服器期間安全地複製公鑰檔案。

本檔概述如何在 Windows 上使用這些工具,以搭配安全殼層 (SSH) 開始使用金鑰型驗證。 如果您不熟悉 SSH 金鑰管理,我們強烈建議您檢閱 NIST 檔案 IR 7966,該檔案的標題為 使用安全殼層進行互動式和自動化存取管理的安全性

密鑰對

金鑰組指的是特定驗證通訊協定所使用的公開和私密金鑰檔案。

SSH 公鑰驗證會使用非對稱密碼編譯演算法來產生兩個密鑰檔案:一個 私人,另一個 公用。 每個私鑰檔案都相當於密碼,而且在所有情況下都應該保持保護。 如果有人取得您的私密金鑰,他們就可以登入您有權存取的任何 SSH 伺服器。 公鑰是放在 SSH 伺服器上的內容,而且可以共用,而不會危害私鑰。

SSH 伺服器和用戶端可以使用金鑰驗證,將提供的使用者名稱的公鑰與私鑰進行比較。 如果無法根據用戶端私密金鑰驗證伺服器端公開金鑰,驗證就會失敗。

在生成金鑰組時輸入通行密語,即可使用金鑰組實作多重要素驗證。 如需詳細資訊,請參閱 使用者金鑰產生。 驗證時會提示使用者輸入通關密語。 將通關密語與私鑰一起使用於 SSH 用戶端上以驗證使用者。

重要

透過金鑰型驗證開啟的遠端會話沒有相關聯的用戶認證。 因此,會話無法以使用者身分進行外部驗證。 此行為是設計使然。

主機金鑰產生

公鑰具有特定的訪問控制清單 (ACL) 需求,在 Windows 上,等同於只允許系統管理員和系統使用者的存取權。 第一次使用 sshd 服務時,會自動產生主機的密鑰組。

重要

您必須先安裝 OpenSSH Server,才能執行本文中的命令。 如需詳細資訊,請參閱 開始使用OpenSSH for Windows

根據預設,您必須手動啟動 sshd。 若要將它設定為在每次重新啟動伺服器時自動啟動,請從伺服器上提升許可權的 PowerShell 提示字元執行下列命令:

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

# Start the sshd service.
Start-Service sshd

因為沒有與 sshd 服務相關聯的使用者,因此主機密鑰會儲存在 C:\ProgramData\ssh 下。

使用者金鑰產生

若要使用金鑰型驗證,您必須先為您的用戶端產生公開/私密金鑰組。 您可以使用 ssh-keygen.exe 來產生金鑰檔案,而且您可以指定下列金鑰產生演演算法:

  • 數位簽章演算法 (DSA)
  • Rivest–Shamir–Adleman (RSA)
  • 橢圓曲線數位簽名演算法 (ECDSA)
  • Ed25519

如果您未指定演算法,則會使用 Ed25519。 應使用強式演算法和金鑰長度,例如本範例中的 ECDSA。

若要使用 ECDSA 演算法產生金鑰檔案,請在用戶端的 PowerShell 或命令提示字元視窗中執行下列命令:

ssh-keygen -t ecdsa

命令的輸出看起來應該像下列幾行,不同之處在於 username 會取代為您的使用者名稱:

Generating public/private ecdsa key pair.
Enter file in which to save the key (C:\Users\username/.ssh/id_ecdsa):

在提示中,您可以選取 [Enter 以接受預設檔案路徑,或者您可以指定所產生密鑰的路徑或檔名。

接下來,系統會提示您使用複雜密碼來加密私鑰檔案。 一般而言,我們不建議使用空的通行密碼,因為通行密碼可以與密鑰檔案一起使用,以提供雙因素驗證。 但在此範例中,您可以將密碼短語留空。

Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:\Users\username/.ssh/id_ecdsa.
Your public key has been saved in C:\Users\username/.ssh/id_ecdsa.pub.
The key fingerprint is:
SHA256:OIzc1yE7joL2Bzy8!gS0j8eGK7bYaH1FmF3sDuMeSj8 username@LOCAL-HOSTNAME

The key's randomart image is:
+--[ECDSA 256]--+
|        .        |
|         o       |
|    . + + .      |
|   o B * = .     |
|   o= B S .      |
|   .=B O o       |
|  + =+% o        |
| *oo.O.E         |
|+.o+=o. .        |
+----[SHA256]-----+

現在,您在指定的位置有一個公用/私人 ECDSA 金鑰組。 .pub 檔案是公鑰,沒有擴展名的檔案是私鑰:

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----         6/3/2021   2:55 PM            464 id_ecdsa
-a----         6/3/2021   2:55 PM            103 id_ecdsa.pub

私鑰檔案相當於密碼,應該以您保護密碼的方式受到保護。 您可以使用 ssh-agent,在與 Windows 帳戶相關聯的 Windows 安全性內容中安全地儲存私鑰。 若要將 ssh-agent 服務設定為在每次重新啟動電腦時自動啟動,並使用 ssh-add 來儲存私鑰,請在伺服器上提升許可權的 PowerShell 提示字元中執行下列命令:

# By default, the ssh-agent service is disabled. Configure it to start automatically.
# Run the following command as an administrator.
Get-Service ssh-agent | Set-Service -StartupType Automatic

# Start the service.
Start-Service ssh-agent

# The following command should return a status of Running.
Get-Service ssh-agent

# Load your key files into ssh-agent.
ssh-add $env:USERPROFILE\.ssh\id_ecdsa

將金鑰新增至用戶端上的 ssh-agent 服務之後,ssh-agent 服務會自動擷取本機私鑰,並將其傳遞至 SSH 用戶端。

重要

建議您將私鑰備份到安全的位置,然後在將私鑰新增至 ssh-agent 服務 之後,從本機系統 刪除它。 使用強式演算法時,無法從代理程式擷取私鑰,例如此範例中的 ECDSA。 如果您無法存取私鑰,您必須建立新的金鑰組,並在您與之互動的所有系統上更新公鑰。

部署公鑰

若要使用您先前建立的使用者密鑰,您必須將公鑰的內容(\.ssh\id_ecdsa.pub)放在伺服器上的文字檔中。 檔案的名稱和位置取決於用戶帳戶是本機系統管理員群組的成員還是標準用戶帳戶。 以下各章節涵蓋標準和系統管理使用者。

標準使用者

您必須將公鑰的內容(\.ssh\id_ecdsa.pub)放在伺服器上,在 C:\Users\username\.ssh\ 中,將名為authorized_keys 的文本檔放入 。 您可以使用 OpenSSH scp 安全的檔案傳輸公用程式,或使用 PowerShell 將密鑰寫入檔案,來複製公鑰。

您可以使用下列程式代碼將公鑰複製到伺服器。 在最後一行中,以您的用戶名稱取代 username。 一開始,系統會提示您輸入伺服器用戶帳戶的密碼。

# Get the public key file generated previously on your client.
$authorizedKey = Get-Content -Path $env:USERPROFILE\.ssh\id_ecdsa.pub

# Generate the PowerShell command to run remotely that copies the public key file generated previously on your client to the authorized_keys file on your server.
$remotePowershell = "powershell New-Item -Force -ItemType Directory -Path $env:USERPROFILE\.ssh; Add-Content -Force -Path $env:USERPROFILE\.ssh\authorized_keys -Value '$authorizedKey'"

# Connect to your server and run the PowerShell command by using the $remotePowerShell variable.
ssh username@domain1@contoso.com $remotePowershell

系統管理使用者

您必須將公鑰的內容(\.ssh\id_ecdsa.pub)放在伺服器上,將名為 administrators_authorized_keys 的文字檔放入 C:\ProgramData\ssh\ 。 您可以使用 OpenSSH scp 安全的檔案傳輸公用程式,或使用 PowerShell 將密鑰寫入檔案,來複製公鑰。 此檔案上的 ACL 必須設定為只允許系統管理員和系統使用者的存取權。

您可以使用下列程式代碼將公鑰複製到伺服器並設定 ACL。 在最後一行中,以您的用戶名稱取代 username。 一開始,系統會提示您輸入伺服器用戶帳戶的密碼。

注意

此範例展示建立 administrators_authorized_keys 檔案的步驟。 此檔案僅適用於系統管理員帳戶。 您必須使用此檔案來取代使用者配置檔中的特定檔案。

# Get the public key file generated previously on your client.
$authorizedKey = Get-Content -Path $env:USERPROFILE\.ssh\id_ecdsa.pub

# Generate the PowerShell command to run remotely that copies the public key file generated previously on your client to the authorized_keys file on your server.
$remotePowershell = "powershell Add-Content -Force -Path $env:ProgramData\ssh\administrators_authorized_keys -Value '''$authorizedKey''';icacls.exe ""$env:ProgramData\ssh\administrators_authorized_keys"" /inheritance:r /grant ""Administrators:F"" /grant ""SYSTEM:F"""

# Connect to your server and run the PowerShell command by using the $remotePowerShell variable.
ssh username@domain1@contoso.com $remotePowershell

針對非英文的作業系統本地化版本,必須修改腳本以據以顯示組名。 若要防止將許可權授與組名時可能發生的錯誤,您可以使用安全性識別碼 (SID) 取代組名。 您可以執行 Get-LocalGroup | Select-Object Name, SID來擷取 SID。 當您使用 SID 取代組名時,其前面必須加上星號(*)。 在以下範例中,Administrators 群組會使用 SIDS-1-5-32-544

$remotePowershell = "powershell Add-Content -Force -Path $env:ProgramData\ssh\administrators_authorized_keys -Value '''$authorizedKey''';icacls.exe ""$env:ProgramData\ssh\administrators_authorized_keys"" /inheritance:r /grant ""*S-1-5-32-544:F"" /grant ""SYSTEM:F"""

這些步驟會完成在 Windows 上搭配 OpenSSH 使用金鑰型驗證所需的設定。 執行這些 PowerShell 命令之後,您可以從具有私鑰的任何用戶端連線到 sshd 主機。