2341 字
12 分钟
SSH 公钥认证机制与 Linux 登录 SSH 配置

SSH 公钥认证机制与 Linux 登录 SSH 配置#

SSH(Secure Shell)是一种用于安全远程登录和通信的网络协议,广泛应用于 Linux 服务器管理、远程命令执行、文件传输以及代码仓库访问等场景

OpenSSH 是 SSH 协议最常见的实现,包含 ssh/sshd 等核心组件,并提供 ssh-keygen、ssh-agent、ssh-add 等辅助工具,用于完成基于公钥的身份认证与密钥管理

一、SSH 认证机制#

1.1 公钥/私钥体系#

  • 公钥(Public Key)

    • 存放于目标端(通常为 ~/.ssh/authorized_keys,具体取决于服务端 AuthorizedKeysFile 配置)
    • 用于验证客户端使用私钥签名的数据有效性
  • 私钥(Private Key)

    • 保存在本地(如 ~/.ssh/id_ed25519id_rsa 或自定义路径)
    • 用于对服务端发起的挑战(challenge)进行签名,以证明身份

SSH 客户端使用私钥生成签名,服务端用对应的公钥验证;验证通过即建立信任连接

1.2 多密钥尝试流程#

SSH 并非仅使用单一私钥,而是按以下顺序尝试多个来源:

  1. 启动 SSH 客户端并读取配置文件

  2. 收集可用私钥:

    • 已通过 ssh-add 加载至 ssh-agent 的密钥(优先级最高)
    • 命令行 -i 指定的私钥
    • ~/.ssh/config 中配置的 IdentityFile
    • 默认路径下的标准名称密钥(如 id_ed25519, id_rsa
  3. 依次使用这些私钥对服务端 challenge 进行签名

  4. 服务端用对应公钥验证签名

  5. 任一匹配成功即完成认证;否则返回 Permission denied (publickey)

NOTE

若自定义密钥未通过 ssh-add 加载到 ssh-agent ,即使 IdentityFile 已配置,也可能因 ssh-agent 为空而认证失败

二、ssh-keygen:密钥生成与管理#

2.1 核心功能#

  • 生成新的密钥对(.pub 公钥 + 私钥)
  • 为私钥设置或修改密码(passphrase)
  • 从私钥导出公钥
  • 转换密钥格式(OpenSSH ↔ PEM ↔ RFC4716)
  • 生成主机密钥(Host Key)

2.2 密钥算法建议#

算法推荐度说明
Ed25519强烈推荐安全性高、密钥短、性能优、现代系统默认支持
RSA (4096位)仅用于兼容旧系统避免使用 2048 位以下

2.3 基本语法与常用选项#

Terminal window
ssh-keygen [选项]
选项作用
-t <type>指定算法(ed25519,rsa
-b <bits>RSA 密钥长度(建议 4096)
-C "comment"添加注释(如邮箱、用途)
-f <file>指定密钥保存路径
-N "pass"设置私钥密码(-N ""表示无密码)
-p修改已有私钥密码
-y从私钥导出公钥
-e/-i公钥格式导出/导入
-o使用新 OpenSSH 私钥格式(更安全)
-q静默模式

2.4 使用示例#

以下示例展示 ssh-keygen常见使用场景下的典型用法

2.4.1 生成 Ed25519 密钥(推荐,默认路径)#

Terminal window
ssh-keygen -t ed25519 -C "your_email@example.com"
  • 适用于 单一身份、默认配置 的场景

  • 密钥默认生成在:

    • 私钥:~/.ssh/id_ed25519
    • 公钥:~/.ssh/id_ed25519.pub
  • 若文件已存在,ssh-keygen 会提示是否覆盖

2.4.2 生成 Ed25519 密钥并指定存放位置#

Terminal window
ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/id_ed25519
  • 适用于 多账号 / 多用途密钥管理 场景(如 GitHub、服务器区分)
  • 可配合 ~/.ssh/config 中的 IdentityFile 使用
  • 不会影响已有默认密钥

2.4.3 生成 RSA 4096 位密钥(兼容旧系统)#

Terminal window
ssh-keygen -t rsa -b 4096 -C "your_email@example.com" -f ~/.ssh/id_rsa -N ""
  • 仅在目标系统 不支持 Ed25519 时使用

  • -N "" 表示私钥不设置密码(自动化场景常见)

  • 生成文件:

    • 私钥:~/.ssh/id_rsa
    • 公钥:~/.ssh/id_rsa.pub

2.4.4 修改已有私钥的密码(不影响公钥)#

Terminal window
ssh-keygen -p -f ~/.ssh/id_rsa
  • 用于:

    • 为无密码私钥补充 passphrase
    • 定期轮换私钥密码
  • 不会改变密钥内容,公钥仍然有效

2.4.5 从私钥重新导出公钥#

Terminal window
ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub
  • 适用于:

    • 公钥文件丢失
    • 需要重新部署 authorized_keys
  • 前提是私钥仍然存在

  • 导出的公钥与原公钥完全一致

2.4.6 转换公钥格式(如 PEM)#

Terminal window
ssh-keygen -e -f ~/.ssh/id_rsa.pub -m PEM
  • 用于与 非 OpenSSH 工具或旧系统 兼容

  • 常见于:

    • 某些老版本 SSH
    • 第三方系统或设备

2.5 文件权限设置#

OpenSSH 在使用基于公钥的身份认证时,会对相关目录和文件的权限进行严格检查,以防止私钥或授权文件被其他用户篡改或读取 除权限外,OpenSSH 也会校验文件/目录属主是否为目标用户或 root(取决于场景),属主异常同样可能导致认证失败

2.5.1 权限要求#

  • ~/.ssh 目录:

    Terminal window
    chmod 700 ~/.ssh

    仅允许当前用户访问,防止他人向该目录注入恶意密钥。

  • 私钥文件(如 id_ed25519id_rsa):

    Terminal window
    chmod 600 ~/.ssh/id_*

    私钥必须仅对所有者可读写,否则 OpenSSH 会认为密钥不安全而拒绝使用。

  • authorized_keys 文件:

    Terminal window
    chmod 600 ~/.ssh/authorized_keys

    防止其他用户向该文件写入未授权的公钥。

  • 用户 home 目录:

    • 不应设置为 777
    • 通常要求为 755 或更严格

    如果 home 目录可被他人写入,OpenSSH 会认为认证环境不可信。

2.5.2 权限校验行为说明#

  • 权限检查发生在 认证阶段

  • 校验逻辑由 SSH 客户端 / 服务端 执行:

    • 客户端:检查私钥文件权限
    • 服务端:检查用户 home、.sshauthorized_keys
  • 一旦检测到权限过宽,认证流程会被中止

常见错误表现包括:

Permissions 0644 for 'id_rsa' are too open
Authentication refused: bad ownership or modes

三、SSH Agent 与 ssh-add#

3.1 ssh-agent 的作用#

  • 在内存中缓存私钥,避免重复输入 passphrase (如果设置了私钥密码)
  • 提供统一接口供 SSH 客户端调用签名操作
  • 增强安全性:私钥不直接暴露给客户端进程
  • 支持多密钥集中管理

3.2 工作机制#

  • 启动后生成两个关键环境变量:

    • SSH_AUTH_SOCK:Unix 域套接字路径,用于通信
    • SSH_AGENT_PID:agent 进程 ID
  • SSH 客户端通过这些变量与 agent 交互,请求签名

3.3 为何需要 ssh-add#

  • 将私钥显式加载到 agent 的内存中
  • SSH 连接时优先从 agent 获取可用密钥
  • 在使用非默认路径或多个密钥时,未加载则可能无法认证

建议配合 ~/.ssh/config 使用 IdentitiesOnly yes,确保仅使用指定密钥

3.4 使用示例#

3.4.1 Linux / macOS#

Terminal window
# 启动 agent
eval "$(ssh-agent -s)"
# 添加私钥
ssh-add ~/.ssh/ssh-github
# 查看已加载密钥
ssh-add -l
# 清空所有密钥
ssh-add -D

3.4.2 Windows(PowerShell)#

Terminal window
Set-Service ssh-agent -StartupType Automatic
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\ssh-github

3.4.3 通过 ~/.ssh/config 指定密钥#

通过 /.ssh/config 为特定主机指定端口、用户名与 IdentityFile,避免每次手动输入参数

Host github.com
HostName ssh.github.com
User git
Port 443
IdentityFile ~/.ssh/ssh-github
IdentitiesOnly yes

加载后测试连接:

Terminal window
ssh -T git@github.com

四、配置 Linux SSH 登录#

NOTE

目标:实现通过公钥认证登录 Linux 服务器 适用系统:Ubuntu、Debian、CentOS、Rocky、AlmaLinux 等

4.1 在客户端生成密钥对#

Terminal window
# 推荐:Ed25519
ssh-keygen -t ed25519 -C "your_email@example.com"
# 或兼容旧系统:RSA 4096
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
  • 默认保存路径:~/.ssh/id_ed25519(私钥)和 id_ed25519.pub(公钥)
  • 可选设置 passphrase(提升安全性)

4.2 确保服务端安装并启用了 SSH#

Terminal window
# Ubuntu / Debian
sudo apt update && sudo apt install -y openssh-server
# CentOS / Rocky / Alma (8+)
sudo dnf install -y openssh-server
# CentOS 7
sudo yum install -y openssh-server
# 启动并启用开机自启
sudo systemctl enable --now sshd
sudo systemctl status sshd

4.3 部署公钥至服务端#

4.3.1 自动部署(使用 ssh-copy-id)#

客户端执行:

Terminal window
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server_ip # user 为用户名,server_ip 为服务器 IP

该命令会自动创建 ~/.ssh/authorized_keys 并设置正确权限(600)

4.3.2 手动部署#

  1. 在客户端查看并复制公钥内容:

    Terminal window
    cat ~/.ssh/id_ed25519.pub
  2. 在服务端创建 ~/.ssh/authorized_keys 文件,并粘贴公钥内容

    Terminal window
    mkdir -p ~/.ssh
    chmod 700 ~/.ssh
    nano ~/.ssh/authorized_keys # 粘贴整行
    chmod 600 ~/.ssh/authorized_keys

4.4 配置 SSH 服务端参数#

编辑 /etc/ssh/sshd_config文件,并修改参数

PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PermitRootLogin prohibit-password # 允许 root 使用密钥登录,禁止密码
PasswordAuthentication yes # 暂时保留,便于调试
TIP

先保留密码登录,确认密钥认证成功后再禁用

重载配置(不中断现有连接):

Terminal window
sudo systemctl reload sshd

4.5 验证连接#

Terminal window
ssh -i ~/.ssh/id_ed25519 user@server_ip
  • 成功:直接进入 shell,无密码提示

  • 失败:启用详细日志排查:

    Terminal window
    ssh -v -i ~/.ssh/id_ed25519 user@server_ip

4.6 安全加固(可选)#

编辑 /etc/ssh/sshd_config文件,并修改参数

PasswordAuthentication no # 完全禁用密码登录
PermitRootLogin prohibit-password # 仅允许 root 使用密钥
AllowUsers alice bob deploy # 限制可登录用户
Port 2222 # 更改默认端口(减少扫描攻击)

重载服务:

Terminal window
sudo systemctl reload sshd

修改端口后需指定端口登录:

Terminal window
ssh -p 2222 -i ~/.ssh/id_ed25519 user@server_ip

五、常用 SSH 客户端命令#

命令用途
ssh user@host登录远程主机
ssh -p 2222 user@host指定端口
ssh -i key user@host指定私钥
ssh -T git@github.com测试 GitHub SSH
ssh -v user@host显示调试日志
scp file user@host:/path上传文件
scp user@host:/file .下载文件
rsync -avz -e ssh src/ user@host:/dst/同步目录
ssh -L 8080:localhost:80 user@host本地端口转发
ssh -R 8080:localhost:80 user@host远程端口转发
ssh-agent bash启动带 agent 的 shell
ssh-add key加载私钥到 agent
ssh-add -l列出 agent 中密钥
ssh-add -D清空 agent

六、常见问题排查#

现象可能原因解决方法
Permission denied (publickey)authorized_keys权限错误chmod 600 ~/.ssh/authorized_keys
仍提示输入密码公钥未生效 /PubkeyAuthentication no检查sshd_config和公钥内容
无法写入.ssh目录家目录权限过宽(如 777)chmod 755 ~.ssh设为 700
连接被拒SSH 未运行 / 防火墙阻断sudo ufw allow 22(或自定义端口)
Git 报错 Permission denied密钥未加载到 agentssh-add ~/.ssh/your_key
SSH 公钥认证机制与 Linux 登录 SSH 配置
https://www.self4m.com/posts/ssh-public-key-auth-linux-login/
✍️作者
Self4m
📅发布于
2025-09-09
©️许可协议
CC BY-NC-SA 4.0

商业用途必须事先获得作者授权;
非商业用途可以使用,但必须注明出处;
若有改编需采用相同许可协议发布。