
1. 为什么密钥登录值得你花十分钟折腾很多人第一次接触服务器远程管理都是靠账号密码走天下的。输个用户名敲个密码回车进去了。方便是真方便但方便的背后藏着一堆隐患。密码这东西短了容易被撞库长了你自己都记不住更麻烦的是只要密码泄露一次别人就能大摇大摆地登进你的机器而你往往等到出事才发现。密钥登录解决的正是这个核心痛点。它的原理不复杂你手里有一把私钥服务器上放一把公钥登录时服务器用公钥出一道只有对应私钥才能解开的“题”你答对了就放行。私钥始终留在你自己的机器上从不通过网络传输所以就算有人在链路上抓包也拿不到能登录的凭证。这比每次把密码明文或哈希发过去要安全得多。这篇文章面向的是刚拿到一台远程主机、想把手动输密码改成密钥自动登录的朋友也适合已经会用但没系统梳理过细节的人。我会从密钥对生成讲起一路走到服务端配置、权限设置、常见报错排查把每一步背后的道理都说清楚。你跟着做一遍基本就能把这套流程彻底吃透以后换机器、加设备都是几分钟的事。需要提前说明的是下面所有操作都基于常见的开源远程管理工具和主流发行版环境命令和路径在不同版本上可能略有差异但核心逻辑是通用的。遇到不一致的地方按你系统里的实际提示调整即可。2. 密钥对到底是怎么生成和分工的2.1 私钥与公钥的角色划分密钥登录的本质是一对非对称加密的钥匙。私钥相当于你家门锁的唯一一把实体钥匙绝对不能给别人公钥相当于锁芯的规格说明可以随便复制、随便公开。服务器上存的是公钥你的本地机器上存的是私钥。登录时服务器拿公钥加密一段随机数据发给你你的客户端用私钥解密后回传服务器验证通过就建立连接。这里有个常见的误解很多人以为公钥是“加密用的”私钥是“解密用的”所以把公钥放服务器、私钥放本地就对了。方向没错但更准确的理解是——这对钥匙互为验证关系谁加密谁解密取决于具体协议流程。你只需要记住一条铁律私钥永远不离开你的本地设备公钥放到目标服务器的指定位置。2.2 生成密钥对的实操命令与参数选择在本地终端里执行生成命令这是整个流程的第一步。以常见的密钥生成工具为例推荐使用更现代的算法它在安全性和性能上都比老算法更优ssh-keygen -t ed25519 -C your_emailexample.com逐段拆解一下这条命令。-t ed25519指定密钥类型ed25519 是目前公认安全性高、密钥短、生成快的一种算法-C后面跟的是注释通常填邮箱或用途说明方便你以后在服务器上看到这串公钥时知道它是谁的、干什么用的。这个注释不参与加密纯粹是给人看的标签。执行后系统会问你密钥保存路径默认是~/.ssh/id_ed25519。如果你只有一台服务器要管直接回车用默认路径就行。但如果你要管理多台机器、多个平台建议给每个用途单独命名比如~/.ssh/id_ed25519_web_server这样以后不会搞混。接着会问你要不要设置密码短语passphrase。这里我的建议是如果你本地机器有可靠的锁屏和磁盘加密可以不设图个方便如果本地环境不太可控强烈建议设一个。密码短语的作用是给私钥再加一层保护即使私钥文件被人拷走没有密码短语也用不了。生成完成后你会得到两个文件id_ed25519私钥和id_ed25519.pub公钥。私钥文件权限应该是 600也就是只有你自己能读写这个权限如果不对很多客户端会直接拒绝使用。公钥文件权限无所谓因为它本来就是要公开的。2.3 密钥长度与算法选择的经验判断有人会问用 RSA 行不行行但要注意长度。RSA 低于 2048 位已经不安全了推荐至少 4096 位。但 RSA 的问题是密钥长、生成慢、验证也慢同等安全强度下 ed25519 的密钥短得多性能也好得多。除非你的目标服务器版本非常老、不支持 ed25519否则优先选它。还有一种情况是你需要兼容一些老旧设备或特殊平台那就只能退回 RSA。这时候命令改成ssh-keygen -t rsa -b 4096 -C legacy_device_key-b 4096指定密钥长度。生成过程会慢几秒因为要算大素数这是正常现象别以为卡死了。3. 把公钥送上服务器的几种姿势3.1 用现成工具一键推送最省事的方式是用客户端自带的公钥复制工具。命令格式很简单ssh-copy-id -i ~/.ssh/id_ed25519.pub userhost这条命令背后做的事其实不神秘它通过你当前的密码登录方式连上服务器然后把公钥内容追加到服务器上~/.ssh/authorized_keys文件里同时帮你把相关目录和文件的权限设置好。-i参数指定你要推送的公钥文件后面跟目标用户和主机地址。但这里有个坑如果你的服务器改了默认端口ssh-copy-id需要额外指定端口参数否则会连不上。命令要写成ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 2222 userhost端口号按你实际情况替换。另外有些精简系统里没有预装这个工具那就得手动来。3.2 手动追加公钥的完整流程手动操作也不复杂分三步。第一步在本地读出公钥内容cat ~/.ssh/id_ed25519.pub你会看到一行以ssh-ed25519开头的长字符串后面跟着注释。整行复制下来。第二步登录服务器检查目标目录是否存在ls -la ~/.ssh/如果目录不存在先创建并设好权限mkdir -p ~/.ssh chmod 700 ~/.ssh第三步把公钥追加到授权文件里echo 你复制的公钥内容 ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys注意是追加而不是覆盖覆盖会把之前已有的公钥全冲掉如果你之前已经配过其他设备的密钥那就全废了。这个细节我见过太多人踩坑尤其是复制粘贴时手快一个符号之差结果把自己锁在外面。3.3 权限设置为什么这么重要远程管理工具对权限的检查近乎偏执这不是它故意刁难你而是安全设计。如果authorized_keys文件或.ssh目录对同组用户或其他用户可写那就意味着别人可以往里面塞自己的公钥等于把钥匙随便给人配。所以服务端会严格检查.ssh目录必须是 700authorized_keys必须是 600用户主目录不能对同组或其他用户可写。如果你登录时明明公钥放对了却还是被拒十有八九是权限问题。排查命令ls -ld ~ ~/.ssh ~/.ssh/authorized_keys输出里看每一行的权限位。主目录至少要是 755 或 700.ssh是 700authorized_keys是 600。不对就改chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chmod go-w ~最后一条是去掉主目录的同组和其他用户写权限很多人忽略这个结果怎么都登不上。4. 服务端配置的取舍与细节4.1 修改配置文件前必须做的备份服务端的远程管理服务有一个主配置文件通常在/etc/ssh/sshd_config。改这个文件之前一定要先备份sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak别嫌麻烦我见过改错一个参数导致服务起不来、自己又进不去机器的惨案。有备份大不了恢复回去重启服务没备份就只能去机房接显示器了。改完之后不要急着重启先用测试命令检查语法sudo sshd -t没有输出就说明语法没问题有报错会告诉你哪一行出了什么错按提示改就行。4.2 关键参数逐项说明配置文件里跟密钥登录相关的参数主要有这几个我逐个解释它们的作用和推荐值。PubkeyAuthentication yes这是密钥登录的总开关必须设为 yes。有些系统默认就是开的但确认一下没坏处。AuthorizedKeysFile .ssh/authorized_keys指定公钥文件的位置。默认值通常就是这个一般不用改。如果你想把公钥放到别的地方改这里但要注意路径是相对于用户主目录的。PasswordAuthentication no这个参数决定是否允许密码登录。强烈建议在确认密钥登录可用之后再改成 no。顺序很重要先确保密钥能登再关密码。反过来操作万一密钥没配好你就彻底进不去了。改这个参数是提升安全性的关键一步因为一旦关了密码登录暴力破解密码的攻击就完全失效了。PermitRootLogin prohibit-password控制 root 用户能否登录。推荐值是prohibit-password意思是 root 可以用密钥登录但不允许用密码。如果你根本不需要 root 远程登录设成no更彻底。千万别设成yes那等于把最高权限账号暴露给密码攻击。ChallengeResponseAuthentication no这个跟密码认证相关关掉可以减少一些交互式认证的入口。不同版本上参数名可能略有差异有的叫KbdInteractiveAuthentication按你系统里的实际名称来。改完这些保存文件再跑一次语法检查然后重启服务sudo systemctl restart sshd注意服务名在不同系统上可能是ssh而不是sshd用systemctl status确认一下。4.3 改完配置后的验证顺序重启服务后不要关闭当前已经登录的会话。新开一个终端窗口尝试用密钥登录ssh -i ~/.ssh/id_ed25519 userhost如果能直接进去说明密钥登录生效了。这时候再测试密码登录是否已经被禁用如果你改了PasswordAuthentication no尝试用密码登录应该被拒绝。两步都验证通过才算配置成功。保留那个旧会话是为了万一新配置有问题你还能从旧会话里改回来。这个“保留旧会话再验证”的习惯是我觉得整个流程里最值得养成的操作纪律。不管改什么远程配置都别把自己后路断了。5. 登录失败时的排查链路5.1 从客户端日志看起密钥登录失败客户端通常会给出比较模糊的提示比如“Permission denied (publickey)”。这时候加-v参数看详细过程ssh -v -i ~/.ssh/id_ed25519 userhost输出会显示客户端尝试了哪些认证方式、用了哪个密钥文件、服务器返回了什么。如果看到“Offering public key”之后被拒绝说明公钥没被服务器认可问题在服务端如果根本没尝试密钥说明客户端没找到私钥文件检查-i路径对不对。更详细的话可以用-vvv三个 v输出会非常啰嗦但能看清每一步的握手细节。一般排查到-v就够了。5.2 服务端日志才是真相所在客户端看到的信息有限真正的拒绝原因在服务端日志里。在服务器上查看sudo tail -f /var/log/auth.log不同发行版日志路径可能不同有的在/var/log/secure。用tail -f实时盯着然后在另一个窗口尝试登录日志里会打印出具体原因比如“Authentication refused: bad ownership or modes for file”这就明确告诉你权限不对“User not allowed because account is locked”说明账号被锁了。常见日志信息与对应原因我整理成表格方便对照日志提示关键词大概率原因处理方向bad ownership or modes目录或文件权限不对按第 3.3 节修正权限key not found公钥没放到正确位置检查 authorized_keys 路径和内容invalid format公钥内容被换行或截断重新完整复制一行公钥connection closed by authenticating user服务端主动断开检查 sshd_config 是否有额外限制no matching key exchange method算法不兼容调整客户端或服务端算法配置5.3 几个反直觉的坑第一个坑公钥复制时被自动换行。有些终端或编辑器会在长行里插入软换行你看着是一行粘贴进去变成了两行服务端解析就失败。解决办法是粘贴后用wc -l看行数一个公钥应该只占一行。第二个坑authorized_keys文件里有多余空行或注释格式不对。空行一般不影响但如果公钥前面多了空格、或者被引号包起来就会解析失败。确保每行以ssh-ed25519或ssh-rsa开头前面没有任何字符。第三个坑SELinux 或类似安全模块在拦截。有些系统开了强制访问控制即使文件权限对了安全上下文不对也会被拒。临时排查可以看日志里有没有avc: denied字样有的话需要调整安全上下文或临时设为宽容模式测试。这个属于进阶内容新手遇到概率不高但知道有这回事排查时不会钻牛角尖。6. 让日常使用更顺手的几个配置6.1 本地客户端配置文件简化登录命令每次登录都敲一长串ssh -i ~/.ssh/xxx userhost -p 端口太累。本地~/.ssh/config文件可以帮你把这些都存起来。格式如下Host myserver HostName 192.0.2.10 User deploy Port 2222 IdentityFile ~/.ssh/id_ed25519_web配好之后登录只需要ssh myserver所有参数自动带上。如果你管理多台机器这个文件能省下大量敲键盘的时间而且不容易记错端口和用户名。Host后面那个名字是你自己起的别名随便叫什么都行。6.2 用密钥代理管理密码短语如果你给私钥设了密码短语每次登录都要输一遍用久了也烦。密钥代理工具可以帮你在一段时间内缓存解密后的私钥避免重复输入。启动代理并添加私钥eval $(ssh-agent -s) ssh-add ~/.ssh/id_ed25519执行ssh-add时会让你输一次密码短语之后在这个会话里再用这个私钥就不需要再输了。很多桌面环境会自动启动代理你只需要ssh-add一下就行。注意代理缓存是跟会话绑定的重启或注销后就失效了这是安全设计不是 bug。6.3 多设备密钥的管理思路如果你有多台本地设备都要连同一台服务器有两种做法。一种是每台设备生成自己的密钥对把各自的公钥都追加到服务器的authorized_keys里。这样做的好处是权限清晰哪台设备要撤销直接删对应那一行公钥就行不影响其他设备。另一种是所有设备共用同一对密钥方便但风险集中一旦私钥泄露所有设备都得换。我的建议是前者每台设备独立密钥。虽然多几步操作但管理起来清楚得多。给每台设备的公钥注释里写清楚设备名或用途比如-C laptop-2024、-C desktop-office以后在authorized_keys里一眼就能认出哪行是哪台。7. 我踩过的几个真实坑和应对第一次配密钥登录的时候我犯了个经典错误先把密码登录关了才想起来测试密钥。结果密钥因为权限问题没生效密码又被禁了整个人卡在门外。最后是找服务商的控制台紧急登录进去改回来的。从那以后我养成了一个习惯任何可能切断远程访问的改动都先开两个会话一个用来改一个用来验证改完确认无误再关旧会话。还有一个坑是公钥内容复制不全。终端里cat出来的公钥很长我用鼠标选中复制的时候末尾几个字符没选上粘贴进去的公钥是残缺的。服务端日志只报“invalid format”不告诉你缺在哪。后来我改用ssh-copy-id工具或者用pbcopy ~/.ssh/id_ed25519.pub这种直接管道复制的方式避免手动选择出错。第三个坑跟权限有关。有一次我把.ssh目录设成了 755觉得“反正里面文件是 600 就行”。结果服务端检查时发现目录对同组用户可读可进入虽然不能写但它依然拒绝。后来查文档才知道.ssh目录必须是 700不能有任何组或其他用户的权限位。这个要求比我想象的严格但理解了安全逻辑之后就觉得很合理——目录可进入意味着别人能列出里面的文件名虽然读不到内容但信息泄露也是泄露。最后一个经验是关于注释的。给密钥加注释时别写太敏感的信息。注释会出现在服务器的authorized_keys文件里任何能读这个文件的人包括你自己以后排查时都能看到。写个设备名或用途就够了别把邮箱密码之类的往上写。这套流程走下来从生成密钥到服务端配置再到排查基本覆盖了密钥登录的全部关键环节。你第一次配可能要花二十分钟配顺了之后换新机器就是五分钟的事。核心就三句话私钥不离身公钥放对位置权限设对。剩下的都是围绕这三句话的细节展开。