问题背景

在 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-rsaOpenSSH 8.8+ 默认禁用 RSA-SHA1 算法,需显式启用兼容模式
文件权限问题.ssh 目录权限为 755 或密钥文件权限为 644SSH 协议强制要求:
- 私钥权限必须为 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 凭据

  1. 访问 Dashboard > Manage Jenkins > Credentials > System > Global credentials
  2. 点击 Add Credentials
  3. 按以下规范配置:
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 凭据验证要点

image.png

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 切换身份。


杨帆
28 声望3 粉丝