延續的我前一天的 如何在 Windows 正確的安裝與設定 OpenSSH Server 服務 文章,在 Windows 平台架設 OpenSSH Server 搭配 SFTP 就能進行安全的檔案傳輸,防火牆也只需要開啟 Port 22 而已,清楚明瞭,系統配置預設也非常安全。這篇文章我就來分享如何對 SFTP 進行安全的設定,讓你在遠端檔案傳輸時能夠更加安全。
設定金鑰免密碼登入
Windows 版本的 OpenSSH Server 只能接受兩種認證方式 (AuthenticationMethods):
- Password-based authentication (
password
)
- Key-based authentication (
publickey
)
密碼驗證預設就是啟用的,而金鑰驗證則要特別設定 AuthorizedKeysFile 而且還要有正確的 NTFS 權限設定才能生效。詳見 Fix SSH file permissions 文章說明。
以下就是一個完整的設定過程步驟:
-
我們先在 Windows 主機建立一個帳號名稱為 user1
的使用者
你可以使用 net user
命令快速建立使用者:
net user user1 * /ADD
過程中需要設定 user1
帳號的密碼,需輸入兩次。
-
嘗試從登入這台 Windows 的 OpenSSH Server
我們可以用 ssh
命令直接登入 user1
使用者,預設會提示你要輸入密碼,這是 Windows OpenSSH 內建的 password
認證方法:
ssh user1@localhost
如果你想登入 AD 網域帳號,可以選擇以下任何一種語法:
ssh -l user@domain host
ssh domain\user@host
ssh user@domain@host
若要以 Kerberos Authentication 登入,可以參考這裡。
首次登入成功時 Windows 會自動建立 C:\Users\user1
這個所謂的 使用者設定檔 (User Profile
) 資料夾,在還沒有任何登入紀錄前,是沒有這個目錄的。但在第一次登入成功後,預設就會啟動 OpenSSH Server 設定好的 DefaultShell
(預設殼層),讓你可以進行遠端操作:
-
建立 .ssh
資料夾
只要是全新的使用者,我通常會在第一次遠端登入後立刻建立好一個 .ssh
資料夾:
mkdir .ssh
接著就可以輸入 exit
登出 Windows 遠端殼層環境。
我們也可以在第一次 SSH 連線時就直接建立 .ssh
資料夾,底下命令可以一口氣建立好 User Profile
資料夾與相對應的 .ssh
資料夾:
ssh user1@localhost mkdir .ssh
上述命令等於遠端登入 OpenSSH Server 並執行完 mkdir .ssh
之後自動登出。
-
建立 .ssh\authorized_keys
授權金鑰檔
如果你想從一台 Windows 的 ssh
使用 publickey
無密碼遠端登入到另一台 Windows 的 OpenSSH Server,那麼你需要先學會如何透過 PowerShell 建立 SSH 金鑰組。命令很簡單,底下這一行就可以搞定:
ssh-keygen -t rsa -b 4096 -f $HOME/.ssh/id_rsa -N '""'
注意:Windows 上的 ssh-keygen
的 -N
參數必須傳入 '""'
才能正確的產生出無密碼的私密金鑰,這很雷!
# 複製你的公開金鑰到遠端的 .ssh/authorized_keys 檔案中 (此命令會覆蓋此檔案)
scp $HOME/.ssh/id_rsa.pub 'user1@localhost:.ssh\authorized_keys'
PowerShell 預設就有一個跟 Linux 完全一樣的 $HOME
環境變數喔!
如果你想從一台 Linux 的 ssh
使用 publickey
無密碼遠端登入到另一台 Windows 的 OpenSSH Server,那麼你需要這樣建立 SSH 金鑰組:
ssh-keygen -t rsa -b 4096 -f $HOME/.ssh/id_rsa -N ''
# 複製你的公開金鑰到遠端的 .ssh/authorized_keys 檔案中 (此命令會覆蓋此檔案)
scp $HOME/.ssh/id_rsa.pub 'user1@172.23.64.1:.ssh\authorized_keys'
註1: 上述命令皆從 Linux 的 bash 環境下執行,路徑中有 \
的話,命令列參數一定要用單引號 '
框起來,否則路徑會有異常!
註2: 若 Windows 主機上的 .ssh\authorized_keys
檔案有自己以外的一般使用者可讀取的話,該檔案就會自動失效,這是 OpenSSH Server 預設的安全機制,所以請注意該檔案的 NTFS 檔案權限設定。詳見 Fix SSH file permissions 文章說明。
註3: 如果要在遠端殼層直接編輯文字檔,我會建議你安裝 Windows 版的 vim 來用!(choco install vim -y
)
-
接著你就可以免密碼登入了,安全又可靠!
ssh user1@localhost
若是在 CI/CD 的環境下連線,我們可能會需要透過 -i
指定自訂的私密金鑰,此時你可以這樣執行:
ssh -i .\id_rsa user@host
ssh -i .\id_rsa -l user@domain host
echo 'put -r shares/' | sftp -i .\id_rsa user@host:.
設定 sshd_config
的 ChrootDirectory
參數
我在設定 Windows 的 SFTP 支援時,通常會啟用 OpenSSH Server 的 ChrootDirectory
設定,將使用者透過 SFTP 登入時,限制在特定目錄下。這個設定在 Linux 設定 SFTP 的時候很常用,而 Windows 版的 OpenSSH Server 是從 v7.7.0.0
版 (2018/5/31)開始支援這個設定,如果你使用 Windows Server 2019 的 LTS 版本,記得要安裝最新版的 OpenSSH Server 才能正常使用。
通常我們會針對「特定使用者」不允許遠端登入,並且限制該使用者只能透過 SFTP 存取「特定資料夾」下的檔案,以增強檔案傳輸的安全性。
以下是設定步驟:
-
建立要讓 user1
使用者透過 SFTP 上傳/下載檔案的資料夾
你可以在 Windows 主機上設定任意一個資料夾,只要該資料夾的權限可以讓 user1
可讀或可寫即可。
mkdir C:\Files\user1
如果你直接用 C:\Files\user1\Downloads
目錄的話,就不用特別建立,可以直接使用。
-
編輯 $env:ProgramData\ssh\sshd_config
檔案
你只要從 Windows 開啟 $env:ProgramData\ssh\sshd_config
檔案,在該檔案最下方加入以下設定即可:
Match User user1
AllowTcpForwarding no
ChrootDirectory C:\Files\user1
ForceCommand internal-sftp
這裡的 Match User user1
就是只針對單一使用者 user1
進行設定,最後的 ForceCommand internal-sftp
就是為了讓該 user1
使用者無法遠端登入主機,只能使用 SFTP 傳檔而已。這裡最重要的當然就是 ChrootDirectory
設定,他會把使用者「關在」特定一個目錄下,遠端透過 SFTP 操作檔案時,是完全看不到 Windows 電腦中的任何其他資料夾! 👍
-
重新啟動 sshd
服務
Restart-Service sshd
測試 sftp 上傳檔案
-
將目前資料夾所有檔案上傳到遠端預設目錄
echo 'put -r *' | sftp user1@localhost:.
這個命令會連同所有子目錄一併上傳到遠端電腦。
-
將目前資料夾下的 shares/
資料夾中所有檔案上傳到遠端預設目錄
echo 'put -r shares/' | sftp user1@localhost:.
注意: 上傳到遠端的目錄下,不會有個 shares
資料夾,而是只有來源端 shares/*
底下所有內容。
-
批次上傳作業
假設你有一堆已知檔名的檔案要上傳,你可以把所有 sftp 命令都先寫好,並且一次套用上傳。
例如你的 batch_commands.txt
命令檔如下:
cd UploadFiles
put '046020882904913013298 20211028.pdf'
put '051725312905913026483 20211029.pdf'
接著你就可以用以下命令執行批次,sftp 會幫你依序執行所有命令:
cat batch_commands.txt | sftp user1@localhost
相關連結