The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

如何在 Windows 安裝 Cygwin 的 SSHD 服務並正確使用 Rsync 同步檔案

我最近嘗試在 Windows 透過 Rsync 搭配 OpenSSH 備份檔案,結果怎樣都無法設定成功,直到今天才嘗試出一個可行的作法。雖然在 Windows 安裝 Cygwin + cygsshd 不是我心目中理想的解決方案,畢竟是開源且沒有技術支援的方案,出問題比較沒人可以救你,但這至少是一個可行方案。這篇文章將說明設定過程的完整步驟。

在 Windows 架設 Cygwin 的 OpenSSH Server 服務 (cygsshd)

請以系統管理人員身份執行 PowerShell 進行操作。

  1. 安裝 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'))
    
  2. 安裝 Cygwin 工具

    除了安裝 cygwin 之外,也建議安裝 cyg-get 工具,方便日後安裝套件:

    choco install cygwin cyg-get -y
    

    預設安裝路徑為 C:\tools\cygwin

  3. 透過 cyg-get 工具安裝必要套件

    cyg-get rsync zstd libzstd cygrunsrv openssh
    
  4. 透過開始功能表點擊 Cygwin64 Terminal 捷徑進入 Cygwin 殼層環境

  5. 初始化 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 開機時自動啟動。

  6. 啟動 cygsshd 服務

    你可以用 net start cygsshd 啟動服務

    net start cygsshd
    

    也可以透過 cygrunsrv --start cygsshd 命令啟動服務

    cygrunsrv --start cygsshd
    
  7. 新增 OpenSSH Server (cygsshd) 防火牆規則

    New-NetFirewallRule -Name cygsshd -DisplayName 'OpenSSH Server (cygsshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
    

設定金鑰認證與無密碼登入

  1. 先從 Windows Server 建立一個 user1 使用者

    net user user1 * /ADD
    
  2. 再從 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 等常用工具。

  3. 設定無密碼的金鑰驗證

    從 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:
    
  4. 修正 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-OpenSSHssh.exe 來跟 Rsync 搭配使用,直接使用 cwRsyncssh.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 帶來的強大檔案同步功能,有檔案差異比對、內容壓縮、與數十個可用的微調參數! 👍

相關連結

留言評論