我這幾年有替幾位客戶實現 Windows 平台的自動化作業,我認為 Windows 在遠端檔案傳輸方面,一直都沒有內建非常理想的解決方案。內建的方案不外乎是開一堆 Ports 且預設傳輸沒加密的 FTP 服務、不太安全的 WinRM (預設沒加密)、或是被大部分企業禁用的 SMB 協議。雖然加裝 TLS/SSL 憑證可以解決安全連線的問題,但是憑證的管理與配送,並不是所有企業都能做好,甚至門檻頗高。我認為在 Windows 平台最安全、最有效率的解決方案,還是提供 sshd
服務 (OpenSSH Server),搭配 SFTP 就能進行安全的檔案傳輸,這篇文章我就來分享如何在 Windows 正確安裝 OpenSSH Server 服務的所有步驟。
關於 SFTP 如何安全地設定,請參閱 如何在 Windows 架設高安全性的 SFTP (SSH File Transfer Protocol) 伺服器 文章說明。
安裝 Windows 10 / Windows Server 2019+ 內建的 OpenSSH 工具
微軟官網有一份 Install OpenSSH 文件,完整描述如何在 Windows 10 / Windows Server 2019 / Windows Server 2022 安裝內建的 OpenSSH 用戶端與伺服器端的軟體,但是 Windows 內建的 OpenSSH 通常不是最新版本,容易存在一些 Bugs 與缺少一些好用設定。
以下是透過 PowerShell 快速安裝的方法:
-
先確認目前的作業系統有包含 OpenSSH 相關功能
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
看到以下內容就代表你目前的 Windows 可以直接用 PowerShell 安裝 OpenSSH 相關功能:
Name : OpenSSH.Client~~~~0.0.1.0
State : NotPresent
Name : OpenSSH.Server~~~~0.0.1.0
State : NotPresent
-
安裝 OpenSSH Client 用戶端工具
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
-
安裝 OpenSSH Server 服務
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
-
啟動 OpenSSH Server 服務
# 啟動 sshd 服務
Start-Service sshd
# 設定 sshd 服務自動啟動
Set-Service -Name sshd -StartupType 'Automatic'
# 確認設定防火牆規則 (通常安裝後會自動設定完成,此步驟只是再確認一次)
if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue | Select-Object Name, Enabled)) {
Write-Output "Firewall Rule 'OpenSSH-Server-In-TCP' does not exist, creating it..."
New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
} else {
Write-Output "Firewall rule 'OpenSSH-Server-In-TCP' has been created and exists."
}
-
變更 DefaultShell
預設殼層設定
Windows 內建的 OpenSSH Server 預設在使用者遠端登入的時候是使用 Command Prompt (cmd.exe
) 作為預設殼層 (Default Shell),你可以透過以下 PowerShell 命令修改 Registry (機碼) 設定,將預設殼層修改為 Windows PowerShell!
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force
注意: 預設殼層不影響你的 sftp
檔案傳輸。
如果你要設定 PowerShell Core 為預設殼層的話,就需要先安裝 PowerShell-7.2.0-win-x64.msi 或 PowerShell-7.2.0-win-x86.msi,然後執行以下 PowerShell 命令即可:
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "c:/progra~1/powershell/7/pwsh.exe" -PropertyType String -Force
如果你想設定 Cygwin 的 bash
當成預設殼層的話,可以直接使用 Git for Windows 內建的 bash
版本,以下是設定方法:
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "$env:ProgramFiles\Git\bin\bash.exe" -PropertyType String -Force
關於完整的 OpenSSH Server 設定說明,可參考 OpenSSH Server Configuration for Windows 10 1809 and Windows Server 2019 文件。
安裝最新版的 Win32 OpenSSH 工具
目前 Windows 版的 OpenSSH 是由微軟官方維護的版本,使用上比較有保障,而且支援 Windows 7 以上的任何版本。不過當你連到 GitHub 的 Releases 頁面時,看到的版本號都是永遠的 Beta 版,而且所有的版本都是 Beta 版,但這些版本都是微軟完整測試過才會釋出,因此不用特別擔心穩定性的問題。
以下就是完整的安裝步驟:
-
下載 OpenSSH-Win64.zip 最新版回來
Invoke-WebRequest -Uri https://github.com/PowerShell/Win32-OpenSSH/releases/download/V8.6.0.0p1-Beta/OpenSSH-Win64.zip -OutFile OpenSSH-Win64.zip
-
請以系統管理人員身份執行 PowerShell 並將檔案複製到 C:\Program Files\OpenSSH
目錄下
# 先解壓縮到暫存資料夾
Expand-Archive -LiteralPath "$PWD\OpenSSH-Win64.zip" -DestinationPath "$env:TEMP\OpenSSH"
# 將 OpenSSH-Win64 目錄下所有檔案複製到 C:\Program Files\OpenSSH
mkdir "$env:ProgramFiles\OpenSSH"
Copy-Item -Path "$env:TEMP\OpenSSH\OpenSSH-Win64\*" -Destination "$env:ProgramFiles\OpenSSH" -Recurse
這個過程必須確保只有 SYSTEM
系統帳戶與 Administrator
群組擁有 Write (寫入) 權限,其他 Authenticated users
都只能有「讀取與執行」(Read and Execute) 權限而已。
-
移除 SshdBroker
服務 (Windows 10 only)
如果你使用 Windows 10 而且先前安裝過內建的 OpenSSH Server 功能,如果你跟我一樣從舊版 Windows 10 一直升級到最新版的話,Windows 10 在某個建置版本之後就移除了 SshdBroker
服務,這個變更會導致無法順利安裝 OpenSSH Server (sshd
) 服務。解決方法是透過 PowerShell Core 的 Remove-Service
命令 (cmdlet) 將 SshdBroker
服務移除即可:
Remove-Service -Name SshdBroker -Verbose
注意: Windows PowerShell 不支援 Remove-Service
cmdlet
-
執行安裝程序
使用與前一個步驟相同的 PowerShell 工作階段(以系統管理人員身份執行),執行以下命令:
cd "$env:ProgramFiles\OpenSSH"
powershell.exe -ExecutionPolicy Bypass -File install-sshd.ps1
-
啟動 OpenSSH Server 服務
# 啟動 sshd 服務
Start-Service sshd
# 設定 sshd 服務自動啟動
Set-Service -Name sshd -StartupType 'Automatic'
# 設定新的 OpenSSH Server 防火牆規則
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
如果你之前有裝過 Windows 內建的 OpenSSH Server 功能,預設會建立一個名為 OpenSSH-Server-In-TCP
的內建防火牆規則,但是這條規則有綁定一個應用程式路徑,所以該條規則對 "C:\Program Files\OpenSSH\sshd.exe"
無效,因此必須設定新的 sshd
防火牆規則才行!
-
變更 DefaultShell
預設殼層設定
Windows 內建的 OpenSSH Server 預設在使用者遠端登入的時候是使用 Command Prompt (cmd.exe
) 作為預設殼層 (Default Shell),你可以透過以下 PowerShell 命令修改 Registry (機碼) 設定,將預設殼層修改為 Windows PowerShell!
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force
注意: 預設殼層不影響你的 sftp
檔案傳輸。
如果你要設定 PowerShell Core 為預設殼層的話,就需要先安裝 PowerShell-7.2.0-win-x64.msi 或 PowerShell-7.2.0-win-x86.msi,然後執行以下 PowerShell 命令即可:
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "c:/progra~1/powershell/7/pwsh.exe" -PropertyType String -Force
如果你想設定 Cygwin 的 bash
當成預設殼層的話,可以直接使用 Git for Windows 內建的 bash
版本,以下是設定方法:
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "$env:ProgramFiles\Git\bin\bash.exe" -PropertyType String -Force
如果未來要移除 Win32 OpenSSH 可以參考這篇文章。
相關連結
- Win32-OpenSSH
- OpenSSH
- PowerShell
- WinRM (Windows Remote Management)