跳到主要內容
AnyStorage
免費下載

SFTP 與 SSH 金鑰

SFTP Permission denied (publickey) 檢查清單

括號裡列的是伺服器還允許的驗證方式,不是失敗的那一個。怎麼讀 ssh -v,以及這句錯誤背後的七個原因。

OpenSSH 說 Permission denied (publickey) 究竟指什麼、伺服器堅持的檔案權限與金鑰格式,以及讓舊 RSA 金鑰失效的那次演算法變更。

sftp permission denied publickey,SFTP 公開金鑰驗證失敗,authorized_keys 權限

這一行,以及大家都讀錯的地方

sh

$ sftp alice@files.example.com
alice@files.example.com: Permission denied (publickey).

這句話在 OpenSSH 用戶端裡只有一個產生點,看它的格式字串最省事:

text

fatal("%s@%s: Permission denied (%s).",
    authctxt->server_user, authctxt->host, authlist);

最後那個欄位是 authlist——伺服器仍然願意接受的驗證方式清單,不是失敗的那個方式。所以 Permission denied (publickey) 的意思是:我把手上有的都試過了,伺服器只提供公開金鑰驗證,而我的金鑰沒被接受。如果它寫的是 (publickey,password),你還有密碼可退;既然沒有,就別再找密碼入口。

症狀、原因與處理
你看到什麼原因處理
立刻失敗,-v 沒有 "Offering public key"用戶端根本沒找到/沒送出金鑰-iIdentitiesOnly yes
-v 送了金鑰,伺服器仍然拒絕authorized_keys 裡沒有,或使用者名稱不對檢查目標帳號下的那份檔案
一個使用者可以,另一個不行~~/.sshauthorized_keys 的權限目錄 700,檔案 600
-v 出現 "no mutual signature algorithm"OpenSSH 8.8 起 ssh-rsa 預設被停用換金鑰型別,或按主機重新啟用
伺服器日誌寫 "invalid format"金鑰檔不對:.ppk,或把公開金鑰當私密金鑰轉成 OpenSSH 格式
Windows 上只有管理員帳號失敗沒用 administrators_authorized_keys寫那個檔案,修好它的 ACL
只在指令碼或跳板機裡失敗沒有 agent,或 agent 沒轉送ssh-addForwardAgent 要有意識地用

1. 先讀 verbose 日誌

在看到用戶端自己對這次交握的記錄之前,下面全部只是猜測。

sh

ssh -v alice@files.example.com
sftp -v alice@files.example.com

三行字帶著答案,而且都是 OpenSSH 原始碼裡的字面字串。Authentications that can continue: publickey 是伺服器的方式清單;Offering public key: /Users/alice/.ssh/id_ed25519 表示用戶端真的送出了這把金鑰——若這行不存在,問題完全在用戶端;no mutual signature algorithm 則是第 4 步的演算法不相符。

伺服器端把 sshd_config 的日誌等級調高:LogLevel 接受 QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, DEBUG3,預設 INFO。要記錄金鑰指紋,VERBOSE 就夠;手冊明確警告以 DEBUG 等級記錄「violates the privacy of users and is not recommended」。

2. 兩端的權限都要修

這是伺服器端最常見也最不顯眼的原因:金鑰是對的,但放在別人可寫的目錄裡,就會被靜默忽略。sshd 手冊寫得很清楚,~/.ssh「the recommended permissions are read/write/execute for the user, and not accessible by others」,~/.ssh/authorized_keys「the recommended permissions are read/write for the user, and not accessible by others」。原因緊接其後:「If this file, the ~/.ssh directory, or the user's home directory are writable by other users, then the file could be modified or replaced by unauthorized users」,這種情況下「sshd will not allow it to be used unless the StrictModes option has been set to 'no'」。而 StrictModes 預設就是 yes

sh

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod go-w ~
ls -ld ~ ~/.ssh ~/.ssh/authorized_keys

用戶端同理:能被別人讀取的私密金鑰會被 ssh 自己拒絕,chmod 600 ~/.ssh/id_ed25519

3. 檢查檔案、格式與使用者名稱

authorized_keys 一行一把金鑰,手冊把欄位描述為「options, keytype, base64-encoded key, comment」,其中 options 可省略。複製貼上或瀏覽器下載塞進來的換行會把 base64 切斷,那一行就靜默失效。

sh

ssh-keygen -lf ~/.ssh/id_ed25519.pub
tail -c 100 ~/.ssh/authorized_keys | cat -A | tail -2

