ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux SSH RSA免密登录:原理、两种配置与排错指南

Linux SSH RSA免密登录:原理、两种配置与排错指南 平时维护十几台机器一天下来 ssh 要敲几十次密码输到手指发酸是常有的事。后来我把所有固定工作节点都换成了Linux 系统下 ssh rsa 免密登录从本地开发机到测试环境、再到线上跳板机一条ssh web01直接落到目标主机的 shell 里整个流程干净利落。这个东西听起来像入门级操作但真到了生产环境权限、SELinux、SSH 版本差异、旧客户端兼容性这些问题一冒出来不少做了几年运维的朋友也会卡住。我把实际用过、踩过、修过的内容整理成这篇重点说清楚ssh免密登录的两条落地路径以及背后的原理顺便把排查思路和常见坑点讲透。刚接触 Linux 的朋友可以照着做已经有基础的读者也能从原理和排错部分补上容易忽略的细节。1. 先弄明白免密登录到底免掉了什么1.1 一次普通 ssh 登录在背后走了哪些步骤很多人对 ssh 的理解停留在远程连上去敲命令实际上一次完整的连接要经过好几个阶段。第一段是 TCP 握手客户端向目标主机的 22 端口或者你自定义的端口比如 22022发起连接第二段是版本协商双方互报协议版本类似SSH-2.0-OpenSSH_8.9第三段是算法协商把后续要用到的密钥交换算法、主机密钥算法、对称加密算法、消息认证码算法全部谈妥第四段是密钥交换这一步会生成一个只有两端知道的会话密钥用于加密后面的所有通信第五段是服务端要求客户端做身份认证第六段才是真正的用户认证也就是我们常说的输密码或者用密钥环节。免密登录省掉的是第六段里的密码输入前面五段该走的流程一步都没少这就解释了为什么配置好密钥之后第一次连接仍然可能弹出一个主机指纹确认的提示。理解这个分层结构之后后面遇到的很多报错就能快速定位。比如提示Connection refused大多停在第一段说明对方端口没开、sshd 没启动或者防火墙拦住了提示Host key verification failed问题出在主机密钥校验环节跟你的用户密钥没有半点关系提示Permission denied (publickey)才轮到用户认证阶段的密钥出问题。我在实际排查时习惯先用ssh -vvv userhost把全过程打印出来看卡在哪一段比盲目改配置文件高效得多。1.2 密码认证和公钥认证的核心差异密码认证的逻辑很直白客户端把用户名送过去服务端说请出示密码客户端把密码发过去服务端比对/etc/shadow里的哈希值。整个过程里密码需要通过网络传输虽然是在加密通道内而且服务端手里握着可以验证你身份的东西一旦服务端被攻破弱密码用户就非常危险。公钥认证的思路完全不同客户端手里有一份私钥服务端手里存着一份对应的公钥认证时客户端用私钥对一段挑战数据做签名服务端用公钥验证签名是否成立。私钥全程不离开客户端网络上传输的只是签名结果即使被截获也无法反推出私钥。从这个差异可以看出免密登录并不是服务端认识你所以免密而是你手里有对应的私钥所以服务端相信是你。这也是为什么authorized_keys文件如此重要往里写一行公钥就等于给持有对应私钥的人开了一扇门。反过来删掉一行门就关了不需要改动任何密码不需要重启服务这一点在人员变动、临时授权、紧急回收权限的场景里非常方便。我在给外包同事开临时通道时就是当天加一行公钥项目结束当天删掉比发账号密码干净得多。1.3 RSA 在 ssh 里到底扮演什么角色很多人会把三件事混在一起密钥交换算法、主机密钥、用户认证密钥。RSA 在这三个地方都可能出现但含义完全不同。密钥交换阶段双方要协商出一个共享的会话密钥老版本协议里可能用到 diffie-hellman-group1-sha1 这类算法扫描器报目标主机支持 rsa 密钥交换往往指的是这一段主机密钥是服务端的身份证明客户端第一次连接时把它记到known_hosts里防止连到假冒服务器用户认证密钥才是本文要讲的主角也就是你本地生成、公钥上传到目标机authorized_keys的那一对。需要特别澄清一个常见误解SSH 公钥认证用的是 RSA 的签名能力不是加密能力。RSA 算法的基本原理是选取两个大素数 p 和 q算出模数 n p × q 和欧拉函数 φ(n)再选一个与 φ(n) 互素的公钥指数 e计算出满足 e × d ≡ 1 (mod φ(n)) 的私钥指数 d。公钥是 (n, e)私钥是 (n, d)。加密时用公钥计算解密时用私钥还原签名时反过来用私钥生成签名用公钥验证。SSH 认证走的是后一条路客户端用私钥对会话标识和挑战数据做签名服务端用authorized_keys里的公钥验证签名。软考信息安全工程师里那些 RSA 计算题问的是加解密流程和 SSH 免密登录的实现不是同一套用法别把两者直接划等号。2. 方式一ssh-copy-id 一键分发公钥2.1 生成 RSA 密钥对时参数怎么定第一步永远是在本地生成一对密钥。命令不长但每个参数都值得说清楚ssh-keygen -t rsa -b 4096 -C opsexample.com deploy-2024 -f ~/.ssh/id_rsa_deploy-t rsa指定密钥类型为 RSA-b 4096指定密钥长度4096 位是当前比较稳妥的选择虽然 RSA 密钥越长签名越慢但对人工登录来说那点延迟完全感知不到-C是注释默认会写上userhostname我习惯写成用途加日期比如deploy-2024这样在多台机器上看到某一行的来源时能立刻判断是哪个环境、哪一年加的-f指定输出路径避免覆盖默认的~/.ssh/id_rsa。生成过程中会询问是否设置口令passphrase这个口令是用来加密私钥文件本身的如果不设置私钥就是明文文件任何拿到这个文件的人都能免密登录。我的建议是个人开发机可以不设口令图方便但涉及跳板机、生产环境的私钥一定要设口令再配合ssh-agent使用。设置了口令之后用eval $(ssh-agent -s)启动代理再ssh-add ~/.ssh/id_rsa_deploy输入一次口令后当前会话内的后续连接就都不用再输了。这样做的好处是私钥文件即使被拷走没有口令也无法直接使用。生成完成后会得到两个文件id_rsa_deploy是私钥权限自动设为 600绝对不要外传id_rsa_deploy.pub是公钥内容是一行以ssh-rsa开头的长字符串权限通常是 644可以随便复制。用ssh-keygen -lf ~/.ssh/id_rsa_deploy.pub可以查看密钥指纹后面在服务端核对时很有用。2.2 ssh-copy-id 到底替你做了哪些事ssh-copy-id本质上是一个 shell 脚本不是什么魔法命令。以 Ubuntu 为例它躺在/usr/bin/ssh-copy-id你可以直接cat出来看。它做的事情分三步首先用你指定的公钥文件连接目标主机然后在远端执行类似umask 077; mkdir -p ~/.ssh chmod 700 ~/.ssh的命令确保目录存在且权限收紧最后把公钥内容追加到~/.ssh/authorized_keys里并且保证该文件权限为 600。整个过程是幂等的较新版本的脚本会先算一遍公钥指纹如果目标机的authorized_keys里已经有同一条就跳过不会重复追加。一条典型用法是这样的ssh-copy-id -i ~/.ssh/id_rsa_deploy.pub -p 22022 deploy10.0.0.21-i指定公钥文件注意这里给的是.pub结尾的公钥不是私钥-p指定目标机 sshd 的端口最后是用户名和主机。执行时会要求输入一次目标机账户的密码输入完成后脚本自动完成目录创建、权限设置、公钥追加三件事并在输出里提示公钥已添加。之后再执行ssh -i ~/.ssh/id_rsa_deploy -p 22022 deploy10.0.0.21如果直接进入 shell 而没有要求密码就说明配置成功。如果目标机不是标准 OpenSSH比如某些精简嵌入式系统或者 Windows 上的第三方 SSH 服务端本地可能没有ssh-copy-id这时候就得用手工方式也就是下一章要讲的内容。另外ssh-copy-id 需要一个能登录的密码账号作为跳板如果目标机已经彻底关闭密码登录它就走不通了只能靠已有密钥通道或者控制台把公钥送进去。2.3 验证连接和常用参数组合配置完成后的验证环节不能少最直接的验证就是不带密码登录一次ssh -i ~/.ssh/id_rsa_deploy -p 22022 -o IdentitiesOnlyyes deploy10.0.0.21 hostname; whoami这里多加了-o IdentitiesOnlyyes作用是只使用-i明确指定的私钥不去尝试ssh-agent或者默认路径下的其他密钥。为什么这个参数这么有用因为当客户端手里有一堆密钥时ssh 会按顺序逐个试探服务端服务端的MaxAuthTries默认是 6如果前面几个都不匹配认证次数耗尽后就会直接拒绝报出来的错误还可能是Permission denied (publickey)让人误以为是密钥配错了。显式指定私钥再加上这个选项可以避开绝大多数密钥明明是对的却连不上的情况。实际工作中我常用的参数还有几个-v打印基础调试信息看协商过程-vvv打印最详细的日志排错时必用-p指定端口-o ConnectTimeout5设置连接超时脚本里避免卡住-o StrictHostKeyCheckingaccept-new在自动化场景下首次连接自动信任主机密钥但要明白这等于跳过了主机身份确认只适合内部可控网络。配置无误的情况下可以直接把这些参数固化到~/.ssh/config里后面只需要ssh web01一个短命令Host web01 HostName 10.0.0.21 User deploy Port 22022 IdentityFile ~/.ssh/id_rsa_deploy IdentitiesOnly yes ServerAliveInterval 30ServerAliveInterval 30表示每 30 秒发一次心跳包防止长时间不操作被防火墙或者负载均衡设备断开连接。写进配置文件之后本地开发环境、VSCode Remote-SSH、Git 客户端都可以复用同一套主机别名管理成本大幅下降。2.4 方式一实操心得与注意点ssh-copy-id用起来舒服但它也有几个容易忽略的细节。第一它默认会依次尝试~/.ssh/id_rsa.pub、~/.ssh/id_dsa.pub等默认路径如果你不显式用-i指定很可能把错误的公钥推上去。我养成习惯无论本地有几对密钥只要不是默认那一对就一定带-i。第二脚本追加公钥时会自己处理权限但如果你在目标机上做过自定义改动了比如把authorized_keys改成了其他路径ssh-copy-id 就不知道它会往默认位置写然后你在 sshd_config 里配置的是别的文件结果就是白忙一场。第三目标机的家目录权限很关键。如果家目录本身是 777或者属主不是登录用户sshd 在检查时会认为这个环境不可信直接忽略authorized_keys表现就是公钥明明写进去了登录时依然要密码。这类问题用namei -l ~/.ssh/authorized_keys一笔就能看出来它会逐级列出路径上每一层目录的权限和属主。最后提醒一句如果目标机的 sshd 已经配置成PasswordAuthentication no那ssh-copy-id的首次认证会直接被拒因为第一阶段仍然需要密码。这种情况下只能通过控制台、云厂商的 VNC或者已有密钥通道把公钥送进去。这也是我推荐在服务器初始化阶段就把公钥配好、随后再关闭密码登录的原因。3. 方式二手工追加 authorized_keys 彻底掌握细节3.1 手工方式的精确操作步骤手工方式看起来原始但它才是理解整个机制的正道。假设你已经在本地生成好了密钥对现在要在目标机上配置。先登录目标机然后依次执行mkdir -p ~/.ssh chmod 700 ~/.ssh touch ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys四步动作顺序别乱。先建目录并设为 700表示只有属主可以读写和进入再创建文件并设为 600表示只有属主可以读写。很多人只关注文件权限忽略了目录权限结果 sshd 在StrictModes开启默认开启的情况下会检查整条路径只要有一层比预期宽松就会拒绝使用该文件。同样的道理用户家目录也不能是组可写或者其他用户可写chmod g-w,o-w ~这种收尾动作值得养成习惯。接下来把本地公钥的内容追加进去。可以在本地执行cat ~/.ssh/id_rsa_deploy.pub复制输出内容粘贴到目标机的~/.ssh/authorized_keys末尾保证是一整行中间不要人为换行。公钥内容很长手工复制容易出错更稳妥的方式是直接用管道传输下一小节讲。追加完成后先别急着退出当前登录另外开一个终端测试新的密钥连接确认没问题再关闭会话这是防止把自己锁在门外的保命操作。3.2 用一条 ssh 命令远程完成追加真正在生产上手动操作时我更喜欢用一条命令把公钥送过去不用登录进去折腾cat ~/.ssh/id_rsa_deploy.pub | ssh -p 22022 deploy10.0.0.21 \ umask 077; mkdir -p ~/.ssh cat ~/.ssh/authorized_keys chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys这条命令的精髓在于umask 077。它保证在远端新建文件时默认权限就是 600 或者更严格避免出现文件刚建好时短暂处于宽权限状态的情况。有人会问为什么不写成ssh userhost echo 内容 ...因为反引号、双引号、$符号在多层 shell 解析时会互相干扰公钥里虽然没有这些字符但一旦养成用管道传递的习惯处理更复杂的场景也更稳。还有一种写法利用输入重定向把本地文件直接喂给远端的catssh -p 22022 deploy10.0.0.21 \ mkdir -p ~/.ssh chmod 700 ~/.ssh cat ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys \ ~/.ssh/id_rsa_deploy.pub两种写法效果等价选哪个看你顺手。要注意的是执行这类命令时远端账户仍然需要密码认证所以整个过程会提示输入一次密码。如果你处于完全无密码可用的环境那就只能借助云控制台或者其他带外通道先把公钥种进去。3.3 权限、属主与 SELinux 这三个坑权限问题排在免密登录失败原因的第一位我见过太多人在本地反复生成密钥实际上是目标机的权限不对。核心规则可以记成一句话~/.ssh是 700authorized_keys是 600家目录不能被组和其他用户写入。sshd 的StrictModes默认是 yes它会对这些路径逐级检查发现不符合预期就忽略对应文件然后回落到密码认证。日志里会留下Authentication refused: bad ownership or modes for file这样的记录tail -f /var/log/secure或者journalctl -u sshd -f可以直接看到。属主问题也常见尤其是用sudo复制文件的时候。比如你执行了sudo cp id_rsa.pub ~/.ssh/authorized_keys在部分系统里文件属主会变成 root而登录用户不是 rootsshd 检查时就会认为文件归属不对。正确做法是用登录用户自己的身份操作或者复制完成后chown deploy:deploy ~/.ssh/authorized_keys修正。SELinux 是第三个坑主要出现在 CentOS、Rocky、AlmaLinux、龙蜥 8 这类系统上。文件的读写位都对但 SELinux 安全上下文不对sshd 照样读不了。判断方法是查看ls -Z ~/.ssh正常应该带上ssh_home_t这样的类型标签。如果显示的是user_home_t或者其他类型执行restorecon -Rv ~/.ssh让它恢复到默认上下文即可。临时验证也可以先setenforce 0试一下如果能连上、恢复 enforcing 又不行基本就能锁定是 SELinux 引起的。生产环境别长期关闭 SELinux用restorecon处理才是正路。3.4 多公钥共存与去重技巧authorized_keys是一个纯文本文件每行一条公钥支持同时存在多条记录。这意味着你可以把自己笔记本、台式机、跳板机的公钥全部放进去也可以给团队成员各留一条。追加时最怕的是把原有内容覆盖掉所以我在做任何修改之前都会先备份cp ~/.ssh/authorized_keys ~/.ssh/authorized_keys.bak.$(date %F)追加前先检查是否已存在同一条公钥用指纹比对最可靠ssh-keygen -lf ~/.ssh/authorized_keys | sort输出的每一行是位长、指纹和注释指纹重复说明密钥已经加过。手工去重时可以借助sort -u做一次清洗但要注意这会改变行序通常无害前提是你确认注释字段不会影响已有策略。如果authorized_keys里配置了带有command或者from的复杂选项行就别用这种简单清洗方式了那些行的字段结构更复杂容易破坏语义。多人协作的场景下我建议给每个密钥写好注释格式统一成姓名-用途-日期这样过一段时间回来审计一眼就能看出哪条是谁的。删掉某条公钥后不需要重启 sshd下一次连接就会生效因为 sshd 是在认证时读取这个文件的。清理离职人员权限时这个特性非常实用。4. 公钥认证在 sshd 侧到底怎么校验4.1 认证阶段的数据流与签名验证先给结论SSH 公钥认证不是服务端用公钥加密东西发给客户端解而是客户端用私钥签名服务端用公钥验签。具体流程可以拆成三次交互。第一次客户端告诉服务端我想用 publickey 方式认证我持有的公钥指纹是某某某注意这一步并不发送完整公钥只是试探第二次服务端收到指纹后去authorized_keys里查如果找到匹配的公钥就回复这个公钥我认识你可以证明你持有私钥并附上一段随机的挑战数据第三次客户端用私钥对包含会话标识的挑战数据做签名把签名结果发回服务端用保存的公钥验证签名通过则认证成功。这里有个细节很多人不知道服务端其实是在第二次交互后才真正读取authorized_keys而且它是按照文件中的行顺序去匹配指纹的。所以如果authorized_keys里有几千行认证会有可感知的延迟这也是大规模场景下推荐按用户或按用途拆分文件、使用AuthorizedKeysFile指定多个路径的原因。至于私钥到底签了什么SSH 协议里签名的是会话标识 session_id 用户认证请求的部分数据会话标识在密钥交换阶段就已经由双方共同确定客户端无法伪造。服务端验签时重新计算同样的内容因此攻击者即便截获了签名也无法在另一条会话里重放因为会话标识变了。4.2 authorized_keys 的格式与可选限制项一行典型的authorized_keys记录由三部分组成密钥类型、Base64 编码的密钥数据、注释。如果你在文件里看到ssh-rsa AAAAB3NzaC1yc2E... opsexample.com其中ssh-rsa只是表示这行是 RSA 类型的公钥后面那一长串才是真正的数据注释部分不参与任何计算可以随便改。这里再强调一次前面提到过的点OpenSSH 8.8 之后默认禁用的是ssh-rsa这个签名算法基于 SHA-1不是禁用 RSA 密钥本身RSA 密钥依旧可以正常工作只是签名时会走rsa-sha2-512或rsa-sha2-256。看到RSA 被禁用的说法先别慌先看清楚说的是算法还是密钥类型。authorized_keys还支持在行首加限制选项实现在密钥能登录的基础上进一步收紧权限。常见的几个选项作用典型用法from限制来源 IP 或网段from10.0.0.0/24command登录后只能执行指定命令备份机只允许执行 rsyncno-pty不允许分配终端自动化拉取任务no-port-forwarding禁止端口转发降低横向移动风险restrict一次性关闭多项能力显式白名单后再放开给自动化任务专用的密钥加上command和no-pty是很好的安全习惯万一密钥泄露攻击者也无法直接拿到交互式 shell。语法上这些选项要写在行首用逗号分隔然后才是密钥类型和数据写错一个标点就会导致整行失效。4.3 known_hosts 和免密登录不是一回事新手最容易混淆的两个文件是authorized_keys和known_hosts。前者放在服务端存的是允许登录的客户端公钥后者放在客户端存的是服务端的主机密钥指纹。第一次连接某台服务器时客户端会弹出The authenticity of host ... cant be established的提示让你确认指纹这一步做的是服务端身份验证跟免密登录没有关系即使你已经配好了密钥这个提示照样可能出现。如果服务端重装了系统或者换了主机密钥客户端会报REMOTE HOST IDENTIFICATION HAS CHANGED然后拒绝连接。处理方式是用ssh-keygen -R 主机名或IP删除旧记录重新连接并确认新指纹。这一步在批量脚本里会让任务直接失败所以自动化场景通常配合ssh-keyscan提前把主机密钥收集好再通过ssh-keygen -H -f known_hosts做哈希处理。要清楚这么做放宽了主机身份验证只适合在可控的内网环境使用。StrictHostKeyCheckingaccept-new是较新版本 OpenSSH 提供的折中选项首次连接自动接受之后如果密钥变化仍然会报错比直接设成no要安全一些。我在内部环境的初始化脚本里会用这个参数公网服务器则坚持人工核对指纹。4.4 为什么必须是私钥签名而不是公钥加密假设反过来设计服务端拿客户端的公钥加密一段随机数发给客户端客户端用私钥解密后返回这也是能证明持有私钥的。早期确实有人这么想过但这种方案有个明显缺陷它把签名能力变成了加密能力而公钥加密方案在有量子计算威胁或者算法实现缺陷时风险面更大同时它还容易受到选择密文攻击。相比之下签名方案可以附带完整的会话上下文天然抗重放语义也更清晰——我用私钥对这条会话声明签名而不是我帮你解密一段数据。从工程角度看签名还有一个好处是可以扩展成证书体系。SSH 支持用 CA 对公钥签名服务端只需信任 CA 的公钥就能动态认可大量用户密钥省去逐台分发authorized_keys的麻烦。这套机制的底层仍然是签名验证理解了authorized_keys的单机模式再往上看证书模式就顺理成章了。5. 常见问题与排查实录5.1 Permission denied 的排查顺序看到Permission denied (publickey)别急着重生成密钥按下面这个顺序排查效率最高。第一步本地确认私钥存在、权限为 600且与目标机authorized_keys里那一行是同一对。用ssh-keygen -lf分别查看两者的指纹比对是否一致。第二步用ssh -v连接观察输出里有没有Offering public key以及后面紧跟的Server accepts key。如果只有前者、没有后者说明服务端没匹配上问题在目标机的authorized_keys或权限如果根本没有Offering public key说明客户端没找到对应的私钥检查-i路径和IdentitiesOnly配置。第三步上目标机看日志。RHEL 系通常是/var/log/secureDebian 系是/var/log/auth.log用journalctl -u sshd也能看到。日志会明确指出是权限问题、属主问题还是找不到文件。第四步确认sshd_config里的PubkeyAuthentication没有被关掉AuthorizedKeysFile指向的路径和你实际写公钥的路径一致。改完配置先用sshd -t做语法检查再systemctl reload sshd平滑重载别直接重启避免影响在线连接。5.2 ssh -v 日志里最值得看的那几行ssh -v输出内容很多抓住几个关键节点就够了。debug1: Authenticating to 10.0.0.21:22022 as deploy表示认证阶段开始debug1: Offering public key: ... RSA SHA256:xxx表示客户端正在尝试某个公钥debug1: Server accepts key: ...表示服务端认这个公钥debug1: Authentication succeeded (publickey)就是成功标志。如果出现no mutual signature algorithm那是客户端和服务端在 RSA 签名算法上谈不拢常见于新服务端搭配旧客户端。针对这类兼容问题临时方案是在客户端~/.ssh/config里对该主机加一行Host legacy-host HostName 10.0.0.30 User deploy IdentityFile ~/.ssh/id_rsa_legacy PubkeyAcceptedAlgorithms ssh-rsa老版本 OpenSSH 里这个参数名是PubkeyAcceptedKeyTypes新版本改成了PubkeyAcceptedAlgorithms两个名字依据版本择一使用。要提醒的是加回ssh-rsa等于重新启用 SHA-1 签名安全性下降只适合过渡期内网使用正确做法是升级两端软件版本让它走rsa-sha2-256或rsa-sha2-512。5.3 多密钥、多环境与客户端配置管理手里密钥一多就不会再靠命令行传-i了。我把所有主机按环境分类写进~/.ssh/config生产、测试、个人服务器各用不同的私钥每个 Host 块里都加上IdentitiesOnly yes。这样做的直接好处是避免客户端按顺序乱试密钥触发服务端的认证次数限制。通常服务端的MaxAuthTries是 6客户端手里超过 6 个密钥时可能出现密钥明明正确却排不上队的情况。密钥文件命名我也建议规范起来比如id_rsa_prod_2024、id_rsa_test、id_rsa_gitlab注释字段同步写清楚。GitLab、GitHub 这类代码托管平台的部署密钥可以单独生成一对只用于拉取代码不要和服务器登录密钥混用万一某一边泄露了影响范围也能控制住。VSCode 远程开发走的是同一套 SSH 配置只要~/.ssh/config配好Remote-SSH 插件里直接选主机别名即可不用重复维护。5.4 批量场景下怎么高效分发公钥只有几台机器时手工加authorized_keys完全够用到了几十台甚至上百台就需要自动化手段。最直接的是写一个循环脚本for host in 10.0.0.21 10.0.0.22 10.0.0.23; do ssh-copy-id -i ~/.ssh/id_rsa_deploy.pub -o StrictHostKeyCheckingaccept-new deploy$host done更规范的方式是用 Ansible 的authorized_key模块它天然幂等重复执行不会产生重复行还能顺带管理exclusive、key_options等参数。一个简单的 playbook 长这样- hosts: linux_servers gather_facts: false tasks: - name: 分发部署公钥 ansible.posix.authorized_key: user: deploy state: present key: {{ lookup(file, ~/.ssh/id_rsa_deploy.pub) }} exclusive: false在龙蜥 8、Rocky 8、Ubuntu 22.04 这些主流系统上都验证过模块会自行处理目录创建和权限设置。要注意的是首次连接时的主机密钥确认可以在ansible.cfg里设置host_key_checking False或者提前用ssh-keyscan把主机密钥写入known_hosts后者更稳妥。批量分发之前务必确认目标机账户可用并且先在测试机跑通再推全量。5.5 安全收尾与密钥生命周期管理免密登录配好之后很多人会顺手把PasswordAuthentication关掉这确实能减少暴力破解的风险但前提是所有需要登录的账号都配好了密钥包括你自己的备用通道否则一旦密钥丢失就只能走控制台救援。我一般会保留一个受限制的密码登录账号或者保留云厂商的控制台入口作为最后的兜底。私钥的生命周期也需要管理。离职、转岗、设备丢失都应当及时从所有服务器的authorized_keys里删除对应公钥。定期用ssh-keygen -lf ~/.ssh/authorized_keys生成清单和设备台账比对一次是个性价比很高的习惯。有条件的话用 SSH 证书替代裸公钥分发把有效期写进证书里到期自动失效管理成本会进一步降低。至于密钥轮换建议至少一年换一次换的时候先加新公钥、验证通过、再删旧公钥整个过程在线完成不需要停服务。最后再分享一个我自己踩过的小坑有一次在一个启用了 SELinux 的龙蜥系统上部署authorized_keys内容、权限、属主全对就是登录不上日志里也没有明显提示。最后用ausearch -m avc -ts recent找到一条拒绝记录才确认是文件上下文的问题restorecon -Rv ~/.ssh之后立刻恢复。这类问题不常见但一旦遇上按权限、属主、SELinux、sshd 配置、客户端日志这个固定顺序排查基本能在十分钟内定位到原因。把公钥认证的原理想透之后这套排查路径就变成了肌肉记忆遇到再陌生的环境也不慌。
返回列表