SSH 的核心功能之一是通过公钥认证机制实现安全的用户身份验证,而 authorized_keys 文件是实现这一机制的关键组成部分。本文将详细介绍 authorized_keys 文件的语法规则、格式容忍度、配置选项以及最佳实践,旨在为系统管理员和开发者提供全面且准确的参考。


一、authorized_keys 文件概述

authorized_keys 文件是 SSH 服务器端用于存储客户端公钥的文件,通常位于用户的家目录下,例如 ~/.ssh/authorized_keys。当客户端尝试通过公钥认证登录时,SSH 服务器会检查此文件中的公钥是否与客户端提供的私钥匹配,从而决定是否允许登录。

1.1 文件作用

authorized_keys 文件的主要作用是:

  • 存储公钥:保存客户端的公钥,用于验证客户端的身份。
  • 控制访问权限:通过配置选项限制公钥的使用范围,例如限制来源 IP、命令执行等。
  • 提高安全性:相比密码认证,公钥认证更安全,减少了暴力破解的风险。

1.2 文件位置与权限

authorized_keys 文件默认位于用户的 ~/.ssh/ 目录下,文件名必须为 authorized_keys(不能随意更改)。文件和目录的权限要求非常严格,以确保安全性:

  • 文件权限:应为 600(仅文件拥有者可读写),使用命令 chmod 600 ~/.ssh/authorized_keys 设置。
  • 目录权限~/.ssh 目录权限应为 700(仅目录拥有者可读写执行),使用命令 chmod 700 ~/.ssh 设置。
  • 所有者:文件和目录的拥有者必须是用户本人,不能是 root 或其他用户。

如果权限设置不正确,SSH 服务器(通常是 sshd)会拒绝使用 authorized_keys 文件,导致公钥认证失败。

二、authorized_keys 文件的语法规则

authorized_keys 文件的每一行代表一个公钥条目,格式通常如下:

[选项] 密钥类型 密钥数据 [注释]

以下是对各部分的详细说明:

2.1 密钥类型

密钥类型指定了公钥的加密算法,常见的类型包括:

  • ssh-rsa
    基于 RSA 算法,兼容性强,常用于 2048/4096 位密钥,但安全性较低,不推荐新部署。
    私钥文件~/.ssh/id_rsa

  • ssh-dss
    基于 DSA 算法,已废弃,安全性弱,不推荐使用。
    私钥文件~/.ssh/id_dsa

  • ecdsa
    基于椭圆曲线数字签名算法,密钥短(256/384/521 位),安全性与效率兼顾。
    私钥文件~/.ssh/id_ecdsa

  • ed25519
    基于 Edwards 曲线(Curve25519),256 位密钥,现代首选,高效且抗量子攻击能力强。
    私钥文件~/.ssh/id_ed25519
    优势:生成快、签名快,推荐使用。

  • ecdsa-sked25519-sk
    支持 FIDO/U2F 硬件安全密钥的变种,增强安全性,适用于高安全场景。
    私钥文件:通常由硬件设备管理。

注意:公钥类型必须与客户端私钥匹配,例如 ed25519 公钥需对应 ed25519 私钥。

2.2 密钥数据

密钥数据是公钥的 Base64 编码内容,通常是一长串字符。例如:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD... user@example.com
  • 格式要求:密钥数据必须是有效的 Base64 编码,且与密钥类型一致。
  • 长度:视算法而定,例如 RSA 密钥通常较长(2048 位或 4096 位),而 ed25519 密钥较短(固定 256 位)。

2.3 注释

注释是可选部分,通常用于标识公钥的用途或拥有者,例如 user@example.combackup-key-2023。注释不影响认证过程,但便于管理多个公钥。

2.4 选项

选项(options)是 authorized_keys 文件的核心功能之一,用于限制公钥的使用。选项以逗号分隔,放置在行首,格式为:

option1="value1",option2="value2" keytype keydata [comment]

常用选项包括:

  • command=“命令”:强制执行特定命令,忽略客户端请求的命令。例如:

    command="/usr/bin/backup_script.sh" ssh-ed25519 AAAAB3N... backup@server
    

    客户端使用此公钥登录时,只能执行指定的 backup_script.sh

  • restrict:禁用所有默认功能(如终端、端口转发等),需显式指定允许的功能。

  • from=“pattern-list”:限制来源 IP 或主机名。例如:

    from="192.168.1.0/24,*.example.com" ssh-ed25519 AAAAB3N... user@host
    

    仅允许来自指定 IP 范围或域名的连接。

  • no-agent-forwarding:禁用 SSH 代理转发。

  • no-port-forwarding:禁用端口转发。

  • no-pty:禁用分配伪终端(PTY)。

  • no-X11-forwarding:禁用 X11 图形转发。

  • permitopen=“host:port”:限制允许的端口转发目标。例如:

    permitopen="localhost:22" ssh-ed25519 AAAAB3N... user@host
    
  • environment=“NAME=value”:设置环境变量。例如:

    environment="LOG_LEVEL=debug" ssh-ed25519 AAAAB3N... user@host
    

选项的顺序不影响功能,但必须在密钥类型之前,且每个选项以逗号分隔。