同一族還有兩件事。金鑰必須在你登入的那個帳號的 authorized_keys 裡,所以拿 alice 的金鑰去 sftp root@host 一定失敗。另外 sshd_configAuthorizedKeysFile 可以指向別處——手冊說它「may include wildcards」並支援 token,所以強化過的主機可能讀的是 /etc/ssh/keys/%u 而不是家目錄。

4. 讓舊 RSA 金鑰失效的那次演算法變更

如果一把用了好幾年的金鑰突然不行,先看這條。OpenSSH 8.8 的發行說明寫著:「This release disables RSA signatures using the SHA-1 hash algorithm by default. This change has been made as the SHA-1 hash algorithm is cryptographically broken.」被停用的是 ssh-rsa 這個簽章演算法,不是 RSA 金鑰本身。

ssh_configPubkeyAcceptedAlgorithms 的現行預設清單包含 rsa-sha2-512rsa-sha2-256,沒有 ssh-rsa。自己機器上的狀況可以直接問:

sh

ssh -Q PubkeyAcceptedAlgorithms

發行說明給的臨時辦法是按目標主機重新啟用,同時把這件事定位為「only as a stopgap measure until legacy implementations can be upgraded or reconfigured with another key type (such as ECDSA or Ed25519)」:

text

Host old-host
    HostkeyAlgorithms +ssh-rsa
    PubkeyAcceptedAlgorithms +ssh-rsa

+ 表示追加到預設集合,- 表示移除,^ 表示放到最前。更好的辦法是換新金鑰:ssh-keygen -t ed25519

5. agent、通關密語,以及金鑰太多的問題

私密金鑰有通關密語而環境裡沒人會彈窗(cron、CI、GUI 應用)時,用戶端沒辦法解開它。裝進 agent 一次就好:

sh

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
ssh-add -l

反向的失敗也存在。MaxAuthTries 預設是 6,如果 agent 一次遞上十幾把金鑰,用戶端還沒輪到對的那把就被切斷。解法是 IdentitiesOnly:它讓 ssh「only use the configured authentication identity and certificate files … even if ssh-agent or a PKCS11Provider or SecurityKeyProvider offers more identities」。

sh

ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 alice@files.example.com

跳板機優先用 ProxyJump,而不是轉送 agent。真要轉送就按主機開,不要做成全域設定。

6. Windows 伺服器有第二份金鑰檔

這個陷阱很費時間,因為通用教學在你最可能用來測試的那類帳號上剛好是錯的。微軟文件說得很直接:管理員使用者的公開金鑰要放進 C:\ProgramData\ssh\ 下的 administrators_authorized_keys,而且「This file only applies to administrator accounts. You must use it instead of the user-specific file within the user's profile location.」ACL 必須只允許管理員與 SYSTEM:

powershell

icacls.exe "$env:ProgramData\ssh\administrators_authorized_keys" /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"

同一頁還有兩個註記:Windows OpenSSH 不支援 AuthorizedKeysCommandAuthorizedKeysCommandUser;金鑰驗證對本機帳號與 Active Directory 帳號有效,但 Microsoft Entra ID 帳號不支援。

金鑰通了之後

驗證修好之後,剩下的問題是這條連線要拿來做什麼。AnyStorage(v0.2.24;macOS 11+、Windows 10+、Ubuntu 20.04+)支援以金鑰驗證連線 SFTP 主機,和 S3 相容端點、WebDAV 放在同一個視窗,免費版可用兩個連線。想把主機當成磁碟機而不是檔案清單時,它透過內建的本機 WebDAV 服務(http://127.0.0.1:3211)掛載——不用 FUSE、WinFsp、macFUSE,也就不必在剛解決的金鑰問題上再疊一層 sshfs 的除錯。

(publickey) 是不是說我的金鑰錯了?

它說的是伺服器只接受公開金鑰驗證,而你提供的東西沒有滿足它——這也包含「你什麼都沒提供」。所以 ssh -v 與 "Offering public key" 那一行才是第一步。

為什麼 ssh 進得去,sftp 不行?

驗證相同,服務不同。如果金鑰能過 sshsftp 在後面失敗,去看 sshd_config 裡的 Subsystem 行(sftp-serverinternal-sftp),以及 ChrootDirectory——它的權限與擁有者是被 sshd 無條件檢查的。

我的舊 RSA 金鑰還能用嗎?

只要它是長度足夠的真 RSA 金鑰就能用:現代的 rsa-sha2-256rsa-sha2-512 簽章演算法用的是同一把金鑰。預設被停用的只是 SHA-1 的 ssh-rsa 簽章。

.ppk 檔可以直接用嗎?

不行。PuTTY 的格式是自己的,用 PuTTYgen 的 Conversions 選單匯出成 OpenSSH 私密金鑰,或用 ssh-keygen 重新產生一對。

下一步