問題背景
在 Jenkins 與目標服務器之間通過 SSH 進行自動化部署時,遇到以下錯誤:
com.jcraft.jsch.JSchException: Auth fail
核心原因分析
| 原因分類 | 具體表現 | 底層機制説明 |
|---|---|---|
| 密鑰格式不兼容 | -----BEGIN OPENSSH PRIVATE KEY----- 頭部的密鑰 |
Jenkins 使用的 JSch 庫僅支持舊版 PEM 格式(-----BEGIN RSA PRIVATE KEY-----) |
| 憑據配置錯誤 | Jenkins 憑據中用户名與目標服務器不匹配/私鑰內容缺失 | SSH 協議要求用户名與密鑰需嚴格匹配目標服務器用户體系 |
| SSH 服務限制 | 目標服務器禁用 RSA 算法(PubkeyAcceptedAlgorithms 未包含 ssh-rsa) |
OpenSSH 8.8+ 默認禁用 RSA-SHA1 算法,需顯式啓用兼容模式 |
| 文件權限問題 | .ssh 目錄權限為 755 或密鑰文件權限為 644 |
SSH 協議強制要求:
- 私鑰權限必須為 600
- .ssh 目錄權限必須為 700 |
| GSSAPI 干擾 | 日誌中出現 Unspecified GSS failure 錯誤 |
SSH 客户端/服務端默認啓用 GSSAPI 認證,與密鑰認證產生衝突 |
| Known Hosts 問題 | 首次連接時未記錄主機指紋 | SSH 協議安全機制要求驗證主機身份,未預置指紋時拒絕連接 |
技術細節擴展
1. 密鑰格式兼容性問題
# OpenSSH 新格式密鑰特徵
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAA...
# PEM 格式密鑰特徵(JSch 兼容)
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA3Zx4H...
2. RSA 算法兼容性配置
# 目標服務器 /etc/ssh/sshd_config 關鍵配置
PubkeyAcceptedAlgorithms +ssh-rsa # 顯式啓用 RSA 算法
HostKeyAlgorithms +ssh-rsa # 允許 RSA 主機密鑰
3. 權限問題觸發機制
# 錯誤權限時的典型日誌
debug1: identity file /var/lib/jenkins/.ssh/id_rsa type -1
debug1: identity file /var/lib/jenkins/.ssh/id_rsa-cert type -1
4. GSSAPI 衝突場景
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic
debug1: Next authentication method: gssapi-with-mic
debug1: Unspecified GSS failure. Minor code may provide more information
影響:GSSAPI 認證嘗試優先於密鑰認證,導致認證流程中斷
優先級排序
按問題出現頻率從高到低排序:
- 🔑 密鑰格式不兼容 (60%)
- 🔐 文件權限問題 (20%)
- 🖥️ SSH 服務配置限制 (10%)
- 📛 憑據配置錯誤 (5%)
- 🌐 GSSAPI/網絡問題 (5%)
分步解決方案全文
1. 密鑰格式轉換(解決 JSch 兼容性問題)
1.1 確認密鑰格式
# 切換到 Jenkins 用户並檢查私鑰
sudo su - jenkins
head -n 1 ~/.ssh/id_rsa
# 若輸出以下內容需轉換:
# -----BEGIN OPENSSH PRIVATE KEY-----
1.2 安裝轉換工具
# Ubuntu/Debian
sudo apt install putty-tools
# CentOS/RHEL
sudo yum install putty
1.3 執行格式轉換
# 轉換為 PEM 格式
puttygen ~/.ssh/id_rsa -O private-openssh -o ~/.ssh/id_rsa.pem
# 替換原密鑰文件
mv ~/.ssh/id_rsa.pem ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
1.4 驗證新密鑰
如果轉換不成功,直接以rsa格式重新生成。
# 確認新格式
head -n 1 ~/.ssh/id_rsa
# 期望輸出:-----BEGIN RSA PRIVATE KEY-----
# 手動測試連接
ssh -i ~/.ssh/id_rsa user@target-server
2. Jenkins 憑據配置
2.1 創建/編輯 SSH 憑據
- 訪問 Dashboard > Manage Jenkins > Credentials > System > Global credentials
- 點擊 Add Credentials
- 按以下規範配置:
Kind : SSH Username with private key
Scope : Global
ID : deploy-target-server (自定義唯一標識)
Username : 目標服務器真實用户名(如 ubuntu/ec2-user)
Private Key : Enter directly
Key : 粘貼 PEM 格式私鑰內容(包含 BEGIN/END 標記)
2.2 憑據驗證要點
3. 目標服務器 SSH 配置調整
3.1 修改服務端配置
sudo vi /etc/ssh/sshd_config
# 關鍵配置項
PubkeyAuthentication yes
PubkeyAcceptedAlgorithms +ssh-rsa # 顯式啓用 RSA 算法
HostKeyAlgorithms +ssh-rsa # 兼容舊版密鑰
3.2 應用配置
# 重啓 SSH 服務
sudo systemctl restart sshd
# 驗證配置生效
sshd -T | grep -E "pubkeyacceptedalgorithms|hostkeyalgorithms"
# 應包含 rsa-sha2-512,rsa-sha2-256 等算法
4. 文件權限修復
4.1 Jenkins 服務器權限
sudo chown -R jenkins:jenkins /var/lib/jenkins/.ssh
sudo chmod 700 /var/lib/jenkins/.ssh
sudo chmod 600 /var/lib/jenkins/.ssh/id_rsa
4.2 目標服務器權限
# 登錄目標服務器後執行
sudo chmod 700 ~/.ssh
sudo chmod 600 ~/.ssh/authorized_keys
sudo chown -R user:user ~/.ssh # user 替換為目標用户名
5. 處理 GSSAPI 錯誤
5.1 禁用客户端 GSSAPI
# 全局配置(/etc/ssh/ssh_config)
Host *
GSSAPIAuthentication no
GSSAPIDelegateCredentials no
# 用户級配置(~/.ssh/config)
echo -e "Host *\n GSSAPIAuthentication no" >> ~/.ssh/config
5.2 禁用服務端 GSSAPI
# 目標服務器配置(/etc/ssh/sshd_config)
GSSAPIAuthentication no
# 重啓服務
sudo systemctl restart sshd
6. 預置主機指紋(跳過首次驗證)
6.1 手動添加指紋
sudo su - jenkins
ssh-keyscan -H target-server-ip >> ~/.ssh/known_hosts
6.2 Pipeline 中禁用檢查
sh 'ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null user@target-server'
7. 完整驗證流程
7.1 手動模擬 Jenkins 環境
sudo su - jenkins
ssh -vvv -i ~/.ssh/id_rsa user@target-server
7.2 關鍵成功日誌
debug1: Offering public key: /var/lib/jenkins/.ssh/id_rsa
debug1: Authentication succeeded (publickey)
7.3 Pipeline 集成測試
pipeline {
agent any
stages {
stage('SSH Test') {
steps {
sshagent(['deploy-target-server']) { // 使用憑據 ID
sh '''
ssh -T user@target-server <<EOF
echo "Connection Successful!"
hostname
EOF
'''
}
}
}
}
}
附錄:輔助診斷命令
網絡連通性檢查
# 檢查 SSH 端口可達性
telnet target-server 22
nc -vz target-server 22
# 檢查 DNS 解析
nslookup target-server
密鑰對匹配性驗證
# 本地生成指紋
ssh-keygen -lf ~/.ssh/id_rsa.pub
# 目標服務器驗證指紋
ssh-keygen -lf ~/.ssh/authorized_keys
注意:所有操作需在 Jenkins 服務用户(通常為 jenkins)環境下執行,通過 sudo su - jenkins 切換身份。