三、格式容忍度

authorized_keys 文件的格式虽然有严格定义,但 SSH 服务器(sshd)在解析时具有一定的容错性。以下是一些关键点:

3.1 空白字符

  • 行首和行尾空格:SSH 服务器会忽略行首和行尾的空白字符。例如:

       ssh-rsa AAAAB3N... user@host    
    

    与以下内容等效:

    ssh-rsa AAAAB3N... user@host
    
  • 选项与密钥之间的空格:选项和密钥类型之间必须有至少一个空格或制表符分隔,否则解析会失败。例如:

    command="echo hello"ssh-rsa AAAAB3N...  # 错误:缺少空格
    command="echo hello" ssh-rsa AAAAB3N...  # 正确
    

3.2 换行与空行

  • 多行公钥:SSH 服务器支持将长公钥拆分为多行,但必须使用反斜杠 \ 续行,且续行符后不能有空格。例如:

    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD... \
    continuation_of_key user@host
    
  • 空行:空行会被忽略,不影响解析。

  • 注释行:以 # 开头的行被视为注释,SSH 服务器会跳过。

3.3 错误容忍

  • 无效选项:如果某个选项拼写错误或不受支持,SSH 服务器通常会忽略该选项,但仍尝试使用公钥进行认证。例如:

    invalid_option="value" ssh-rsa AAAAB3N... user@host
    

    invalid_option 会被忽略,认证仍可能成功。

  • 格式错误:如果密钥类型或密钥数据无效,整行会被忽略,但不会影响其他有效行。例如:

    ssh-rsa INVALID_KEY user@host  # 无效,忽略
    ssh-ed25519 AAAAB3N... user@host  # 有效,正常处理
    

3.4 文件大小与性能

  • 文件大小authorized_keys 文件没有严格的大小限制,但过多的公钥(例如上千条)可能导致认证过程变慢。建议定期清理无用公钥。
  • 行长度:单行长度通常无严格限制,但过长可能导致编辑器或工具处理困难,建议使用续行符拆分。

四、配置示例

以下是一些实际的 authorized_keys 配置示例,展示不同场景的应用:

4.1 基本公钥认证

最简单的配置,仅包含密钥类型、密钥数据和注释:

ssh-ed25519 AAAAB3NzaC1lZDI1NTE5AAAAI... user@workstation

4.2 限制命令执行

强制客户端执行特定脚本,适用于自动化任务:

command="/usr/local/bin/backup.sh",no-pty,no-port-forwarding ssh-ed25519 AAAAB3N... backup@server

4.3 限制来源 IP

仅允许特定网络的客户端连接:

from="192.168.1.0/24" ssh-rsa AAAAB3N... admin@office

4.4 组合多个选项

综合使用多个选项,增强安全性:

restrict,command="/usr/bin/whoami",from="10.0.0.0/8",no-agent-forwarding ssh-ed25519 AAAAB3N... restricted@host

五、常见问题与排查

5.1 公钥认证失败

可能原因及解决方法:

  • 权限错误:检查 ~/.ssh/authorized_keys 的权限,确保分别为 700600
  • SELinux 或 AppArmor:某些系统(如 Red Hat 或 Ubuntu)可能启用 SELinux 或 AppArmor,限制文件访问。使用 restorecon 或调整策略解决。
  • 密钥类型不匹配:确保客户端私钥与服务器公钥类型一致。
  • 文件格式错误:检查是否有无效字符或格式问题,使用 ssh-keygen -y -P "" -f private_key 验证公钥。

5.2 选项未生效

  • 拼写错误:检查选项名称是否正确,例如 no-port-forwarding 而不是 no-port-forward
  • 优先级问题:某些选项(如 restrict)可能覆盖其他选项,需仔细检查组合逻辑。

5.3 日志分析

启用 sshd 的详细日志(在 /etc/ssh/sshd_config 中设置 LogLevel DEBUG),查看认证失败的具体原因。例如:

debug1: userauth_pubkey: test whether pkalg/pkblob are acceptable [preauth]

六、扩展与高级用法

6.1 AuthorizedKeysCommand

/etc/ssh/sshd_config 中,可以配置 AuthorizedKeysCommand 从外部源(如数据库)动态获取公钥,而不依赖 authorized_keys 文件。例如:

AuthorizedKeysCommand /usr/local/bin/fetch_keys.sh
AuthorizedKeysCommandUser nobody

脚本需返回符合 authorized_keys 格式的公钥列表。

6.2 证书认证

OpenSSH 支持基于证书的认证,authorized_keys 文件可存储证书公钥(以 cert-authority 开头)。例如:

cert-authority ssh-rsa AAAAB3N... ca@domain

此功能适用于大规模环境,需配合 CA 签名。

总结

authorized_keys 文件是 SSH 公钥认证的核心,提供了灵活而强大的身份验证机制。通过合理的语法配置和选项设置,可以实现高安全性和精细的访问控制。尽管格式具有一定容忍度,严格遵循权限管理和最佳实践仍是关键。希望本文的详细介绍能帮助读者更好地理解和使用 authorized_keys,从而构建更安全的远程访问环境。

更多推荐