我最近嘗試在 Windows 透過 Rsync 搭配 OpenSSH 備份檔案,結果怎樣都無法設定成功,直到今天才嘗試出一個可行的作法。雖然在 Windows 安裝 Cygwin + cygsshd
不是我心目中理想的解決方案,畢竟是開源且沒有技術支援的方案,出問題比較沒人可以救你,但這至少是一個可行方案。這篇文章將說明設定過程的完整步驟。
在 Windows 架設 Cygwin 的 OpenSSH Server 服務 (cygsshd
)
請以系統管理人員身份執行 PowerShell 進行操作。
-
安裝 Chocolatey 套件管理器
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
-
安裝 Cygwin 工具
除了安裝 cygwin
之外,也建議安裝 cyg-get
工具,方便日後安裝套件:
choco install cygwin cyg-get -y
預設安裝路徑為 C:\tools\cygwin
-
透過 cyg-get
工具安裝必要套件
cyg-get rsync zstd libzstd cygrunsrv openssh
-
透過開始功能表點擊 Cygwin64 Terminal 捷徑進入 Cygwin 殼層環境
-
初始化 OpenSSH Server 設定
執行 ssh-host-config
工具可以全自動完成所有必要設定
ssh-host-config
設定的過程會問你三個問題,依序回答 yes
, yes
, Enter
繼續即可:
*** Info: Generating missing SSH host keys
ssh-keygen: generating new host keys: RSA DSA ECDSA ED25519
*** Query: Should StrictModes be used? (yes/no) yes
*** Info: Updating /etc/sshd_config file
*** Query: Do you want to install sshd as a service?
*** Query: (Say "no" if it is already installed as a service) (yes/no) yes
*** Query: Enter the value of CYGWIN for the daemon: []
*** Info: The sshd service has been installed under the LocalSystem
*** Info: account (also known as SYSTEM). To start the service now, call
*** Info: `net start cygsshd' or `cygrunsrv -S cygsshd'. Otherwise, it
*** Info: will start automatically after the next reboot.
*** Info: Host configuration finished. Have fun!
預設 cygsshd
服務會自動隨著 Windows 開機時自動啟動。
-
啟動 cygsshd
服務
你可以用 net start cygsshd
啟動服務
net start cygsshd
也可以透過 cygrunsrv --start cygsshd
命令啟動服務
cygrunsrv --start cygsshd
-
新增 OpenSSH Server (cygsshd)
防火牆規則
New-NetFirewallRule -Name cygsshd -DisplayName 'OpenSSH Server (cygsshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
設定金鑰認證與無密碼登入
-
先從 Windows Server 建立一個 user1
使用者
net user user1 * /ADD
-
再從 Windows Client 安裝 cwRsync 工具
我們將在 Windows 用戶端安裝 cwRsync 工具,但請注意,不要使用 Chocolatey 的 cwRsync 套件進行安裝。
# 下載 cwRsync 最新版
Invoke-WebRequest -Uri https://itefix.net/dl/free-software/cwrsync_6.2.4_x64_free.zip -OutFile cwrsync_6.2.4_x64_free.zip
# 先解壓縮到暫存資料夾
Expand-Archive -LiteralPath "$PWD\cwrsync_6.2.4_x64_free.zip" -DestinationPath "$env:TEMP\cwrsync"
# 將 cwrsync_6.2.4_x64_free 目錄下所有檔案複製到 C:\cwrsync
mkdir "C:\cwrsync"
Copy-Item -Path "$env:TEMP\cwrsync\cwrsync_6.2.4_x64_free\*" -Destination "C:\cwrsync" -Recurse
安裝好的 cwRsync 會在 C:\cwrsync\bin
看到 rsync.exe
, ssh.exe
, ssh-keygen.exe
, ssh-agent.exe
等常用工具。
-
設定無密碼的金鑰驗證
從 Windows Client 產生一組 SSH 金鑰
C:\cwrsync\bin\ssh-keygen.exe -f 'mysshkey' -N '""'
上述命令會產生兩個檔案,一個私密金鑰檔 mysshkey
與一個公開金鑰檔 mysshkey.pub
# 第一次設定需建立合格的 .ssh/authorized_keys 檔案
ssh user1@172.29.217.64 'mkdir .ssh; touch .ssh/authorized_keys; chmod 600 .ssh/authorized_keys'
# 將公開金鑰檔內容複製過去
cat ./mysshkey.pub | ssh user1@172.29.217.64 tee -a ~/.ssh/authorized_keys
Windows 通常在建立好金鑰組之後會無法使用金鑰登入,因為 NTFS 權限可能有問題
ssh -i ./mysshkey user1@172.29.217.64
你會看到 Permissions for './mysshkey' are too open.
的錯誤訊息:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions for './mysshkey' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "./mysshkey": bad permissions
user1@172.29.217.64's password:
-
修正 SSH 金鑰權限
由於私密金鑰檔的 NTFS 權限只能給「系統管理員」與「擁有者」可以讀取,所以有任何「其他使用者」也能讀取這個檔案,將無法通過 ssh
的安全檢查,因此無法使用 publickey
進行驗證。
# 查詢私密金鑰檔所有 NTFS 權限
icacls .\mysshkey
# 先移除 NTFS 檔案權限繼承
icacls .\mysshkey /inheritance:r
# 移除所有「非擁有者」的權限
icacls .\mysshkey /remove Everyone
icacls .\mysshkey /remove BUILTIN\Users
icacls .\mysshkey /remove "NT AUTHORITY\Authenticated Users"
icacls .\mysshkey /remove "NULL SID"
# 先查詢擁有者是誰
$owner=(Get-Acl .\mysshkey).owner
# 允許擁有者可以完整存取該檔案
icacls .\mysshkey /grant ${owner}:F
# 查詢私密金鑰檔所有 NTFS 權限
icacls .\mysshkey
# 修正完 NTFS 權限就可以順利登入了
ssh -i ./mysshkey user1@172.29.217.64
建立測試 rsync 透過 ssh 傳輸檔案
一般來說我們通常會這樣執行命令:
rsync -avzr -e 'ssh -i .\mysshkey' mysshkey.pub user1@172.29.217.64:.
但是在我的電腦會看到以下錯誤:
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(228) [Receiver=3.2.4dev]
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(228) [sender=3.2.3]
起初我以為是 rsync
版本不匹配導致,後來發現根本不是這麼一回事!
問題的主因主要是 ssh.exe
的匹配出了問題,你不能使用 Win32-OpenSSH 的 ssh.exe
來跟 Rsync 搭配使用,直接使用 cwRsync 的 ssh.exe
即可!
以下才是正確的參數用法:
rsync -avzr -e 'C:\cwrsync\bin\ssh.exe -i .\mysshkey' mysshkey.pub user1@172.29.217.64:.
以下是成功執行的顯示結果:
sending incremental file list
mysshkey.pub
sent 581 bytes received 35 bytes 410.67 bytes/sec
total size is 571 speedup is 0.93
有了 Rsync 之後,你就可以輕鬆的實現 Windows 對 Windows 之間的自動備份方案,而且同時兼顧安裝設定的簡便性、網路傳輸的安全性,以及享受 rsync 帶來的強大檔案同步功能,有檔案差異比對、內容壓縮、與數十個可用的微調參數! 👍
相關連結